From 3f54be87164ba1c4dd94433c9fb36f6e82aec33e Mon Sep 17 00:00:00 2001 From: Olivier Poitrey Date: Sat, 20 May 2017 00:22:37 -0700 Subject: [PATCH] Improve context.Context logging --- README.md | 19 ++++++++++++++++--- ctx.go | 18 +++++++++++++----- ctx_test.go | 16 +++++----------- event.go | 2 +- log/log.go | 7 +++++++ 5 files changed, 42 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index f4f9783..8edbeda 100644 --- a/README.md +++ b/README.md @@ -190,6 +190,16 @@ sampled.Info().Msg("will be logged every 10 messages") // Output: {"time":1494567715,"sample":10,"message":"will be logged every 10 messages"} ``` +### Pass a sub-logger by context + +```go +ctx := log.With("component", "module").Logger().FromContext(ctx) + +log.Ctx(ctx).Info().Msg("hello world") + +// Output: {"component":"module","level":"info","message":"hello world"} +``` + ## Global Settings Some settings can be changed and will by applied to all loggers: @@ -202,7 +212,7 @@ Some settings can be changed and will by applied to all loggers: * `zerolog.MessageFieldName`: Can be set to customize message field name. * `zerolog.ErrorFieldName`: Can be set to customize `Err` field name. * `zerolog.SampleFieldName`: Can be set to customize the field name added when sampling is enabled. -* `zerolog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. +* `zerolog.TimeFieldFormat`: Can be set to customize `Time` field value formatting. If set with an empty string, times are formated as UNIX timestamp. ## Field Types @@ -216,7 +226,10 @@ Some settings can be changed and will by applied to all loggers: ### Advanced Fields -* `Timestamp`: Insert UNIX timestamp field with `zerolog.TimestampFieldName` field name. -* `Time`: Add a field with the time formated with the `zerolog.TimeFieldFormat`. * `Err`: Takes an `error` and render it as a string using the `zerolog.ErrorFieldName` field name. +* `Timestamp`: Insert a timestamp field with `zerolog.TimestampFieldName` field name and formatted using `zerolog.TimeFieldFormat`. +* `Time`: Adds a field with the time formated with the `zerolog.TimeFieldFormat`. +* `Dur`: Adds a field with a `time.Duration` formatted as a `float`. For `int` value, use `DurInt`. +* `Dict`: Adds a sub-key/value as a field of the event. +* `Interface`: Uses reflection to marshal the type. diff --git a/ctx.go b/ctx.go index d5616bc..4abf062 100644 --- a/ctx.go +++ b/ctx.go @@ -1,6 +1,11 @@ package zerolog -import "context" +import ( + "context" + "io/ioutil" +) + +var disabledLogger = New(ioutil.Discard).Level(Disabled) type ctxKey struct{} @@ -9,8 +14,11 @@ func (l Logger) WithContext(ctx context.Context) context.Context { return context.WithValue(ctx, ctxKey{}, l) } -// FromContext returns the Logger associated with the ctx. -func FromContext(ctx context.Context) (l Logger, ok bool) { - l, ok = ctx.Value(ctxKey{}).(Logger) - return +// Ctx returns the Logger associated with the ctx. If no logger +// is associated, a disabled logger is returned. +func Ctx(ctx context.Context) Logger { + if l, ok := ctx.Value(ctxKey{}).(Logger); ok { + return l + } + return disabledLogger } diff --git a/ctx_test.go b/ctx_test.go index 770e670..dc9943f 100644 --- a/ctx_test.go +++ b/ctx_test.go @@ -10,19 +10,13 @@ import ( func TestCtx(t *testing.T) { log := New(ioutil.Discard) ctx := log.WithContext(context.Background()) - log2, ok := FromContext(ctx) - if !ok { - t.Error("Expected ok=true from FromContext") - } + log2 := Ctx(ctx) if !reflect.DeepEqual(log, log2) { - t.Error("FromContext did not return the expected logger") + t.Error("Ctx did not return the expected logger") } - log2, ok = FromContext(context.Background()) - if ok { - t.Error("Expected ok=false from FromContext") - } - if !reflect.DeepEqual(log2, Logger{}) { - t.Error("FromContext did not return the expected logger") + log2 = Ctx(context.Background()) + if !reflect.DeepEqual(log2, disabledLogger) { + t.Error("Ctx did not return the expected logger") } } diff --git a/event.go b/event.go index 6c8fb18..91bff3a 100644 --- a/event.go +++ b/event.go @@ -89,7 +89,7 @@ func (e *Event) Msgf(format string, v ...interface{}) (n int, err error) { return e.write() } -// Dict adds the field key with a dict to the *Event context. +// Dict adds the field key with a dict to the event context. // Use zerolog.Dict() to create the dictionary. func (e *Event) Dict(key string, dict *Event) *Event { if !e.enabled { diff --git a/log/log.go b/log/log.go index c516dd0..a478596 100644 --- a/log/log.go +++ b/log/log.go @@ -2,6 +2,7 @@ package log import ( + "context" "os" "github.com/rs/zerolog" @@ -76,3 +77,9 @@ func Panic() *zerolog.Event { func Log() *zerolog.Event { return Logger.Log() } + +// Ctx returns the Logger associated with the ctx. If no logger +// is associated, a disabled logger is returned. +func Ctx(ctx context.Context) zerolog.Logger { + return zerolog.Ctx(ctx) +}