diff --git a/bridges/otelzap/encoder.go b/bridges/otelzap/encoder.go index eed14b0798f..77219cbc350 100644 --- a/bridges/otelzap/encoder.go +++ b/bridges/otelzap/encoder.go @@ -4,6 +4,7 @@ package otelzap // import "go.opentelemetry.io/contrib/bridges/otelzap" import ( + "encoding/json" "time" "go.uber.org/zap/zapcore" @@ -19,7 +20,8 @@ var ( // objectEncoder implements zapcore.ObjectEncoder. // It encodes given fields to OTel key-values. type objectEncoder struct { - kv []log.KeyValue + kv []log.KeyValue + reflectval log.Value } // nolint:unused @@ -93,11 +95,23 @@ func (m *objectEncoder) AddUint64(k string, v uint64) { }) } -// TODO. +// AddReflected converts all non-primitive type to JSON string. func (m *objectEncoder) AddReflected(k string, v interface{}) error { + enc := json.NewEncoder(m) + if err := enc.Encode(v); err != nil { + return err + } + m.AddString(k, m.reflectval.AsString()) return nil } +// Implements io.Writer to which json encoder writes to. +// Used by [AddReflected]. +func (m *objectEncoder) Write(p []byte) (n int, err error) { + m.reflectval = log.StringValue(string(p)) + return len(p), nil +} + // OpenNamespace opens an isolated namespace where all subsequent fields will // be added. func (m *objectEncoder) OpenNamespace(k string) { @@ -179,7 +193,15 @@ func (a *arrayEncoder) AppendObject(v zapcore.ObjectMarshaler) error { // TODO. func (a *arrayEncoder) AppendReflected(v interface{}) error { - return nil + enc := json.NewEncoder(a) + return enc.Encode(v) +} + +// Implements io.Writer to which json encoder writes to. +// Used by [AppendReflected]. +func (a *arrayEncoder) Write(p []byte) (n int, err error) { + a.elems = append(a.elems, log.StringValue(string(p))) + return len(p), nil } func (a *arrayEncoder) AppendByteString(v []byte) { diff --git a/bridges/otelzap/encoder_test.go b/bridges/otelzap/encoder_test.go index 561eb37f34f..84ab243c5d9 100644 --- a/bridges/otelzap/encoder_test.go +++ b/bridges/otelzap/encoder_test.go @@ -65,6 +65,13 @@ func TestObjectEncoder(t *testing.T) { }, expected: []interface{}{wantTurducken, wantTurducken}, }, + { + desc: "AddReflected", + f: func(e zapcore.ObjectEncoder) { + assert.NoError(t, e.AddReflected("k", map[string]interface{}{"foo": 5}), "Expected AddReflected to succeed.") + }, + expected: "{\"foo\":5}\n", + }, { desc: "AddBinary", f: func(e zapcore.ObjectEncoder) { e.AddBinary("k", []byte("foo")) }, @@ -207,6 +214,13 @@ func TestArrayEncoder(t *testing.T) { }, expected: []interface{}{true, false}, }, + { + desc: "AppendReflected", + f: func(e zapcore.ArrayEncoder) { + assert.NoError(t, e.AppendReflected(map[string]interface{}{"foo": 5})) + }, + expected: "{\"foo\":5}\n", + }, {"AppendBool", func(e zapcore.ArrayEncoder) { e.AppendBool(true) }, true}, {"AppendByteString", func(e zapcore.ArrayEncoder) { e.AppendByteString([]byte("foo")) }, "foo"}, {"AppendFloat64", func(e zapcore.ArrayEncoder) { e.AppendFloat64(3.14) }, 3.14},