log: improve module-oriented logging
To improve the output of module logging, we now include a path that represents the modules that a context has passed through. This makes it easy to tell if a log line came from a particular module hierarchy. A helper function, `WithModule`, provides an easy way to mark a context with a module and inject that module into the logger. Signed-off-by: Stephen J Day <stephen.day@docker.com>
This commit is contained in:
parent
41aadb3fb0
commit
5288d8f9fe
1 changed files with 45 additions and 1 deletions
|
@ -1,6 +1,8 @@
|
||||||
package log
|
package log
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"path"
|
||||||
|
|
||||||
"github.com/Sirupsen/logrus"
|
"github.com/Sirupsen/logrus"
|
||||||
"golang.org/x/net/context"
|
"golang.org/x/net/context"
|
||||||
)
|
)
|
||||||
|
@ -16,7 +18,10 @@ var (
|
||||||
L = logrus.NewEntry(logrus.StandardLogger())
|
L = logrus.NewEntry(logrus.StandardLogger())
|
||||||
)
|
)
|
||||||
|
|
||||||
type loggerKey struct{}
|
type (
|
||||||
|
loggerKey struct{}
|
||||||
|
moduleKey struct{}
|
||||||
|
)
|
||||||
|
|
||||||
// WithLogger returns a new context with the provided logger. Use in
|
// WithLogger returns a new context with the provided logger. Use in
|
||||||
// combination with logger.WithField(s) for great effect.
|
// combination with logger.WithField(s) for great effect.
|
||||||
|
@ -35,3 +40,42 @@ func GetLogger(ctx context.Context) *logrus.Entry {
|
||||||
|
|
||||||
return logger.(*logrus.Entry)
|
return logger.(*logrus.Entry)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// WithModule adds the module to the context, appending it with a slash if a
|
||||||
|
// module already exists. A module is just an roughly correlated defined by the
|
||||||
|
// call tree for a given context.
|
||||||
|
//
|
||||||
|
// As an example, we might have a "node" module already part of a context. If
|
||||||
|
// this function is called with "tls", the new value of module will be
|
||||||
|
// "node/tls".
|
||||||
|
//
|
||||||
|
// Modules represent the call path. If the new module and last module are the
|
||||||
|
// same, a new module entry will not be created. If the new module and old
|
||||||
|
// older module are the same but separated by other modules, the cycle will be
|
||||||
|
// represented by the module path.
|
||||||
|
func WithModule(ctx context.Context, module string) context.Context {
|
||||||
|
parent := GetModulePath(ctx)
|
||||||
|
|
||||||
|
if parent != "" {
|
||||||
|
// don't re-append module when module is the same.
|
||||||
|
if path.Base(parent) == module {
|
||||||
|
return ctx
|
||||||
|
}
|
||||||
|
|
||||||
|
module = path.Join(parent, module)
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx = WithLogger(ctx, GetLogger(ctx).WithField("module", module))
|
||||||
|
return context.WithValue(ctx, moduleKey{}, module)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetModulePath returns the module path for the provided context. If no module
|
||||||
|
// is set, an empty string is returned.
|
||||||
|
func GetModulePath(ctx context.Context) string {
|
||||||
|
module := ctx.Value(moduleKey{})
|
||||||
|
if module == nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return module.(string)
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue