diff --git a/event.go b/event.go index 56de6061..935a69ca 100644 --- a/event.go +++ b/event.go @@ -1,7 +1,9 @@ package zerolog import ( + "bytes" "context" + "encoding/json" "fmt" "net" "os" @@ -828,3 +830,21 @@ func (e *Event) MACAddr(key string, ha net.HardwareAddr) *Event { e.buf = enc.AppendMACAddr(enc.AppendKey(e.buf, key), ha) return e } + +// GetMetadata returns the JSON decoded metadata of the event. Please note that the metadata might not be mapped to their original field type as JSON decoder maps numbers to float64, etc. +func (e *Event) GetMetadata() (map[string]interface{}, error) { + if e == nil { + return nil, nil + } + + eventFields := make(map[string]interface{}) + buffer := bytes.TrimSpace(e.buf) + // If `Msg()` was not called the buffer will be missing the closing curly brace + if !bytes.HasSuffix(buffer, []byte("}")) { + buffer = append(buffer, '}') + } + if err := json.Unmarshal(buffer, &eventFields); err != nil { + return nil, err + } + return eventFields, nil +} diff --git a/event_test.go b/event_test.go index e7cf4250..53081f04 100644 --- a/event_test.go +++ b/event_test.go @@ -1,3 +1,4 @@ +//go:build !binary_log // +build !binary_log package zerolog @@ -63,3 +64,63 @@ func TestEvent_EmbedObjectWithNil(t *testing.T) { t.Errorf("Event.EmbedObject() = %q, want %q", got, want) } } + +func TestEvent_GetMetadata(t *testing.T) { + type testCase struct { + name string + e *Event + message string + want map[string]interface{} + } + + testCases := []testCase{ + { + name: "event without message", + e: newEvent(nil, DebugLevel).Str("foo", "bar").Float64("n", 42), + want: map[string]interface{}{ + "foo": "bar", + "n": float64(42), + }, + }, + { + name: "event without message and integer", + e: newEvent(nil, DebugLevel).Str("foo", "bar").Int("n", 42), + want: map[string]interface{}{ + "foo": "bar", + "n": float64(42), + }, + }, + { + name: "event with message", + e: newEvent(nil, DebugLevel).Str("foo", "bar").Float64("n", 42), + message: "test", + want: map[string]interface{}{ + "foo": "bar", + "n": float64(42), + "message": "test", + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + if tc.message != "" { + tc.e.Msg(tc.message) + } + got, err := tc.e.GetMetadata() + if err != nil { + t.Error(err) + } + + if len(got) != len(tc.want) { + t.Errorf("Event.GetMetadata() = %v, want %v", len(got), len(tc.want)) + } + for k, v := range tc.want { + if got[k] != v { + t.Errorf("Event.GetMetadata() = %v, want %v", got[k], v) + } + } + }) + + } +}