9c88801a12
Back in the before time, the best practices surrounding usage of Context weren't quite worked out. We defined our own type to make usage easier. As this packaged was used elsewhere, it make it more and more challenging to integrate with the forked `Context` type. Now that it is available in the standard library, we can just use that one directly. To make usage more consistent, we now use `dcontext` when referring to the distribution context package. Signed-off-by: Stephen J Day <stephen.day@docker.com>
119 lines
3.6 KiB
Go
119 lines
3.6 KiB
Go
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{})
|
|
}
|
|
|
|
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)
|
|
}
|