2015-02-05 22:56:50 +01:00
|
|
|
package context
|
|
|
|
|
|
|
|
import (
|
2017-08-12 00:31:16 +02:00
|
|
|
"context"
|
2015-02-05 22:56:50 +01:00
|
|
|
"fmt"
|
2017-08-12 00:31:16 +02:00
|
|
|
"runtime"
|
2015-02-05 22:56:50 +01:00
|
|
|
|
2017-06-23 21:45:04 +02:00
|
|
|
"github.com/sirupsen/logrus"
|
2015-02-05 22:56:50 +01:00
|
|
|
)
|
|
|
|
|
|
|
|
// 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{})
|
2017-11-15 02:21:36 +01:00
|
|
|
|
|
|
|
WithError(err error) *logrus.Entry
|
2015-02-05 22:56:50 +01:00
|
|
|
}
|
|
|
|
|
2017-08-12 00:31:16 +02:00
|
|
|
type loggerKey struct{}
|
|
|
|
|
2015-02-05 22:56:50 +01:00
|
|
|
// WithLogger creates a new context with provided logger.
|
2017-08-12 00:31:16 +02:00
|
|
|
func WithLogger(ctx context.Context, logger Logger) context.Context {
|
|
|
|
return context.WithValue(ctx, loggerKey{}, logger)
|
2015-02-05 22:56:50 +01:00
|
|
|
}
|
|
|
|
|
2015-04-02 01:27:24 +02:00
|
|
|
// 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.
|
2017-08-12 00:31:16 +02:00
|
|
|
func GetLoggerWithField(ctx context.Context, key, value interface{}, keys ...interface{}) Logger {
|
2015-04-02 01:27:24 +02:00
|
|
|
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.
|
2017-08-12 00:31:16 +02:00
|
|
|
func GetLoggerWithFields(ctx context.Context, fields map[interface{}]interface{}, keys ...interface{}) Logger {
|
2015-09-11 05:40:01 +02:00
|
|
|
// 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)
|
2015-04-02 01:27:24 +02:00
|
|
|
}
|
|
|
|
|
2015-02-05 22:56:50 +01:00
|
|
|
// 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.
|
2017-08-12 00:31:16 +02:00
|
|
|
func GetLogger(ctx context.Context, keys ...interface{}) Logger {
|
2015-02-05 22:56:50 +01:00
|
|
|
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.
|
2017-08-12 00:31:16 +02:00
|
|
|
func getLogrusLogger(ctx context.Context, keys ...interface{}) *logrus.Entry {
|
2015-02-05 22:56:50 +01:00
|
|
|
var logger *logrus.Entry
|
|
|
|
|
|
|
|
// Get a logger, if it is present.
|
2017-08-12 00:31:16 +02:00
|
|
|
loggerInterface := ctx.Value(loggerKey{})
|
2015-02-05 22:56:50 +01:00
|
|
|
if loggerInterface != nil {
|
|
|
|
if lgr, ok := loggerInterface.(*logrus.Entry); ok {
|
|
|
|
logger = lgr
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if logger == nil {
|
2015-09-11 05:41:58 +02:00
|
|
|
fields := logrus.Fields{}
|
|
|
|
|
|
|
|
// Fill in the instance id, if we have it.
|
|
|
|
instanceID := ctx.Value("instance.id")
|
|
|
|
if instanceID != nil {
|
|
|
|
fields["instance.id"] = instanceID
|
|
|
|
}
|
|
|
|
|
2015-10-06 00:28:22 +02:00
|
|
|
fields["go.version"] = runtime.Version()
|
2015-02-05 22:56:50 +01:00
|
|
|
// If no logger is found, just return the standard logger.
|
2015-09-11 05:41:58 +02:00
|
|
|
logger = logrus.StandardLogger().WithFields(fields)
|
2015-02-05 22:56:50 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
fields := logrus.Fields{}
|
|
|
|
for _, key := range keys {
|
|
|
|
v := ctx.Value(key)
|
|
|
|
if v != nil {
|
|
|
|
fields[fmt.Sprint(key)] = v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return logger.WithFields(fields)
|
|
|
|
}
|