logger.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package context
  2. import (
  3. "fmt"
  4. "github.com/Sirupsen/logrus"
  5. "runtime"
  6. )
  7. // Logger provides a leveled-logging interface.
  8. type Logger interface {
  9. // standard logger methods
  10. Print(args ...interface{})
  11. Printf(format string, args ...interface{})
  12. Println(args ...interface{})
  13. Fatal(args ...interface{})
  14. Fatalf(format string, args ...interface{})
  15. Fatalln(args ...interface{})
  16. Panic(args ...interface{})
  17. Panicf(format string, args ...interface{})
  18. Panicln(args ...interface{})
  19. // Leveled methods, from logrus
  20. Debug(args ...interface{})
  21. Debugf(format string, args ...interface{})
  22. Debugln(args ...interface{})
  23. Error(args ...interface{})
  24. Errorf(format string, args ...interface{})
  25. Errorln(args ...interface{})
  26. Info(args ...interface{})
  27. Infof(format string, args ...interface{})
  28. Infoln(args ...interface{})
  29. Warn(args ...interface{})
  30. Warnf(format string, args ...interface{})
  31. Warnln(args ...interface{})
  32. }
  33. // WithLogger creates a new context with provided logger.
  34. func WithLogger(ctx Context, logger Logger) Context {
  35. return WithValue(ctx, "logger", logger)
  36. }
  37. // GetLoggerWithField returns a logger instance with the specified field key
  38. // and value without affecting the context. Extra specified keys will be
  39. // resolved from the context.
  40. func GetLoggerWithField(ctx Context, key, value interface{}, keys ...interface{}) Logger {
  41. return getLogrusLogger(ctx, keys...).WithField(fmt.Sprint(key), value)
  42. }
  43. // GetLoggerWithFields returns a logger instance with the specified fields
  44. // without affecting the context. Extra specified keys will be resolved from
  45. // the context.
  46. func GetLoggerWithFields(ctx Context, fields map[interface{}]interface{}, keys ...interface{}) Logger {
  47. // must convert from interface{} -> interface{} to string -> interface{} for logrus.
  48. lfields := make(logrus.Fields, len(fields))
  49. for key, value := range fields {
  50. lfields[fmt.Sprint(key)] = value
  51. }
  52. return getLogrusLogger(ctx, keys...).WithFields(lfields)
  53. }
  54. // GetLogger returns the logger from the current context, if present. If one
  55. // or more keys are provided, they will be resolved on the context and
  56. // included in the logger. While context.Value takes an interface, any key
  57. // argument passed to GetLogger will be passed to fmt.Sprint when expanded as
  58. // a logging key field. If context keys are integer constants, for example,
  59. // its recommended that a String method is implemented.
  60. func GetLogger(ctx Context, keys ...interface{}) Logger {
  61. return getLogrusLogger(ctx, keys...)
  62. }
  63. // GetLogrusLogger returns the logrus logger for the context. If one more keys
  64. // are provided, they will be resolved on the context and included in the
  65. // logger. Only use this function if specific logrus functionality is
  66. // required.
  67. func getLogrusLogger(ctx Context, keys ...interface{}) *logrus.Entry {
  68. var logger *logrus.Entry
  69. // Get a logger, if it is present.
  70. loggerInterface := ctx.Value("logger")
  71. if loggerInterface != nil {
  72. if lgr, ok := loggerInterface.(*logrus.Entry); ok {
  73. logger = lgr
  74. }
  75. }
  76. if logger == nil {
  77. fields := logrus.Fields{}
  78. // Fill in the instance id, if we have it.
  79. instanceID := ctx.Value("instance.id")
  80. if instanceID != nil {
  81. fields["instance.id"] = instanceID
  82. }
  83. fields["go.version"] = runtime.Version()
  84. // If no logger is found, just return the standard logger.
  85. logger = logrus.StandardLogger().WithFields(fields)
  86. }
  87. fields := logrus.Fields{}
  88. for _, key := range keys {
  89. v := ctx.Value(key)
  90. if v != nil {
  91. fields[fmt.Sprint(key)] = v
  92. }
  93. }
  94. return logger.WithFields(fields)
  95. }