Skip to content

Commit be8e992

Browse files
prashantvakshayjshah
authored andcommitted
Replace Nest in KeyValue interface with LogMarshalerFunc type (uber-go#91)
This reduces the KeyValue interface while still allowing a function to be used to build an object using LogMarshalerFunc
1 parent 3f6e84d commit be8e992

6 files changed

+29
-31
lines changed

field_test.go

+5
Original file line numberDiff line numberDiff line change
@@ -163,6 +163,11 @@ func TestNestField(t *testing.T) {
163163
assertCanBeReused(t, nest)
164164
}
165165

166+
func TestLogMarshalerFunc(t *testing.T) {
167+
assertFieldJSON(t, `"foo":{"name":"phil"}`,
168+
Marshaler("foo", LogMarshalerFunc(fakeUser{"phil"}.MarshalLog)))
169+
}
170+
166171
func TestStackField(t *testing.T) {
167172
enc := newJSONEncoder()
168173
defer enc.Free()

json_encoder.go

+5-12
Original file line numberDiff line numberDiff line change
@@ -117,22 +117,15 @@ func (enc *jsonEncoder) AddFloat64(key string, val float64) {
117117
}
118118
}
119119

120-
// Nest allows the caller to populate a nested object under the provided key.
121-
func (enc *jsonEncoder) Nest(key string, f func(KeyValue) error) error {
122-
enc.addKey(key)
123-
enc.bytes = append(enc.bytes, '{')
124-
err := f(enc)
125-
enc.bytes = append(enc.bytes, '}')
126-
return err
127-
}
128-
129120
// AddMarshaler adds a LogMarshaler to the encoder's fields.
130121
//
131122
// TODO: Encode the error into the message instead of returning.
132123
func (enc *jsonEncoder) AddMarshaler(key string, obj LogMarshaler) error {
133-
return enc.Nest(key, func(kv KeyValue) error {
134-
return obj.MarshalLog(kv)
135-
})
124+
enc.addKey(key)
125+
enc.bytes = append(enc.bytes, '{')
126+
err := obj.MarshalLog(enc)
127+
enc.bytes = append(enc.bytes, '}')
128+
return err
136129
}
137130

138131
// AddObject uses reflection to add an arbitrary object to the logging context.

json_encoder_bench_test.go

+10-5
Original file line numberDiff line numberDiff line change
@@ -34,15 +34,20 @@ type logRecord struct {
3434
Fields map[string]interface{} `json:"fields"`
3535
}
3636

37-
var s string
37+
// newEncoder returns the encoder interface, which is how end users would use
38+
// the LogMarshalerFunc type. Using the JSON encoder type directly allows
39+
// inlining which reduces allocs artificially.
40+
func newEncoder() encoder {
41+
return newJSONEncoder()
42+
}
3843

39-
func BenchmarkJSONEncoderNest(b *testing.B) {
44+
func BenchmarkLogMarshalerFunc(b *testing.B) {
4045
for i := 0; i < b.N; i++ {
41-
enc := newJSONEncoder()
42-
enc.Nest("nested", func(kv KeyValue) error {
46+
enc := newEncoder()
47+
enc.AddMarshaler("nested", LogMarshalerFunc(func(kv KeyValue) error {
4348
kv.AddInt("i", i)
4449
return nil
45-
})
50+
}))
4651
enc.Free()
4752
}
4853
}

json_encoder_test.go

-13
Original file line numberDiff line numberDiff line change
@@ -149,19 +149,6 @@ func TestJSONWriteMessage(t *testing.T) {
149149
})
150150
}
151151

152-
func TestJSONNest(t *testing.T) {
153-
withJSONEncoder(func(enc *jsonEncoder) {
154-
err := enc.Nest("nested", func(kv KeyValue) error {
155-
kv.AddString("sub-foo", "sub-bar")
156-
return nil
157-
})
158-
require.NoError(t, err, "Unexpected error using Nest.")
159-
enc.AddString("baz", "bing")
160-
161-
assertJSON(t, `"foo":"bar","nested":{"sub-foo":"sub-bar"},"baz":"bing"`, enc)
162-
})
163-
}
164-
165152
type loggable struct{}
166153

167154
func (l loggable) MarshalLog(kv KeyValue) error {

keyvalue.go

-1
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,4 @@ type KeyValue interface {
3535
// allocation-heavy. Consider implementing the LogMarshaler interface instead.
3636
AddObject(key string, value interface{})
3737
AddString(key, value string)
38-
Nest(key string, f func(KeyValue) error) error
3938
}

marshaler.go

+9
Original file line numberDiff line numberDiff line change
@@ -26,3 +26,12 @@ package zap
2626
type LogMarshaler interface {
2727
MarshalLog(KeyValue) error
2828
}
29+
30+
// LogMarshalerFunc is a type adapter that allows using a function as a
31+
// LogMarshaler.
32+
type LogMarshalerFunc func(KeyValue) error
33+
34+
// MarshalLog calls the underlying function.
35+
func (f LogMarshalerFunc) MarshalLog(kv KeyValue) error {
36+
return f(kv)
37+
}

0 commit comments

Comments
 (0)