From 1ddc6acf77621bac7e7459f6b9c1d968fd545426 Mon Sep 17 00:00:00 2001 From: Khushi Jain Date: Wed, 5 Jun 2024 13:22:33 +0530 Subject: [PATCH] otelzap: Implement Reflect method (#5703) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Part of https://github.com/open-telemetry/opentelemetry-go-contrib/issues/5191 Pre-work https://github.com/open-telemetry/opentelemetry-go-contrib/pull/5279 --------- Co-authored-by: Robert PajÄ…k --- bridges/otelzap/encoder.go | 63 +++++++++++++++++++++++++++++++-- bridges/otelzap/encoder_test.go | 14 ++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) diff --git a/bridges/otelzap/encoder.go b/bridges/otelzap/encoder.go index eed14b0798f..5a8312c6933 100644 --- a/bridges/otelzap/encoder.go +++ b/bridges/otelzap/encoder.go @@ -4,6 +4,8 @@ package otelzap // import "go.opentelemetry.io/contrib/bridges/otelzap" import ( + "fmt" + "reflect" "time" "go.uber.org/zap/zapcore" @@ -93,8 +95,12 @@ func (m *objectEncoder) AddUint64(k string, v uint64) { }) } -// TODO. func (m *objectEncoder) AddReflected(k string, v interface{}) error { + m.kv = append(m.kv, + log.KeyValue{ + Key: k, + Value: convertValue(v), + }) return nil } @@ -177,8 +183,8 @@ func (a *arrayEncoder) AppendObject(v zapcore.ObjectMarshaler) error { return err } -// TODO. func (a *arrayEncoder) AppendReflected(v interface{}) error { + a.elems = append(a.elems, convertValue(v)) return nil } @@ -231,3 +237,56 @@ func (a *arrayEncoder) AppendUint32(v uint32) { a.AppendInt64(int64(v)) func (a *arrayEncoder) AppendUint16(v uint16) { a.AppendInt64(int64(v)) } func (a *arrayEncoder) AppendUint8(v uint8) { a.AppendInt64(int64(v)) } func (a *arrayEncoder) AppendUintptr(v uintptr) { a.AppendUint64(uint64(v)) } + +func convertValue(v interface{}) log.Value { + switch v := v.(type) { + case bool: + return log.BoolValue(v) + case []byte: + return log.BytesValue(v) + case float64: + return log.Float64Value(v) + case int: + return log.IntValue(v) + case int64: + return log.Int64Value(v) + case string: + return log.StringValue(v) + } + + t := reflect.TypeOf(v) + if t == nil { + return log.Value{} + } + val := reflect.ValueOf(v) + switch t.Kind() { + case reflect.Struct: + return log.StringValue(fmt.Sprintf("%+v", v)) + case reflect.Slice, reflect.Array: + items := make([]log.Value, 0, val.Len()) + for i := 0; i < val.Len(); i++ { + items = append(items, convertValue(val.Index(i).Interface())) + } + return log.SliceValue(items...) + case reflect.Map: + kvs := make([]log.KeyValue, 0, val.Len()) + for _, k := range val.MapKeys() { + var key string + // If the key is a struct, use %+v to print the struct fields. + if k.Kind() == reflect.Struct { + key = fmt.Sprintf("%+v", k.Interface()) + } else { + key = fmt.Sprintf("%v", k.Interface()) + } + kvs = append(kvs, log.KeyValue{ + Key: key, + Value: convertValue(val.MapIndex(k).Interface()), + }) + } + return log.MapValue(kvs...) + case reflect.Ptr, reflect.Interface: + return convertValue(val.Elem().Interface()) + } + + return log.StringValue(fmt.Sprintf("unhandled attribute type: (%s) %+v", t, v)) +} diff --git a/bridges/otelzap/encoder_test.go b/bridges/otelzap/encoder_test.go index 561eb37f34f..944136e4af1 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: map[string]interface{}{"foo": int64(5)}, + }, { 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: map[string]interface{}{"foo": int64(5)}, + }, {"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},