Skip to content

Commit

Permalink
otelzap: Implement methods on encoder (#5665)
Browse files Browse the repository at this point in the history
Part of
#5191

Pre-work
#5279
  • Loading branch information
khushijain21 authored May 31, 2024
1 parent b178009 commit 206099a
Show file tree
Hide file tree
Showing 3 changed files with 105 additions and 9 deletions.
2 changes: 0 additions & 2 deletions bridges/otelzap/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -151,8 +151,6 @@ func (o *Core) Write(ent zapcore.Entry, fields []zapcore.Field) error {
// TODO: Handle attributes passed via With (exceptions: context.Context and zap.Namespace).
// TODO: Handle context.Context containing trace context.
// TODO: Handle zap.Namespace.
// TODO: Handle zap.Object.
// TODO: Handle zap.Array.
// TODO: Handle ent.LoggerName.

r.AddAttributes(o.attr...)
Expand Down
23 changes: 16 additions & 7 deletions bridges/otelzap/encoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,11 @@ func (m *objectEncoder) AddArray(key string, v zapcore.ArrayMarshaler) error {
}

func (m *objectEncoder) AddObject(k string, v zapcore.ObjectMarshaler) error {
// TODO
return nil
// TODO: Use objectEncoder from a pool.
newobj := newObjectEncoder(2)
err := v.MarshalLogObject(newobj)
m.kv = append(m.kv, log.Map(k, newobj.kv...))
return err
}

func (m *objectEncoder) AddBinary(k string, v []byte) {
Expand Down Expand Up @@ -155,17 +158,23 @@ func assignUintValue(v uint64) log.Value {

// arrayEncoder implements [zapcore.ArrayEncoder].
type arrayEncoder struct {
elems []log.Value // nolint:unused
elems []log.Value
}

// TODO.
func (a *arrayEncoder) AppendArray(v zapcore.ArrayMarshaler) error {
return nil
// TODO: Use arrayEncoder from a pool.
arr := &arrayEncoder{}
err := v.MarshalLogArray(arr)
a.elems = append(a.elems, log.SliceValue(arr.elems...))
return err
}

// TODO.
func (a *arrayEncoder) AppendObject(v zapcore.ObjectMarshaler) error {
return nil
// TODO: Use objectEncoder from a pool.
m := newObjectEncoder(2)
err := v.MarshalLogObject(m)
a.elems = append(a.elems, log.MapValue(m.kv...))
return err
}

// TODO.
Expand Down
89 changes: 89 additions & 0 deletions bridges/otelzap/encoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
package otelzap

import (
"errors"
"testing"
"time"

Expand All @@ -18,11 +19,33 @@ import (

// Copied from https://github.com/uber-go/zap/blob/b39f8b6b6a44d8371a87610be50cce58eeeaabcb/zapcore/memory_encoder_test.go.
func TestObjectEncoder(t *testing.T) {
// Expected output of a turducken.
wantTurducken := map[string]interface{}{
"ducks": []interface{}{
map[string]interface{}{"in": "chicken"},
map[string]interface{}{"in": "chicken"},
},
}

tests := []struct {
desc string
f func(zapcore.ObjectEncoder)
expected interface{}
}{
{
desc: "AddObject",
f: func(e zapcore.ObjectEncoder) {
assert.NoError(t, e.AddObject("k", loggable{true}), "Expected AddObject to succeed.")
},
expected: map[string]interface{}{"loggable": "yes"},
},
{
desc: "AddObject (nested)",
f: func(e zapcore.ObjectEncoder) {
assert.NoError(t, e.AddObject("k", turducken{}), "Expected AddObject to succeed.")
},
expected: wantTurducken,
},
{
desc: "AddArray",
f: func(e zapcore.ObjectEncoder) {
Expand All @@ -35,6 +58,13 @@ func TestObjectEncoder(t *testing.T) {
},
expected: []interface{}{true, false, true},
},
{
desc: "AddArray (nested)",
f: func(e zapcore.ObjectEncoder) {
assert.NoError(t, e.AddArray("k", turduckens(2)), "Expected AddArray to succeed.")
},
expected: []interface{}{wantTurducken, wantTurducken},
},
{
desc: "AddBinary",
f: func(e zapcore.ObjectEncoder) { e.AddBinary("k", []byte("foo")) },
Expand Down Expand Up @@ -164,6 +194,19 @@ func TestArrayEncoder(t *testing.T) {
f func(zapcore.ArrayEncoder)
expected interface{}
}{
// AppendObject is covered by AddObject (nested) case above.
{
desc: "AppendArray (arrays of arrays)",
f: func(e zapcore.ArrayEncoder) {
err := e.AppendArray(zapcore.ArrayMarshalerFunc(func(inner zapcore.ArrayEncoder) error {
inner.AppendBool(true)
inner.AppendBool(false)
return nil
}))
assert.NoError(t, err)
},
expected: []interface{}{true, false},
},
{"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},
Expand Down Expand Up @@ -201,6 +244,52 @@ func TestArrayEncoder(t *testing.T) {
}
}

type turducken struct{}

func (t turducken) MarshalLogObject(enc zapcore.ObjectEncoder) error {
return enc.AddArray("ducks", zapcore.ArrayMarshalerFunc(func(arr zapcore.ArrayEncoder) error {
for i := 0; i < 2; i++ {
err := arr.AppendObject(zapcore.ObjectMarshalerFunc(func(inner zapcore.ObjectEncoder) error {
inner.AddString("in", "chicken")
return nil
}))
if err != nil {
return err
}
}
return nil
}))
}

type turduckens int

func (t turduckens) MarshalLogArray(enc zapcore.ArrayEncoder) error {
var err error
tur := turducken{}
for i := 0; i < int(t); i++ {
err = errors.Join(err, enc.AppendObject(tur))
}
return err
}

type loggable struct{ bool }

func (l loggable) MarshalLogObject(enc zapcore.ObjectEncoder) error {
if !l.bool {
return errors.New("can't marshal")
}
enc.AddString("loggable", "yes")
return nil
}

func (l loggable) MarshalLogArray(enc zapcore.ArrayEncoder) error {
if !l.bool {
return errors.New("can't marshal")
}
enc.AppendBool(true)
return nil
}

func value2Result(v log.Value) any {
switch v.Kind() {
case log.KindBool:
Expand Down

0 comments on commit 206099a

Please sign in to comment.