diff --git a/README.md b/README.md index 9610d35..90cbd6c 100644 --- a/README.md +++ b/README.md @@ -96,9 +96,21 @@ if e := log.Debug(); e.Enabled() { e.Str("foo": value).Msg("some debug message") } -// Output: {"level":"info","time":1494567715,"routed message"} +// Output: {"level":"info","time":1494567715,"message":"routed message"} ``` +### Sub dictionary + +```go +log.Info(). + Str("foo", "bar"). + Dict("dict", zerolog.Dict(). + Str("bar", "baz"). + Int("n", 1) + ).Msg("hello world") + +// Output: {"level":"info","time":1494567715,"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"} +``` ### Customize automatic field names diff --git a/context.go b/context.go index e4e73e8..cdd7fff 100644 --- a/context.go +++ b/context.go @@ -25,6 +25,12 @@ func (c Context) append(f field) Context { } } +// Dict adds the field key with the dict to the logger context. +func (c Context) Dict(key string, dict Event) Context { + dict.buf.WriteByte('}') + return c.append(fRaw(key, dict.buf.String())) +} + // Str adds the field key with val as a string to the logger context. func (c Context) Str(key, val string) Context { return c.append(fStr(key, val)) diff --git a/event.go b/event.go index c345631..d0bcd2f 100644 --- a/event.go +++ b/event.go @@ -3,6 +3,8 @@ package zerolog import ( "bytes" "fmt" + "io" + "io/ioutil" "sync" "time" ) @@ -101,6 +103,27 @@ 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. +// Use zerolog.Dict() to create the dictionary. +func (e Event) Dict(key string, dict Event) Event { + if !e.enabled { + return e + } + if e.buf.Len() > 1 { + e.buf.WriteByte(',') + } + io.Copy(e.buf, dict.buf) + e.buf.WriteByte('}') + return e +} + +// Dict creates an Event to be used with the event.Dict method. +// Call usual field methods like Str, Int etc to add fields to this +// event and give it as argument the event.Dict method. +func Dict() Event { + return newEvent(levelWriterAdapter{ioutil.Discard}, 0, true) +} + // Str adds the field key with val as a string to the event context. func (e Event) Str(key, val string) Event { if !e.enabled { diff --git a/field.go b/field.go index e2f8303..ec9940b 100644 --- a/field.go +++ b/field.go @@ -134,5 +134,8 @@ func fTimestamp() field { func fTime(key string, t time.Time) field { return field{key, quotedFieldMode, t.Format(TimeFieldFormat), nil} - +} + +func fRaw(key string, raw string) field { + return field{key, rawFieldMode, raw, nil} } diff --git a/log_example_test.go b/log_example_test.go index 27e19f3..22b0e6a 100644 --- a/log_example_test.go +++ b/log_example_test.go @@ -99,3 +99,30 @@ func ExampleLogger_Log() { // Output: {"foo":"bar","bar":"baz"} } + +func ExampleEvent_Dict() { + log := zerolog.New(os.Stdout) + + log.Log(). + Str("foo", "bar"). + Dict("dict", zerolog.Dict(). + Str("bar", "baz"). + Int("n", 1), + ). + Msg("hello world") + + // Output: {"foo":"bar",{"bar":"baz","n":1},"message":"hello world"} +} + +func ExampleContext_Dict() { + log := zerolog.New(os.Stdout).With(). + Str("foo", "bar"). + Dict("dict", zerolog.Dict(). + Str("bar", "baz"). + Int("n", 1), + ).Logger() + + log.Log().Msg("hello world") + + // Output: {"foo":"bar","dict":{"bar":"baz","n":1},"message":"hello world"} +} diff --git a/log_test.go b/log_test.go index 5ceb779..c253ea5 100644 --- a/log_test.go +++ b/log_test.go @@ -87,7 +87,7 @@ func TestWith(t *testing.T) { Uint8("uint8", 7). Uint16("uint16", 8). Uint32("uint32", 9). - Uint32("uint64", 10). + Uint64("uint64", 10). Float32("float32", 11). Float64("float64", 12). Time("time", time.Time{}). @@ -114,7 +114,7 @@ func TestFields(t *testing.T) { Uint8("uint8", 7). Uint16("uint16", 8). Uint32("uint32", 9). - Uint32("uint64", 10). + Uint64("uint64", 10). Float32("float32", 11). Float64("float64", 12). Time("time", time.Time{}). @@ -140,7 +140,7 @@ func TestFieldsDisabled(t *testing.T) { Uint8("uint8", 7). Uint16("uint16", 8). Uint32("uint32", 9). - Uint32("uint64", 10). + Uint64("uint64", 10). Float32("float32", 11). Float64("float64", 12). Time("time", time.Time{}).