mirror of
https://github.com/rs/zerolog
synced 2026-06-08 17:13:30 +00:00
Added variadic StrsV, ObjectsV, and StringersV (#752)
* Added variadic StrsV, ObjectsV, and StringersV This allows you to just list all the string, object, or stringer that you want added to a Event or Context. The variadic versions are suffixed with V so as to not be a breaking change. If you have an existing array of objects that implement the LogObjectMarshaler or fmt.Stringer interfaces, unfortunately go doesn't consider those slices as identical types, so you have to allocate an array and copy the entries, there are generic helper methods in global_118.go zerolog.AsLogObjectMarshalers and zerolog.AsStringers if you're using go 1.18 or later. Somewhat addresses #551 * Address CoPilot comments. * Resolve odd Stringers on nil array
This commit is contained in:
@@ -23,7 +23,7 @@ jobs:
|
||||
- name: Test
|
||||
run: go test -race -bench . -benchmem ./...
|
||||
- name: Test CBOR
|
||||
run: go test -tags binary_log ./...
|
||||
run: go test -tags binary_log -race ./...
|
||||
coverage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
@@ -142,12 +142,18 @@ func BenchmarkLogFieldType(b *testing.B) {
|
||||
"Strs": func(e *Event) *Event {
|
||||
return e.Strs("k", fixtures.Strings)
|
||||
},
|
||||
"StrsV": func(e *Event) *Event {
|
||||
return e.StrsV("k", fixtures.Strings...)
|
||||
},
|
||||
"Stringer": func(e *Event) *Event {
|
||||
return e.Stringer("k", fixtures.Stringers[0])
|
||||
},
|
||||
"Stringers": func(e *Event) *Event {
|
||||
return e.Stringers("k", fixtures.Stringers)
|
||||
},
|
||||
"StringersV": func(e *Event) *Event {
|
||||
return e.StringersV("k", fixtures.Stringers...)
|
||||
},
|
||||
"Err": func(e *Event) *Event {
|
||||
return e.Err(fixtures.Errs[0])
|
||||
},
|
||||
@@ -187,6 +193,9 @@ func BenchmarkLogFieldType(b *testing.B) {
|
||||
"Objects": func(e *Event) *Event {
|
||||
return e.Objects("k", fixtures.Objects)
|
||||
},
|
||||
"ObjectsV": func(e *Event) *Event {
|
||||
return e.ObjectsV("k", fixtures.Objects...)
|
||||
},
|
||||
"Timestamp": func(e *Event) *Event {
|
||||
return e.Timestamp()
|
||||
},
|
||||
@@ -270,12 +279,18 @@ func BenchmarkContextFieldType(b *testing.B) {
|
||||
"Strs": func(c Context) Context {
|
||||
return c.Strs("k", fixtures.Strings)
|
||||
},
|
||||
"StrsV": func(c Context) Context {
|
||||
return c.StrsV("k", fixtures.Strings...)
|
||||
},
|
||||
"Stringer": func(c Context) Context {
|
||||
return c.Stringer("k", fixtures.Stringers[0])
|
||||
},
|
||||
"Stringers": func(c Context) Context {
|
||||
return c.Stringers("k", fixtures.Stringers)
|
||||
},
|
||||
"StringersV": func(c Context) Context {
|
||||
return c.StringersV("k", fixtures.Stringers...)
|
||||
},
|
||||
"Err": func(c Context) Context {
|
||||
return c.Err(fixtures.Errs[0])
|
||||
},
|
||||
@@ -315,6 +330,9 @@ func BenchmarkContextFieldType(b *testing.B) {
|
||||
"Objects": func(c Context) Context {
|
||||
return c.Objects("k", fixtures.Objects)
|
||||
},
|
||||
"ObjectsV": func(c Context) Context {
|
||||
return c.ObjectsV("k", fixtures.Objects...)
|
||||
},
|
||||
"Timestamp": func(c Context) Context {
|
||||
return c.Timestamp()
|
||||
},
|
||||
|
||||
+35
-9
@@ -78,7 +78,10 @@ func (c Context) Object(key string, obj LogObjectMarshaler) Context {
|
||||
return c
|
||||
}
|
||||
|
||||
// Object marshals an object that implement the LogObjectMarshaler interface.
|
||||
// Objects adds the field key with objs to the logger context as an array of
|
||||
// objects that implement the LogObjectMarshaler interface.
|
||||
//
|
||||
// This is the array version that accepts a slice of LogObjectMarshaler objects.
|
||||
func (c Context) Objects(key string, objs []LogObjectMarshaler) Context {
|
||||
e := c.l.scratchEvent()
|
||||
e.Objects(key, objs)
|
||||
@@ -87,6 +90,14 @@ func (c Context) Objects(key string, objs []LogObjectMarshaler) Context {
|
||||
return c
|
||||
}
|
||||
|
||||
// ObjectsV adds the field key with objs to the logger context as an array of
|
||||
// objects that implement the LogObjectMarshaler interface.
|
||||
//
|
||||
// This is a variadic version that accepts a list of individual LogObjectMarshaler objects.
|
||||
func (c Context) ObjectsV(key string, objs ...LogObjectMarshaler) Context {
|
||||
return c.Objects(key, objs)
|
||||
}
|
||||
|
||||
// EmbedObject marshals and Embeds an object that implement the LogObjectMarshaler interface.
|
||||
func (c Context) EmbedObject(obj LogObjectMarshaler) Context {
|
||||
e := c.l.scratchEvent()
|
||||
@@ -103,11 +114,20 @@ func (c Context) Str(key, val string) Context {
|
||||
}
|
||||
|
||||
// Strs adds the field key with val as a string to the logger context.
|
||||
//
|
||||
// This is the array version that accepts a slice of string values.
|
||||
func (c Context) Strs(key string, vals []string) Context {
|
||||
c.l.context = enc.AppendStrings(enc.AppendKey(c.l.context, key), vals)
|
||||
return c
|
||||
}
|
||||
|
||||
// StrsV adds the field key with vals as a []string to the logger context.
|
||||
//
|
||||
// This is a variadic version that accepts a list of individual strings.
|
||||
func (c Context) StrsV(key string, vals ...string) Context {
|
||||
return c.Strs(key, vals)
|
||||
}
|
||||
|
||||
// Stringer adds the field key with val.String() (or null if val is nil) to the logger context.
|
||||
func (c Context) Stringer(key string, val fmt.Stringer) Context {
|
||||
if val != nil {
|
||||
@@ -119,18 +139,24 @@ func (c Context) Stringer(key string, val fmt.Stringer) Context {
|
||||
return c
|
||||
}
|
||||
|
||||
// Stringers adds the field key with vals as an array of strings by calling .String() on each entry
|
||||
// to the logger context.
|
||||
// Stringers adds the field key with vals to the logger context where each
|
||||
// individual val is added by calling val.String().
|
||||
//
|
||||
// This is the array version that accepts a slice of fmt.Stringer values.
|
||||
func (c Context) Stringers(key string, vals []fmt.Stringer) Context {
|
||||
if vals != nil {
|
||||
c.l.context = enc.AppendStringers(enc.AppendKey(c.l.context, key), vals)
|
||||
return c
|
||||
}
|
||||
|
||||
c.l.context = enc.AppendInterface(enc.AppendKey(c.l.context, key), nil)
|
||||
c.l.context = enc.AppendStringers(enc.AppendKey(c.l.context, key), vals)
|
||||
return c
|
||||
}
|
||||
|
||||
// StringersV adds the field key with vals to the logger context where each
|
||||
// individual val is added by calling val.String().
|
||||
//
|
||||
// This is a variadic version that accepts a list of individual
|
||||
// fmt.Stringer values.
|
||||
func (c Context) StringersV(key string, vals ...fmt.Stringer) Context {
|
||||
return c.Stringers(key, vals)
|
||||
}
|
||||
|
||||
// Bytes adds the field key with val as a []byte to the logger context.
|
||||
func (c Context) Bytes(key string, val []byte) Context {
|
||||
c.l.context = enc.AppendBytes(enc.AppendKey(c.l.context, key), val)
|
||||
|
||||
@@ -264,7 +264,10 @@ func (e *Event) Object(key string, obj LogObjectMarshaler) *Event {
|
||||
return e
|
||||
}
|
||||
|
||||
// Objects adds the field key with obj as an array of objects that implement the LogObjectMarshaler interface.
|
||||
// Objects adds the field key with objs as an array of objects that
|
||||
// implement the LogObjectMarshaler interface to the event.
|
||||
//
|
||||
// This is the array version that accepts a slice of LogObjectMarshaler objects.
|
||||
func (e *Event) Objects(key string, objs []LogObjectMarshaler) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
@@ -280,6 +283,14 @@ func (e *Event) Objects(key string, objs []LogObjectMarshaler) *Event {
|
||||
return e
|
||||
}
|
||||
|
||||
// ObjectsV adds the field key with objs as an array of objects that
|
||||
// implement the LogObjectMarshaler interface to the event.
|
||||
//
|
||||
// This is a variadic version that accepts a list of individual LogObjectMarshaler objects.
|
||||
func (e *Event) ObjectsV(key string, objs ...LogObjectMarshaler) *Event {
|
||||
return e.Objects(key, objs)
|
||||
}
|
||||
|
||||
// Func allows an anonymous func to run only if the event is enabled.
|
||||
func (e *Event) Func(f func(e *Event)) *Event {
|
||||
if e != nil && e.Enabled() {
|
||||
@@ -310,6 +321,8 @@ func (e *Event) Str(key, val string) *Event {
|
||||
}
|
||||
|
||||
// Strs adds the field key with vals as a []string to the *Event context.
|
||||
//
|
||||
// This is the array version that accepts a slice of string values.
|
||||
func (e *Event) Strs(key string, vals []string) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
@@ -318,8 +331,16 @@ func (e *Event) Strs(key string, vals []string) *Event {
|
||||
return e
|
||||
}
|
||||
|
||||
// Stringer adds the field key with val.String() (or null if val is nil)
|
||||
// to the *Event context.
|
||||
// StrsV adds the field key with vals as a []string to the *Event context.
|
||||
//
|
||||
// This is a variadic version that accepts a list of individual strings.
|
||||
func (e *Event) StrsV(key string, vals ...string) *Event {
|
||||
return e.Strs(key, vals)
|
||||
}
|
||||
|
||||
// Stringer adds the field key and a val to the *Event context.
|
||||
// If val is not nil, it is added by calling val.String().
|
||||
// If val is nil, it is encoded as null without calling String().
|
||||
func (e *Event) Stringer(key string, val fmt.Stringer) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
@@ -328,9 +349,11 @@ func (e *Event) Stringer(key string, val fmt.Stringer) *Event {
|
||||
return e
|
||||
}
|
||||
|
||||
// Stringers adds the field key with vals where each individual val
|
||||
// is used as val.String() (or null if val is empty) to the *Event
|
||||
// context.
|
||||
// Stringers adds the field key with vals to the *Event context.
|
||||
// If a val is not nil, it is added by calling val.String().
|
||||
// If a val is nil, it is encoded as null without calling String().
|
||||
//
|
||||
// This is the array version that accepts a slice of fmt.Stringer values.
|
||||
func (e *Event) Stringers(key string, vals []fmt.Stringer) *Event {
|
||||
if e == nil {
|
||||
return e
|
||||
@@ -339,6 +362,16 @@ func (e *Event) Stringers(key string, vals []fmt.Stringer) *Event {
|
||||
return e
|
||||
}
|
||||
|
||||
// StringersV adds the field key with vals to the *Event context.
|
||||
// If a val is not nil, it is added by calling val.String().
|
||||
// If a val is nil, it is encoded as null without calling String().
|
||||
//
|
||||
// This is a variadic version that accepts a list of individual
|
||||
// fmt.Stringer values.
|
||||
func (e *Event) StringersV(key string, vals ...fmt.Stringer) *Event {
|
||||
return e.Stringers(key, vals)
|
||||
}
|
||||
|
||||
// Bytes adds the field key with val as a string to the *Event context.
|
||||
//
|
||||
// Runes outside of normal ASCII ranges will be hex-encoded in the resulting
|
||||
|
||||
@@ -259,9 +259,15 @@ func TestEvent_WithNilEvent(t *testing.T) {
|
||||
"Strs": func() *Event {
|
||||
return e.Strs("k", fixtures.Strings)
|
||||
},
|
||||
"StrsV": func() *Event {
|
||||
return e.StrsV("k", fixtures.Strings...)
|
||||
},
|
||||
"Stringers": func() *Event {
|
||||
return e.Stringers("k", fixtures.Stringers)
|
||||
},
|
||||
"StringersV": func() *Event {
|
||||
return e.StringersV("k", fixtures.Stringers...)
|
||||
},
|
||||
"Err": func() *Event {
|
||||
return e.Err(fixtures.Errs[0])
|
||||
},
|
||||
@@ -306,6 +312,9 @@ func TestEvent_WithNilEvent(t *testing.T) {
|
||||
"Objects": func() *Event {
|
||||
return e.Objects("k", fixtures.Objects)
|
||||
},
|
||||
"ObjectsV": func() *Event {
|
||||
return e.ObjectsV("k", fixtures.Objects...)
|
||||
},
|
||||
"EmbedObject": func() *Event {
|
||||
return e.EmbedObject(fixtures.Objects[0])
|
||||
},
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
//go:build go1.18
|
||||
// +build go1.18
|
||||
|
||||
package zerolog
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func AsLogObjectMarshalers[T LogObjectMarshaler](objs []T) []LogObjectMarshaler {
|
||||
if objs == nil {
|
||||
return nil
|
||||
}
|
||||
s := make([]LogObjectMarshaler, len(objs))
|
||||
for i, v := range objs {
|
||||
s[i] = v
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
func AsStringers[T fmt.Stringer](objs []T) []fmt.Stringer {
|
||||
if objs == nil {
|
||||
return nil
|
||||
}
|
||||
s := make([]fmt.Stringer, len(objs))
|
||||
for i, v := range objs {
|
||||
s[i] = v
|
||||
}
|
||||
return s
|
||||
}
|
||||
@@ -35,7 +35,7 @@ func (Encoder) AppendString(dst []byte, s string) []byte {
|
||||
// AppendStringers encodes and adds an array of Stringer values
|
||||
// to the dst byte array.
|
||||
func (e Encoder) AppendStringers(dst []byte, vals []fmt.Stringer) []byte {
|
||||
if len(vals) == 0 {
|
||||
if vals == nil || len(vals) == 0 {
|
||||
return e.AppendArrayEnd(e.AppendArrayStart(dst))
|
||||
}
|
||||
dst = e.AppendArrayStart(dst)
|
||||
|
||||
@@ -66,7 +66,7 @@ func (Encoder) AppendString(dst []byte, s string) []byte {
|
||||
// AppendStringers encodes the provided Stringer list to json and
|
||||
// appends the encoded Stringer list to the input byte slice.
|
||||
func (e Encoder) AppendStringers(dst []byte, vals []fmt.Stringer) []byte {
|
||||
if len(vals) == 0 {
|
||||
if vals == nil || len(vals) == 0 {
|
||||
return append(dst, '[', ']')
|
||||
}
|
||||
dst = append(dst, '[')
|
||||
|
||||
+71
-2
@@ -290,6 +290,34 @@ func ExampleEvent_Object() {
|
||||
// Output: {"foo":"bar","user":{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Objects() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
u2 := User{"Bono", 54, time.Time{}}
|
||||
users := []User{u, u2}
|
||||
|
||||
log.Log().
|
||||
Objects("users", zerolog.AsLogObjectMarshalers(users)).
|
||||
Msg("hello world")
|
||||
// Output: {"users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bono","age":54,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_ObjectsV() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
u2 := User{"Bono", 54, time.Time{}}
|
||||
|
||||
log.Log().
|
||||
ObjectsV("users", u, u2).
|
||||
Msg("hello world")
|
||||
|
||||
// Output: {"users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bono","age":54,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_EmbedObject() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
@@ -454,8 +482,22 @@ func ExampleContext_Objects() {
|
||||
// Output: {"foo":"bar","users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bono","age":54,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_EmbedObject() {
|
||||
func ExampleContext_ObjectsV() {
|
||||
// User implements zerolog.LogObjectMarshaler
|
||||
u := User{"John", 35, time.Time{}}
|
||||
u2 := User{"Bono", 54, time.Time{}}
|
||||
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
Str("foo", "bar").
|
||||
ObjectsV("users", u, u2). // shows variadic version with distinct element arguments
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
// Output: {"foo":"bar","users":[{"name":"John","age":35,"created":"0001-01-01T00:00:00Z"},{"name":"Bono","age":54,"created":"0001-01-01T00:00:00Z"}],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_EmbedObject() {
|
||||
price := Price{val: 6449, prec: 2, unit: "$"}
|
||||
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
@@ -464,7 +506,6 @@ func ExampleContext_EmbedObject() {
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
// Output: {"foo":"bar","price":"$64.49","message":"hello world"}
|
||||
}
|
||||
|
||||
@@ -615,3 +656,31 @@ func ExampleContext_Times() {
|
||||
|
||||
// Output: {"foo":"bar","times":["0001-01-01T00:00:00Z","0001-01-01T00:00:10Z"],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleEvent_Stringers() {
|
||||
log := zerolog.New(os.Stdout)
|
||||
|
||||
// net.IP values implement fmt.Stringer and can be used with StringersV
|
||||
a := net.IP{127, 0, 0, 1}
|
||||
b := net.IP{127, 0, 0, 2}
|
||||
ips := []net.IP{a, b}
|
||||
|
||||
log.Log().
|
||||
Stringers("ips", zerolog.AsStringers(ips)).
|
||||
Msg("hello world")
|
||||
// Output: {"ips":["127.0.0.1","127.0.0.2"],"message":"hello world"}
|
||||
}
|
||||
|
||||
func ExampleContext_StringersV() {
|
||||
// net.IP values implement fmt.Stringer and can be used with StringersV
|
||||
a := net.IPv4bcast
|
||||
b := net.IPv4allrouter
|
||||
|
||||
log := zerolog.New(os.Stdout).With().
|
||||
StringersV("ips", a, b).
|
||||
Logger()
|
||||
|
||||
log.Log().Msg("hello world")
|
||||
|
||||
// Output: {"ips":["255.255.255.255","224.0.0.2"],"message":"hello world"}
|
||||
}
|
||||
|
||||
+81
-16
@@ -172,12 +172,22 @@ func TestStackedWiths(t *testing.T) {
|
||||
|
||||
func TestWithPlurals(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
ctx := New(out).With().
|
||||
Strs("strings", []string{"foo", "bar"}).
|
||||
Strs("strings_nil", nil).
|
||||
Stringers("stringers", []fmt.Stringer{net.IP{127, 0, 0, 1}, nil}).
|
||||
ctx := New(out).
|
||||
With().
|
||||
Objects("objs", []LogObjectMarshaler{fixtureObj{"a", "z", 1}}).
|
||||
Objects("objs_nil", nil).
|
||||
ObjectsV("objs_v", fixtureObj{"A", "Z", 2}).
|
||||
ObjectsV("objs_v_empty").
|
||||
Strs("strs", []string{"foo", "bar"}).
|
||||
Strs("strs_nil", nil).
|
||||
StrsV("strs_v", "baz", "fizz").
|
||||
StrsV("strs_v_empty").
|
||||
Stringers("stringers", []fmt.Stringer{net.IP{127, 0, 0, 1}, time.Time{}.AddDate(0, 1, 2), 1 * time.Second, nil}).
|
||||
Stringers("stringers_nil", nil).
|
||||
StringersV("stringers_v", net.IP{127, 0, 0, 1}, time.Time{}.AddDate(0, 1, 2), 1*time.Second, nil).
|
||||
StringersV("stringers_v_empty").
|
||||
Errs("errs", []error{errors.New("some error"), errors.New("some other error"), nil, loggableError{fmt.Errorf("oops")}, nonLoggableError{fmt.Errorf("whoops"), 401}}).
|
||||
Errs("errs_nil", nil).
|
||||
Bools("bool", []bool{true, false}).
|
||||
Ints("int", []int{1, 2}).
|
||||
Ints8("int8", []int8{2, 3}).
|
||||
@@ -196,7 +206,7 @@ func TestWithPlurals(t *testing.T) {
|
||||
log := ctx.Logger()
|
||||
log.Log().Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()),
|
||||
`{"strings":["foo","bar"],"strings_nil":[],"stringers":["127.0.0.1",null],"stringers_nil":null,"errs":["some error","some other error",null,{"l":"OOPS"},"whoops"],"bool":[true,false],"int":[1,2],"int8":[2,3],"int16":[3,4],"int32":[4,5],"int64":[5,6],"uint":[6,7],"uint8":[7,8],"uint16":[8,9],"uint32":[9,10],"uint64":[10,11],"float32":[1.1,2.2],"float64":[2.2,3.3],"time":["0001-02-03T00:00:00Z","0005-06-07T00:00:00Z"],"dur":[1000,2000]}`+"\n"; got != want {
|
||||
`{"objs":[{"Pub":"a","Tag":"z","priv":1}],"objs_nil":[],"objs_v":[{"Pub":"A","Tag":"Z","priv":2}],"objs_v_empty":[],"strs":["foo","bar"],"strs_nil":[],"strs_v":["baz","fizz"],"strs_v_empty":[],"stringers":["127.0.0.1","0001-02-03 00:00:00 +0000 UTC","1s",null],"stringers_nil":[],"stringers_v":["127.0.0.1","0001-02-03 00:00:00 +0000 UTC","1s",null],"stringers_v_empty":[],"errs":["some error","some other error",null,{"l":"OOPS"},"whoops"],"errs_nil":[],"bool":[true,false],"int":[1,2],"int8":[2,3],"int16":[3,4],"int32":[4,5],"int64":[5,6],"uint":[6,7],"uint8":[7,8],"uint16":[8,9],"uint32":[9,10],"uint64":[10,11],"float32":[1.1,2.2],"float64":[2.2,3.3],"time":["0001-02-03T00:00:00Z","0005-06-07T00:00:00Z"],"dur":[1000,2000]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -473,9 +483,9 @@ func TestFields(t *testing.T) {
|
||||
caller := fmt.Sprintf("%s:%d", file, line+3)
|
||||
log.Log().
|
||||
Caller().
|
||||
Object("obj", fixtureObj{"a", "z", 1}).
|
||||
Str("string", "foo").
|
||||
Stringer("stringer", net.IP{127, 0, 0, 1}).
|
||||
Stringer("stringer_nil", nil).
|
||||
Bytes("bytes", []byte("bar")).
|
||||
Hex("hex", []byte{0x12, 0xef}).
|
||||
RawJSON("json", []byte(`{"some":"json"}`)).
|
||||
@@ -510,7 +520,41 @@ func TestFields(t *testing.T) {
|
||||
Any("logobject", fixtureObj{"a", "z", 1}).
|
||||
Stack().
|
||||
Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","string":"foo","stringer":"127.0.0.1","stringer_nil":null,"bytes":"bar","hex":"12ef","json":{"some":"json"},"cbor":"data:application/cbor;base64,gwGCAgOCBAU=","func":"func_output","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"ipv4":"192.168.0.100","ipv6":"2001:db8:85a3::8a2e:370:7334","mac":"00:14:22:01:23:45","pfxv4":"192.168.0.100/24","pfxv6":"2001:db8:85a3::8a2e:370:7334/64","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000,"type":"string","any":{"A":"test"},"logobject":{"Pub":"a","Tag":"z","priv":1}}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","obj":{"Pub":"a","Tag":"z","priv":1},"string":"foo","stringer":"127.0.0.1","bytes":"bar","hex":"12ef","json":{"some":"json"},"cbor":"data:application/cbor;base64,gwGCAgOCBAU=","func":"func_output","error":"some error","bool":true,"int":1,"int8":2,"int16":3,"int32":4,"int64":5,"uint":6,"uint8":7,"uint16":8,"uint32":9,"uint64":10,"ipv4":"192.168.0.100","ipv6":"2001:db8:85a3::8a2e:370:7334","mac":"00:14:22:01:23:45","pfxv4":"192.168.0.100/24","pfxv6":"2001:db8:85a3::8a2e:370:7334/64","float32":11.1234,"float64":12.321321321,"dur":1000,"time":"0001-01-01T00:00:00Z","diff":10000,"type":"string","any":{"A":"test"},"logobject":{"Pub":"a","Tag":"z","priv":1}}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFieldsArrayNil(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().
|
||||
Objects("objs", nil).
|
||||
ObjectsV("objs_v").
|
||||
Strs("strs", nil).
|
||||
StrsV("strs_v").
|
||||
Stringers("stringers", nil).
|
||||
StringersV("stringers_v").
|
||||
Errs("err", nil).
|
||||
Bools("bool", nil).
|
||||
Ints("int", nil).
|
||||
Ints8("int8", nil).
|
||||
Ints16("int16", nil).
|
||||
Ints32("int32", nil).
|
||||
Ints64("int64", nil).
|
||||
Uints("uint", nil).
|
||||
Uints8("uint8", nil).
|
||||
Uints16("uint16", nil).
|
||||
Uints32("uint32", nil).
|
||||
Uints64("uint64", nil).
|
||||
Floats32("float32", nil).
|
||||
Floats64("float64", nil).
|
||||
Durs("dur", nil).
|
||||
Times("time", nil).
|
||||
IPAddrs("ip", nil).
|
||||
IPPrefixes("pfx", nil).
|
||||
Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"objs":[],"objs_v":[],"strs":[],"strs_v":[],"stringers":[],"stringers_v":[],"err":[],"bool":[],"int":[],"int8":[],"int16":[],"int32":[],"int64":[],"uint":[],"uint8":[],"uint16":[],"uint32":[],"uint64":[],"float32":[],"float64":[],"dur":[],"time":[],"ip":[],"pfx":[]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -519,8 +563,12 @@ func TestFieldsArrayEmpty(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().
|
||||
Strs("string", []string{}).
|
||||
Stringers("stringer", []fmt.Stringer{}).
|
||||
Objects("objs", []LogObjectMarshaler{}).
|
||||
ObjectsV("objs_v").
|
||||
Strs("strs", []string{}).
|
||||
StrsV("strs_v").
|
||||
Stringers("stringers", []fmt.Stringer{}).
|
||||
StringersV("stringers_v").
|
||||
Errs("err", []error{}).
|
||||
Bools("bool", []bool{}).
|
||||
Ints("int", []int{}).
|
||||
@@ -540,7 +588,7 @@ func TestFieldsArrayEmpty(t *testing.T) {
|
||||
IPAddrs("ip", []net.IP{}).
|
||||
IPPrefixes("pfx", []net.IPNet{}).
|
||||
Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":[],"stringer":[],"err":[],"bool":[],"int":[],"int8":[],"int16":[],"int32":[],"int64":[],"uint":[],"uint8":[],"uint16":[],"uint32":[],"uint64":[],"float32":[],"float64":[],"dur":[],"time":[],"ip":[],"pfx":[]}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"objs":[],"objs_v":[],"strs":[],"strs_v":[],"stringers":[],"stringers_v":[],"err":[],"bool":[],"int":[],"int8":[],"int16":[],"int32":[],"int64":[],"uint":[],"uint8":[],"uint16":[],"uint32":[],"uint64":[],"float32":[],"float64":[],"dur":[],"time":[],"ip":[],"pfx":[]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -549,8 +597,12 @@ func TestFieldsArraySingleElement(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().
|
||||
Strs("string", []string{"foo"}).
|
||||
Objects("obj", []LogObjectMarshaler{fixtureObj{"a", "z", 1}}).
|
||||
ObjectsV("obj_v", fixtureObj{"A", "Z", 2}).
|
||||
Strs("str", []string{"foo"}).
|
||||
StrsV("str_v", "baz").
|
||||
Stringers("stringer", []fmt.Stringer{net.IP{127, 0, 0, 1}}).
|
||||
StringersV("stringer_v", net.IPv6loopback).
|
||||
Errs("err", []error{errors.New("some error")}).
|
||||
Bools("bool", []bool{true}).
|
||||
Ints("int", []int{1}).
|
||||
@@ -570,7 +622,7 @@ func TestFieldsArraySingleElement(t *testing.T) {
|
||||
IPAddrs("ip", []net.IP{{192, 168, 0, 100}}).
|
||||
IPPrefixes("pfx", []net.IPNet{{IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}}).
|
||||
Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":["foo"],"stringer":["127.0.0.1"],"err":["some error"],"bool":[true],"int":[1],"int8":[2],"int16":[3],"int32":[4],"int64":[5],"uint":[6],"uint8":[7],"uint16":[8],"uint32":[9],"uint64":[10],"float32":[11],"float64":[12],"dur":[1000],"time":["0001-01-01T00:00:00Z"],"ip":["192.168.0.100"],"pfx":["192.168.0.100/24"]}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"obj":[{"Pub":"a","Tag":"z","priv":1}],"obj_v":[{"Pub":"A","Tag":"Z","priv":2}],"str":["foo"],"str_v":["baz"],"stringer":["127.0.0.1"],"stringer_v":["::1"],"err":["some error"],"bool":[true],"int":[1],"int8":[2],"int16":[3],"int32":[4],"int64":[5],"uint":[6],"uint8":[7],"uint16":[8],"uint32":[9],"uint64":[10],"float32":[11],"float64":[12],"dur":[1000],"time":["0001-01-01T00:00:00Z"],"ip":["192.168.0.100"],"pfx":["192.168.0.100/24"]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -579,8 +631,12 @@ func TestFieldsArrayMultipleElement(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
log.Log().
|
||||
Strs("string", []string{"foo", "bar"}).
|
||||
Stringers("stringer", []fmt.Stringer{nil, net.IP{127, 0, 0, 1}}).
|
||||
Objects("objs", []LogObjectMarshaler{fixtureObj{"a", "z", 1}, fixtureObj{"b", "y", 2}}).
|
||||
ObjectsV("objs_v", fixtureObj{"A", "Z", 3}, fixtureObj{"B", "Y", 4}).
|
||||
Strs("strs", []string{"foo", "bar"}).
|
||||
StrsV("strs_v", "baz", "fizz").
|
||||
Stringers("stringers", []fmt.Stringer{nil, net.IP{127, 0, 0, 1}}).
|
||||
StringersV("stringers_v", net.IPv4bcast, net.IPv6loopback).
|
||||
Errs("err", []error{errors.New("some error"), nil}).
|
||||
Bools("bool", []bool{true, false}).
|
||||
Ints("int", []int{1, 0}).
|
||||
@@ -600,7 +656,7 @@ func TestFieldsArrayMultipleElement(t *testing.T) {
|
||||
IPAddrs("ip", []net.IP{{192, 168, 0, 100}, {0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34}}).
|
||||
IPPrefixes("pfx", []net.IPNet{{IP: net.IP{192, 168, 0, 100}, Mask: net.CIDRMask(24, 32)}, {IP: net.IP{0x20, 0x01, 0x0d, 0xb8, 0x85, 0xa3, 0x00, 0x00, 0x00, 0x00, 0x8a, 0x2e, 0x03, 0x70, 0x73, 0x34}, Mask: net.CIDRMask(64, 128)}}).
|
||||
Msg("")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"string":["foo","bar"],"stringer":[null,"127.0.0.1"],"err":["some error",null],"bool":[true,false],"int":[1,0],"int8":[2,0],"int16":[3,0],"int32":[4,0],"int64":[5,0],"uint":[6,0],"uint8":[7,0],"uint16":[8,0],"uint32":[9,0],"uint64":[10,0],"float32":[11,0],"float64":[12,0],"dur":[1000,0],"time":["0001-01-01T00:00:00Z","0001-01-01T00:00:00Z"],"ip":["192.168.0.100","2001:db8:85a3::8a2e:370:7334"],"pfx":["192.168.0.100/24","2001:db8:85a3::8a2e:370:7334/64"]}`+"\n"; got != want {
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"objs":[{"Pub":"a","Tag":"z","priv":1},{"Pub":"b","Tag":"y","priv":2}],"objs_v":[{"Pub":"A","Tag":"Z","priv":3},{"Pub":"B","Tag":"Y","priv":4}],"strs":["foo","bar"],"strs_v":["baz","fizz"],"stringers":[null,"127.0.0.1"],"stringers_v":["255.255.255.255","::1"],"err":["some error",null],"bool":[true,false],"int":[1,0],"int8":[2,0],"int16":[3,0],"int32":[4,0],"int64":[5,0],"uint":[6,0],"uint8":[7,0],"uint16":[8,0],"uint32":[9,0],"uint64":[10,0],"float32":[11,0],"float64":[12,0],"dur":[1000,0],"time":["0001-01-01T00:00:00Z","0001-01-01T00:00:00Z"],"ip":["192.168.0.100","2001:db8:85a3::8a2e:370:7334"],"pfx":["192.168.0.100/24","2001:db8:85a3::8a2e:370:7334/64"]}`+"\n"; got != want {
|
||||
t.Errorf("invalid log output:\ngot: %v\nwant: %v", got, want)
|
||||
}
|
||||
}
|
||||
@@ -610,8 +666,14 @@ func TestFieldsDisabled(t *testing.T) {
|
||||
log := New(out).Level(InfoLevel)
|
||||
now := time.Now()
|
||||
log.Debug().
|
||||
Objects("obj", []LogObjectMarshaler{fixtureObj{"a", "z", 1}}).
|
||||
ObjectsV("obj_v", fixtureObj{"A", "Z", 2}).
|
||||
Str("string", "foo").
|
||||
Strs("strs", []string{"foo"}).
|
||||
StrsV("strs_v", "baz").
|
||||
Stringer("stringer", net.IP{127, 0, 0, 1}).
|
||||
Stringers("stringers", []fmt.Stringer{net.IP{127, 0, 0, 1}}).
|
||||
StringersV("stringers_v", net.IPv6loopback).
|
||||
Bytes("bytes", []byte("bar")).
|
||||
Hex("hex", []byte{0x12, 0xef}).
|
||||
AnErr("some_err", nil).
|
||||
@@ -1096,9 +1158,12 @@ func TestCallerMarshalFunc(t *testing.T) {
|
||||
out := &bytes.Buffer{}
|
||||
log := New(out)
|
||||
|
||||
var pc uintptr
|
||||
var file string
|
||||
var line int
|
||||
// test default behaviour this is really brittle due to the line numbers
|
||||
// actually mattering for validation
|
||||
pc, file, line, _ := runtime.Caller(0)
|
||||
pc, file, line, _ = runtime.Caller(0)
|
||||
caller := fmt.Sprintf("%s:%d", file, line+2)
|
||||
log.Log().Caller().Msg("msg")
|
||||
if got, want := decodeIfBinaryToString(out.Bytes()), `{"caller":"`+caller+`","message":"msg"}`+"\n"; got != want {
|
||||
|
||||
Reference in New Issue
Block a user