| package context |
| |
| import ( |
| "context" |
| "fmt" |
| "runtime" |
| |
| "github.com/sirupsen/logrus" |
| ) |
| |
| // Logger provides a leveled-logging interface. |
| type Logger interface { |
| // standard logger methods |
| Print(args ...interface{}) |
| Printf(format string, args ...interface{}) |
| Println(args ...interface{}) |
| |
| Fatal(args ...interface{}) |
| Fatalf(format string, args ...interface{}) |
| Fatalln(args ...interface{}) |
| |
| Panic(args ...interface{}) |
| Panicf(format string, args ...interface{}) |
| Panicln(args ...interface{}) |
| |
| // Leveled methods, from logrus |
| Debug(args ...interface{}) |
| Debugf(format string, args ...interface{}) |
| Debugln(args ...interface{}) |
| |
| Error(args ...interface{}) |
| Errorf(format string, args ...interface{}) |
| Errorln(args ...interface{}) |
| |
| Info(args ...interface{}) |
| Infof(format string, args ...interface{}) |
| Infoln(args ...interface{}) |
| |
| Warn(args ...interface{}) |
| Warnf(format string, args ...interface{}) |
| Warnln(args ...interface{}) |
| |
| WithError(err error) *logrus.Entry |
| } |
| |
| type loggerKey struct{} |
| |
| // WithLogger creates a new context with provided logger. |
| func WithLogger(ctx context.Context, logger Logger) context.Context { |
| return context.WithValue(ctx, loggerKey{}, logger) |
| } |
| |
| // GetLoggerWithField returns a logger instance with the specified field key |
| // and value without affecting the context. Extra specified keys will be |
| // resolved from the context. |
| func GetLoggerWithField(ctx context.Context, key, value interface{}, keys ...interface{}) Logger { |
| return getLogrusLogger(ctx, keys...).WithField(fmt.Sprint(key), value) |
| } |
| |
| // GetLoggerWithFields returns a logger instance with the specified fields |
| // without affecting the context. Extra specified keys will be resolved from |
| // the context. |
| func GetLoggerWithFields(ctx context.Context, fields map[interface{}]interface{}, keys ...interface{}) Logger { |
| // must convert from interface{} -> interface{} to string -> interface{} for logrus. |
| lfields := make(logrus.Fields, len(fields)) |
| for key, value := range fields { |
| lfields[fmt.Sprint(key)] = value |
| } |
| |
| return getLogrusLogger(ctx, keys...).WithFields(lfields) |
| } |
| |
| // GetLogger returns the logger from the current context, if present. If one |
| // or more keys are provided, they will be resolved on the context and |
| // included in the logger. While context.Value takes an interface, any key |
| // argument passed to GetLogger will be passed to fmt.Sprint when expanded as |
| // a logging key field. If context keys are integer constants, for example, |
| // its recommended that a String method is implemented. |
| func GetLogger(ctx context.Context, keys ...interface{}) Logger { |
| return getLogrusLogger(ctx, keys...) |
| } |
| |
| // GetLogrusLogger returns the logrus logger for the context. If one more keys |
| // are provided, they will be resolved on the context and included in the |
| // logger. Only use this function if specific logrus functionality is |
| // required. |
| func getLogrusLogger(ctx context.Context, keys ...interface{}) *logrus.Entry { |
| var logger *logrus.Entry |
| |
| // Get a logger, if it is present. |
| loggerInterface := ctx.Value(loggerKey{}) |
| if loggerInterface != nil { |
| if lgr, ok := loggerInterface.(*logrus.Entry); ok { |
| logger = lgr |
| } |
| } |
| |
| if logger == nil { |
| fields := logrus.Fields{} |
| |
| // Fill in the instance id, if we have it. |
| instanceID := ctx.Value("instance.id") |
| if instanceID != nil { |
| fields["instance.id"] = instanceID |
| } |
| |
| fields["go.version"] = runtime.Version() |
| // If no logger is found, just return the standard logger. |
| logger = logrus.StandardLogger().WithFields(fields) |
| } |
| |
| fields := logrus.Fields{} |
| for _, key := range keys { |
| v := ctx.Value(key) |
| if v != nil { |
| fields[fmt.Sprint(key)] = v |
| } |
| } |
| |
| return logger.WithFields(fields) |
| } |