Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement log/experimental_levels #470

Merged
merged 8 commits into from
Mar 3, 2017
101 changes: 57 additions & 44 deletions log/experimental_level/benchmark_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,52 +8,65 @@ import (
"github.com/go-kit/kit/log/experimental_level"
)

func BenchmarkNopBaseline(b *testing.B) {
benchmarkRunner(b, log.NewNopLogger())
}

func BenchmarkNopDisallowedLevel(b *testing.B) {
benchmarkRunner(b, level.New(log.NewNopLogger(),
level.Allowed(level.AllowInfoAndAbove())))
}

func BenchmarkNopAllowedLevel(b *testing.B) {
benchmarkRunner(b, level.New(log.NewNopLogger(),
level.Allowed(level.AllowAll())))
}

func BenchmarkJSONBaseline(b *testing.B) {
benchmarkRunner(b, log.NewJSONLogger(ioutil.Discard))
}

func BenchmarkJSONDisallowedLevel(b *testing.B) {
benchmarkRunner(b, level.New(log.NewJSONLogger(ioutil.Discard),
level.Allowed(level.AllowInfoAndAbove())))
}

func BenchmarkJSONAllowedLevel(b *testing.B) {
benchmarkRunner(b, level.New(log.NewJSONLogger(ioutil.Discard),
level.Allowed(level.AllowAll())))
}

func BenchmarkLogfmtBaseline(b *testing.B) {
benchmarkRunner(b, log.NewLogfmtLogger(ioutil.Discard))
}
func Benchmark(b *testing.B) {
contexts := []struct {
name string
context func(log.Logger) log.Logger
}{
{"NoContext", func(l log.Logger) log.Logger {
return l
}},
{"TimeContext", func(l log.Logger) log.Logger {
return log.NewContext(l).With("time", log.DefaultTimestampUTC)
}},
{"CallerContext", func(l log.Logger) log.Logger {
return log.NewContext(l).With("caller", log.DefaultCaller)
}},
{"TimeCallerReqIDContext", func(l log.Logger) log.Logger {
return log.NewContext(l).With("time", log.DefaultTimestampUTC, "caller", log.DefaultCaller, "reqID", 29)
}},
}

func BenchmarkLogfmtDisallowedLevel(b *testing.B) {
benchmarkRunner(b, level.New(log.NewLogfmtLogger(ioutil.Discard),
level.Allowed(level.AllowInfoAndAbove())))
}
loggers := []struct {
name string
logger log.Logger
}{
{"Nop", log.NewNopLogger()},
{"Logfmt", log.NewLogfmtLogger(ioutil.Discard)},
{"JSON", log.NewJSONLogger(ioutil.Discard)},
}

func BenchmarkLogfmtAllowedLevel(b *testing.B) {
benchmarkRunner(b, level.New(log.NewLogfmtLogger(ioutil.Discard),
level.Allowed(level.AllowAll())))
}
filters := []struct {
name string
filter func(log.Logger) log.Logger
}{
{"Baseline", func(l log.Logger) log.Logger {
return l
}},
{"DisallowedLevel", func(l log.Logger) log.Logger {
return level.NewFilter(l, level.AllowInfo())
}},
{"AllowedLevel", func(l log.Logger) log.Logger {
return level.NewFilter(l, level.AllowAll())
}},
}

func benchmarkRunner(b *testing.B, logger log.Logger) {
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
level.Debug(logger).Log("foo", "bar")
for _, c := range contexts {
b.Run(c.name, func(b *testing.B) {
for _, f := range filters {
b.Run(f.name, func(b *testing.B) {
for _, l := range loggers {
b.Run(l.name, func(b *testing.B) {
logger := c.context(f.filter(l.logger))
b.ResetTimer()
b.ReportAllocs()
for i := 0; i < b.N; i++ {
level.Debug(logger).Log("foo", "bar")
}
})
}
})
}
})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🏄

}
}
13 changes: 5 additions & 8 deletions log/experimental_level/doc.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// definitely have breaking changes and may be deleted altogether. Be warned!
//
// To use the level package, create a logger as per normal in your func main,
// and wrap it with level.New.
// and wrap it with level.NewFilter.
//
// var logger log.Logger
// logger = log.NewLogfmtLogger(os.Stderr)
// logger = level.New(logger, level.Allowed(level.AllowInfoAndAbove())) // <--
// logger = level.NewFilter(logger, level.AllowInfoAndAbove()) // <--
// logger = log.NewContext(logger).With("ts", log.DefaultTimestampUTC)
//
// Then, at the callsites, use one of the level.Debug, Info, Warn, or Error
Expand All @@ -18,10 +18,7 @@
// level.Error(logger).Log("value", value)
// }
//
// The leveled logger allows precise control over what should happen if a log
// event is emitted without a level key, or if a squelched level is used. Check
// the Option functions for details. And, you can easily use non-default level
// values: create new string constants for whatever you want to change, pass
// them explicitly to the Allowed Option function, and write your own level.Foo-style
// helper methods.
// NewFilter allows precise control over what happens when a log event is
// emitted without a level key, or if a squelched level is used. Check the
// Option functions for details.
package level
25 changes: 25 additions & 0 deletions log/experimental_level/example_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package level_test

import (
"errors"
"os"

"github.com/go-kit/kit/log"
"github.com/go-kit/kit/log/experimental_level"
)

func Example_basic() {
// setup logger with level filter
logger := log.NewLogfmtLogger(os.Stdout)
logger = level.NewFilter(logger, level.AllowInfo())
logger = log.NewContext(logger).With("caller", log.DefaultCaller)

// use level helpers to log at different levels
level.Error(logger).Log("err", errors.New("bad data"))
level.Info(logger).Log("event", "data saved")
level.Debug(logger).Log("next item", 17) // filtered

// Output:
// level=error caller=example_test.go:18 err="bad data"
// level=info caller=example_test.go:19 event="data saved"
}
Loading