logger.go 2.4 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182
  1. package logging
  2. import (
  3. "context"
  4. "io"
  5. "log"
  6. )
  7. // Classification is the type of the log entry's classification name.
  8. type Classification string
  9. // Set of standard classifications that can be used by clients and middleware
  10. const (
  11. Warn Classification = "WARN"
  12. Debug Classification = "DEBUG"
  13. )
  14. // Logger is an interface for logging entries at certain classifications.
  15. type Logger interface {
  16. // Logf is expected to support the standard fmt package "verbs".
  17. Logf(classification Classification, format string, v ...interface{})
  18. }
  19. // LoggerFunc is a wrapper around a function to satisfy the Logger interface.
  20. type LoggerFunc func(classification Classification, format string, v ...interface{})
  21. // Logf delegates the logging request to the wrapped function.
  22. func (f LoggerFunc) Logf(classification Classification, format string, v ...interface{}) {
  23. f(classification, format, v...)
  24. }
  25. // ContextLogger is an optional interface a Logger implementation may expose that provides
  26. // the ability to create context aware log entries.
  27. type ContextLogger interface {
  28. WithContext(context.Context) Logger
  29. }
  30. // WithContext will pass the provided context to logger if it implements the ContextLogger interface and return the resulting
  31. // logger. Otherwise the logger will be returned as is. As a special case if a nil logger is provided, a Nop logger will
  32. // be returned to the caller.
  33. func WithContext(ctx context.Context, logger Logger) Logger {
  34. if logger == nil {
  35. return Nop{}
  36. }
  37. cl, ok := logger.(ContextLogger)
  38. if !ok {
  39. return logger
  40. }
  41. return cl.WithContext(ctx)
  42. }
  43. // Nop is a Logger implementation that simply does not perform any logging.
  44. type Nop struct{}
  45. // Logf simply returns without performing any action
  46. func (n Nop) Logf(Classification, string, ...interface{}) {
  47. return
  48. }
  49. // StandardLogger is a Logger implementation that wraps the standard library logger, and delegates logging to it's
  50. // Printf method.
  51. type StandardLogger struct {
  52. Logger *log.Logger
  53. }
  54. // Logf logs the given classification and message to the underlying logger.
  55. func (s StandardLogger) Logf(classification Classification, format string, v ...interface{}) {
  56. if len(classification) != 0 {
  57. format = string(classification) + " " + format
  58. }
  59. s.Logger.Printf(format, v...)
  60. }
  61. // NewStandardLogger returns a new StandardLogger
  62. func NewStandardLogger(writer io.Writer) *StandardLogger {
  63. return &StandardLogger{
  64. Logger: log.New(writer, "SDK ", log.LstdFlags),
  65. }
  66. }