Skip to content

Commit

Permalink
Add Bytes to Field union
Browse files Browse the repository at this point in the history
To make logging bytestrings and binary more efficient, add a byte slice to the
Field union. This adds ~80ns to the `AddingFields` benchmarks, but saves an
allocation along a path that particularly performance-sensitive applications
will use.
  • Loading branch information
Akshay Shah committed Mar 14, 2017
1 parent 03e7655 commit c7ba680
Show file tree
Hide file tree
Showing 4 changed files with 11 additions and 9 deletions.
4 changes: 2 additions & 2 deletions field.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func Skip() zapcore.Field {
// zap's JSON encoder base64-encodes binary blobs. To log UTF-8 encoded text,
// use ByteString.
func Binary(key string, val []byte) zapcore.Field {
return zapcore.Field{Key: key, Type: zapcore.BinaryType, Interface: val}
return zapcore.Field{Key: key, Type: zapcore.BinaryType, Bytes: val}
}

// Bool constructs a field that carries a bool.
Expand All @@ -55,7 +55,7 @@ func Bool(key string, val bool) zapcore.Field {
// To log opaque binary blobs (which aren't necessarily valid UTF-8), use
// Binary.
func ByteString(key string, val []byte) zapcore.Field {
return zapcore.Field{Key: key, Type: zapcore.ByteStringType, Interface: val}
return zapcore.Field{Key: key, Type: zapcore.ByteStringType, Bytes: val}
}

// Complex128 constructs a field that carries a complex number. Unlike most
Expand Down
4 changes: 2 additions & 2 deletions field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,10 +71,10 @@ func TestFieldConstructors(t *testing.T) {
expect zapcore.Field
}{
{"Skip", zapcore.Field{Type: zapcore.SkipType}, Skip()},
{"Binary", zapcore.Field{Key: "k", Type: zapcore.BinaryType, Interface: []byte("ab12")}, Binary("k", []byte("ab12"))},
{"Binary", zapcore.Field{Key: "k", Type: zapcore.BinaryType, Bytes: []byte("ab12")}, Binary("k", []byte("ab12"))},
{"Bool", zapcore.Field{Key: "k", Type: zapcore.BoolType, Integer: 1}, Bool("k", true)},
{"Bool", zapcore.Field{Key: "k", Type: zapcore.BoolType, Integer: 1}, Bool("k", true)},
{"ByteString", zapcore.Field{Key: "k", Type: zapcore.ByteStringType, Interface: []byte("ab12")}, ByteString("k", []byte("ab12"))},
{"ByteString", zapcore.Field{Key: "k", Type: zapcore.ByteStringType, Bytes: []byte("ab12")}, ByteString("k", []byte("ab12"))},
{"Complex128", zapcore.Field{Key: "k", Type: zapcore.Complex128Type, Interface: 1 + 2i}, Complex128("k", 1+2i)},
{"Complex64", zapcore.Field{Key: "k", Type: zapcore.Complex64Type, Interface: complex64(1 + 2i)}, Complex64("k", 1+2i)},
{"Duration", zapcore.Field{Key: "k", Type: zapcore.DurationType, Integer: 1}, Duration("k", 1)},
Expand Down
5 changes: 3 additions & 2 deletions zapcore/field.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ type Field struct {
Type FieldType
Integer int64
String string
Bytes []byte
Interface interface{}
}

Expand All @@ -111,11 +112,11 @@ func (f Field) AddTo(enc ObjectEncoder) {
case ObjectMarshalerType:
err = enc.AddObject(f.Key, f.Interface.(ObjectMarshaler))
case BinaryType:
enc.AddBinary(f.Key, f.Interface.([]byte))
enc.AddBinary(f.Key, f.Bytes)
case BoolType:
enc.AddBool(f.Key, f.Integer == 1)
case ByteStringType:
enc.AddByteString(f.Key, f.Interface.([]byte))
enc.AddByteString(f.Key, f.Bytes)
case Complex128Type:
enc.AddComplex128(f.Key, f.Interface.(complex128))
case Complex64Type:
Expand Down
7 changes: 4 additions & 3 deletions zapcore/field_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,14 +100,15 @@ func TestFields(t *testing.T) {
t FieldType
i int64
s string
b []byte
iface interface{}
want interface{}
}{
{t: ArrayMarshalerType, iface: users(2), want: []interface{}{"user", "user"}},
{t: ObjectMarshalerType, iface: users(2), want: map[string]interface{}{"users": 2}},
{t: BinaryType, iface: []byte("foo"), want: []byte("foo")},
{t: BinaryType, b: []byte("foo"), want: []byte("foo")},
{t: ByteStringType, b: []byte("foo"), want: []byte("foo")},
{t: BoolType, i: 0, want: false},
{t: ByteStringType, iface: []byte("foo"), want: []byte("foo")},
{t: Complex128Type, iface: 1 + 2i, want: 1 + 2i},
{t: Complex64Type, iface: complex64(1 + 2i), want: complex64(1 + 2i)},
{t: DurationType, i: 1000, want: time.Microsecond},
Expand All @@ -133,7 +134,7 @@ func TestFields(t *testing.T) {

for _, tt := range tests {
enc := NewMapObjectEncoder()
f := Field{Key: "k", Type: tt.t, Integer: tt.i, Interface: tt.iface, String: tt.s}
f := Field{Key: "k", Type: tt.t, Integer: tt.i, Interface: tt.iface, Bytes: tt.b, String: tt.s}
f.AddTo(enc)
assert.Equal(t, tt.want, enc.Fields["k"], "Unexpected output from field %+v.", f)

Expand Down

0 comments on commit c7ba680

Please sign in to comment.