1
0
mirror of https://github.com/rs/zerolog synced 2026-06-08 17:13:30 +00:00
Files
rs-zerolog/benchmark_test.go
T
Marc Brooks e133b6a517 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
2026-03-27 18:49:07 +00:00

373 lines
9.1 KiB
Go

package zerolog
import (
"errors"
"io"
"testing"
"time"
)
var (
errExample = errors.New("fail")
fakeMessage = "Test logging, but use a somewhat realistic message length."
)
func BenchmarkLogEmpty(b *testing.B) {
logger := New(io.Discard)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Log().Msg("")
}
})
}
func BenchmarkDisabled(b *testing.B) {
logger := New(io.Discard).Level(Disabled)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(fakeMessage)
}
})
}
func BenchmarkInfo(b *testing.B) {
logger := New(io.Discard)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(fakeMessage)
}
})
}
func BenchmarkContextFields(b *testing.B) {
logger := New(io.Discard).With().
Str("string", "four!").
Time("time", time.Time{}).
Int("int", 123).
Float32("float", -2.203230293249593).
Logger()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().Msg(fakeMessage)
}
})
}
func BenchmarkContextAppend(b *testing.B) {
logger := New(io.Discard).With().
Str("foo", "bar").
Logger()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.With().Str("bar", "baz")
}
})
}
func BenchmarkLogFields(b *testing.B) {
logger := New(io.Discard)
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
logger.Info().
Str("string", "four!").
Time("time", time.Time{}).
Int("int", 123).
Float32("float", -2.203230293249593).
Msg(fakeMessage)
}
})
}
func BenchmarkLogArrayObject(b *testing.B) {
obj1 := fixtureObj{"a", "b", 2}
obj2 := fixtureObj{"c", "d", 3}
obj3 := fixtureObj{"e", "f", 4}
logger := New(io.Discard)
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
arr := Arr()
arr.Object(&obj1)
arr.Object(&obj2)
arr.Object(&obj3)
logger.Info().Array("objects", arr).Msg("test")
}
}
func BenchmarkLogFieldType(b *testing.B) {
fixtures := makeFieldFixtures()
types := map[string]func(e *Event) *Event{
"Any": func(e *Event) *Event {
return e.Any("k", fixtures.Interfaces[0])
},
"Bool": func(e *Event) *Event {
return e.Bool("k", fixtures.Bools[0])
},
"Bools": func(e *Event) *Event {
return e.Bools("k", fixtures.Bools)
},
"Bytes": func(e *Event) *Event {
return e.Bytes("k", fixtures.Bytes)
},
"Hex": func(e *Event) *Event {
return e.Hex("k", fixtures.Bytes)
},
"Int": func(e *Event) *Event {
return e.Int("k", fixtures.Ints[0])
},
"Ints": func(e *Event) *Event {
return e.Ints("k", fixtures.Ints)
},
"Float32": func(e *Event) *Event {
return e.Float32("k", fixtures.Floats32[0])
},
"Floats32": func(e *Event) *Event {
return e.Floats32("k", fixtures.Floats32)
},
"Float64": func(e *Event) *Event {
return e.Float64("k", fixtures.Floats64[0])
},
"Floats64": func(e *Event) *Event {
return e.Floats64("k", fixtures.Floats64)
},
"Str": func(e *Event) *Event {
return e.Str("k", fixtures.Strings[0])
},
"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])
},
"Errs": func(e *Event) *Event {
return e.Errs("k", fixtures.Errs)
},
"Ctx": func(e *Event) *Event {
return e.Ctx(fixtures.Ctx)
},
"Time": func(e *Event) *Event {
return e.Time("k", fixtures.Times[0])
},
"Times": func(e *Event) *Event {
return e.Times("k", fixtures.Times)
},
"Dur": func(e *Event) *Event {
return e.Dur("k", fixtures.Durations[0])
},
"Durs": func(e *Event) *Event {
return e.Durs("k", fixtures.Durations)
},
"Interface": func(e *Event) *Event {
return e.Interface("k", fixtures.Interfaces[0])
},
"Interfaces": func(e *Event) *Event {
return e.Interface("k", fixtures.Interfaces)
},
"Interface(Object)": func(e *Event) *Event {
return e.Interface("k", fixtures.Objects[0])
},
"Interface(Objects)": func(e *Event) *Event {
return e.Interface("k", fixtures.Objects)
},
"Object": func(e *Event) *Event {
return e.Object("k", fixtures.Objects[0])
},
"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()
},
"IPAddr": func(e *Event) *Event {
return e.IPAddr("k", fixtures.IPAddrs[0])
},
"IPAddrs": func(e *Event) *Event {
return e.IPAddrs("k", fixtures.IPAddrs)
},
"IPPrefix": func(e *Event) *Event {
return e.IPPrefix("k", fixtures.IPPfxs[0])
},
"IPPrefixes": func(e *Event) *Event {
return e.IPPrefixes("k", fixtures.IPPfxs)
},
"MACAddr": func(e *Event) *Event {
return e.MACAddr("k", fixtures.MACAddr)
},
"Type": func(e *Event) *Event {
return e.Type("k", fixtures.Type)
},
}
logger := New(io.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("")
}
})
})
}
}
func BenchmarkContextFieldType(b *testing.B) {
oldFormat := TimeFieldFormat
TimeFieldFormat = TimeFormatUnix
defer func() { TimeFieldFormat = oldFormat }()
fixtures := makeFieldFixtures()
types := map[string]func(c Context) Context{
"Any": func(c Context) Context {
return c.Any("k", fixtures.Interfaces[0])
},
"Bool": func(c Context) Context {
return c.Bool("k", fixtures.Bools[0])
},
"Bools": func(c Context) Context {
return c.Bools("k", fixtures.Bools)
},
"Bytes": func(c Context) Context {
return c.Bytes("k", fixtures.Bytes)
},
"Hex": func(c Context) Context {
return c.Hex("k", fixtures.Bytes)
},
"Int": func(c Context) Context {
return c.Int("k", fixtures.Ints[0])
},
"Ints": func(c Context) Context {
return c.Ints("k", fixtures.Ints)
},
"Float32": func(c Context) Context {
return c.Float32("k", fixtures.Floats32[0])
},
"Floats32": func(c Context) Context {
return c.Floats32("k", fixtures.Floats32)
},
"Float64": func(c Context) Context {
return c.Float64("k", fixtures.Floats64[0])
},
"Floats64": func(c Context) Context {
return c.Floats64("k", fixtures.Floats64)
},
"Str": func(c Context) Context {
return c.Str("k", fixtures.Strings[0])
},
"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])
},
"Errs": func(c Context) Context {
return c.Errs("k", fixtures.Errs)
},
"Ctx": func(c Context) Context {
return c.Ctx(fixtures.Ctx)
},
"Time": func(c Context) Context {
return c.Time("k", fixtures.Times[0])
},
"Times": func(c Context) Context {
return c.Times("k", fixtures.Times)
},
"Dur": func(c Context) Context {
return c.Dur("k", fixtures.Durations[0])
},
"Durs": func(c Context) Context {
return c.Durs("k", fixtures.Durations)
},
"Interface": func(c Context) Context {
return c.Interface("k", fixtures.Interfaces[0])
},
"Interfaces": func(c Context) Context {
return c.Interface("k", fixtures.Interfaces)
},
"Interface(Object)": func(c Context) Context {
return c.Interface("k", fixtures.Objects[0])
},
"Interface(Objects)": func(c Context) Context {
return c.Interface("k", fixtures.Objects)
},
"Object": func(c Context) Context {
return c.Object("k", fixtures.Objects[0])
},
"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()
},
"IPAddr": func(c Context) Context {
return c.IPAddr("k", fixtures.IPAddrs[0])
},
"IPAddrs": func(c Context) Context {
return c.IPAddrs("k", fixtures.IPAddrs)
},
"IPPrefix": func(c Context) Context {
return c.IPPrefix("k", fixtures.IPPfxs[0])
},
"IPPrefixes": func(c Context) Context {
return c.IPPrefixes("k", fixtures.IPPfxs)
},
"MACAddr": func(c Context) Context {
return c.MACAddr("k", fixtures.MACAddr)
},
"Type": func(c Context) Context {
return c.Type("k", fixtures.Type)
},
}
logger := New(io.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() {
l := f(logger.With()).Logger()
l.Info().Msg("")
}
})
})
}
}