mirror of
https://github.com/rs/zerolog
synced 2026-06-08 17:13:30 +00:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f220d89e1f | |||
| 87aceba511 |
@@ -71,3 +71,89 @@ func BenchmarkLogFields(b *testing.B) {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkLogFieldType(b *testing.B) {
|
||||
type obj struct {
|
||||
Pub string
|
||||
Tag string `json:"tag"`
|
||||
priv int
|
||||
}
|
||||
bools := []bool{true, false, true, false, true, false, true, false, true, false}
|
||||
ints := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
floats := []float64{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
strings := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"}
|
||||
durations := []time.Duration{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
|
||||
times := []time.Time{
|
||||
time.Unix(0, 0),
|
||||
time.Unix(1, 0),
|
||||
time.Unix(2, 0),
|
||||
time.Unix(3, 0),
|
||||
time.Unix(4, 0),
|
||||
time.Unix(5, 0),
|
||||
time.Unix(6, 0),
|
||||
time.Unix(7, 0),
|
||||
time.Unix(8, 0),
|
||||
time.Unix(9, 0),
|
||||
}
|
||||
o := obj{"a", "a", 0}
|
||||
errs := []error{errors.New("a"), errors.New("b"), errors.New("c"), errors.New("d"), errors.New("e")}
|
||||
types := map[string]func(e *Event) *Event{
|
||||
"Bool": func(e *Event) *Event {
|
||||
return e.Bool("k", bools[0])
|
||||
},
|
||||
"Bools": func(e *Event) *Event {
|
||||
return e.Bools("k", bools)
|
||||
},
|
||||
"Int": func(e *Event) *Event {
|
||||
return e.Int("k", ints[0])
|
||||
},
|
||||
"Ints": func(e *Event) *Event {
|
||||
return e.Ints("k", ints)
|
||||
},
|
||||
"Float": func(e *Event) *Event {
|
||||
return e.Float64("k", floats[0])
|
||||
},
|
||||
"Floats": func(e *Event) *Event {
|
||||
return e.Floats64("k", floats)
|
||||
},
|
||||
"Str": func(e *Event) *Event {
|
||||
return e.Str("k", strings[0])
|
||||
},
|
||||
"Strs": func(e *Event) *Event {
|
||||
return e.Strs("k", strings)
|
||||
},
|
||||
"Err": func(e *Event) *Event {
|
||||
return e.Err(errs[0])
|
||||
},
|
||||
"Errs": func(e *Event) *Event {
|
||||
return e.Errs("k", errs)
|
||||
},
|
||||
"Time": func(e *Event) *Event {
|
||||
return e.Time("k", times[0])
|
||||
},
|
||||
"Times": func(e *Event) *Event {
|
||||
return e.Times("k", times)
|
||||
},
|
||||
"Dur": func(e *Event) *Event {
|
||||
return e.Dur("k", durations[0])
|
||||
},
|
||||
"Durs": func(e *Event) *Event {
|
||||
return e.Durs("k", durations)
|
||||
},
|
||||
"Interface": func(e *Event) *Event {
|
||||
return e.Interface("k", o)
|
||||
},
|
||||
}
|
||||
logger := New(ioutil.Discard)
|
||||
b.ResetTimer()
|
||||
for name := range types {
|
||||
f := types[name]
|
||||
b.Run(name, func(b *testing.B) {
|
||||
b.RunParallel(func(pb *testing.PB) {
|
||||
for pb.Next() {
|
||||
f(logger.Info()).Msg("")
|
||||
}
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package zerolog
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"math"
|
||||
"sort"
|
||||
"strconv"
|
||||
"time"
|
||||
@@ -157,6 +158,9 @@ func appendErrorsKey(dst []byte, key string, errs []error) []byte {
|
||||
}
|
||||
|
||||
func appendError(dst []byte, err error) []byte {
|
||||
if err == nil {
|
||||
return dst
|
||||
}
|
||||
return appendErrorKey(dst, ErrorFieldName, err)
|
||||
}
|
||||
|
||||
@@ -369,8 +373,23 @@ func appendUints64(dst []byte, key string, vals []uint64) []byte {
|
||||
return dst
|
||||
}
|
||||
|
||||
func appendFloat(dst []byte, val float64, bitSize int) []byte {
|
||||
// JSON does not permit NaN or Infinity. A typical JSON encoder would fail
|
||||
// with an error, but a logging library wants the data to get thru so we
|
||||
// make a tradeoff and store those types as string.
|
||||
switch {
|
||||
case math.IsNaN(val):
|
||||
return append(dst, `"NaN"`...)
|
||||
case math.IsInf(val, 1):
|
||||
return append(dst, `"+Inf"`...)
|
||||
case math.IsInf(val, -1):
|
||||
return append(dst, `"-Inf"`...)
|
||||
}
|
||||
return strconv.AppendFloat(dst, val, 'f', -1, bitSize)
|
||||
}
|
||||
|
||||
func appendFloat32(dst []byte, key string, val float32) []byte {
|
||||
return strconv.AppendFloat(appendKey(dst, key), float64(val), 'f', -1, 32)
|
||||
return appendFloat(appendKey(dst, key), float64(val), 32)
|
||||
}
|
||||
|
||||
func appendFloats32(dst []byte, key string, vals []float32) []byte {
|
||||
@@ -378,10 +397,10 @@ func appendFloats32(dst []byte, key string, vals []float32) []byte {
|
||||
return append(appendKey(dst, key), '[', ']')
|
||||
}
|
||||
dst = append(appendKey(dst, key), '[')
|
||||
dst = strconv.AppendFloat(dst, float64(vals[0]), 'f', -1, 32)
|
||||
dst = appendFloat(dst, float64(vals[0]), 32)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendFloat(append(dst, ','), float64(val), 'f', -1, 32)
|
||||
dst = appendFloat(append(dst, ','), float64(val), 32)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
@@ -389,7 +408,7 @@ func appendFloats32(dst []byte, key string, vals []float32) []byte {
|
||||
}
|
||||
|
||||
func appendFloat64(dst []byte, key string, val float64) []byte {
|
||||
return strconv.AppendFloat(appendKey(dst, key), val, 'f', -1, 32)
|
||||
return appendFloat(appendKey(dst, key), val, 64)
|
||||
}
|
||||
|
||||
func appendFloats64(dst []byte, key string, vals []float64) []byte {
|
||||
@@ -397,10 +416,10 @@ func appendFloats64(dst []byte, key string, vals []float64) []byte {
|
||||
return append(appendKey(dst, key), '[', ']')
|
||||
}
|
||||
dst = append(appendKey(dst, key), '[')
|
||||
dst = strconv.AppendFloat(dst, vals[0], 'f', -1, 32)
|
||||
dst = appendFloat(dst, vals[0], 32)
|
||||
if len(vals) > 1 {
|
||||
for _, val := range vals[1:] {
|
||||
dst = strconv.AppendFloat(append(dst, ','), val, 'f', -1, 32)
|
||||
dst = appendFloat(append(dst, ','), val, 64)
|
||||
}
|
||||
}
|
||||
dst = append(dst, ']')
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_appendFloat64(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input float64
|
||||
want []byte
|
||||
}{
|
||||
{"-Inf", math.Inf(-1), []byte(`"foo":"-Inf"`)},
|
||||
{"+Inf", math.Inf(1), []byte(`"foo":"+Inf"`)},
|
||||
{"NaN", math.NaN(), []byte(`"foo":"NaN"`)},
|
||||
{"0", 0, []byte(`"foo":0`)},
|
||||
{"-1.1", -1.1, []byte(`"foo":-1.1`)},
|
||||
{"1e20", 1e20, []byte(`"foo":100000000000000000000`)},
|
||||
{"1e21", 1e21, []byte(`"foo":1000000000000000000000`)},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := appendFloat32([]byte{}, "foo", float32(tt.input)); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("appendFloat32() = %s, want %s", got, tt.want)
|
||||
}
|
||||
if got := appendFloat64([]byte{}, "foo", tt.input); !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("appendFloat32() = %s, want %s", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user