diff --git a/log/deprecated_levels/levels.go b/log/deprecated_levels/levels.go new file mode 100644 index 0000000..da6b681 --- /dev/null +++ b/log/deprecated_levels/levels.go @@ -0,0 +1,127 @@ +package levels + +import "github.com/go-kit/kit/log" + +// Levels provides a leveled logging wrapper around a logger. It has five +// levels: debug, info, warning (warn), error, and critical (crit). If you +// want a different set of levels, you can create your own levels type very +// easily, and you can elide the configuration. +type Levels struct { + ctx *log.Context + levelKey string + + // We have a choice between storing level values in string fields or + // making a separate context for each level. When using string fields the + // Log method must combine the base context, the level data, and the + // logged keyvals; but the With method only requires updating one context. + // If we instead keep a separate context for each level the Log method + // must only append the new keyvals; but the With method would have to + // update all five contexts. + + // Roughly speaking, storing multiple contexts breaks even if the ratio of + // Log/With calls is more than the number of levels. We have chosen to + // make the With method cheap and the Log method a bit more costly because + // we do not expect most applications to Log more than five times for each + // call to With. + + debugValue string + infoValue string + warnValue string + errorValue string + critValue string +} + +// New creates a new leveled logger, wrapping the passed logger. +func New(logger log.Logger, options ...Option) Levels { + l := Levels{ + ctx: log.NewContext(logger), + levelKey: "level", + + debugValue: "debug", + infoValue: "info", + warnValue: "warn", + errorValue: "error", + critValue: "crit", + } + for _, option := range options { + option(&l) + } + return l +} + +// With returns a new leveled logger that includes keyvals in all log events. +func (l Levels) With(keyvals ...interface{}) Levels { + return Levels{ + ctx: l.ctx.With(keyvals...), + levelKey: l.levelKey, + debugValue: l.debugValue, + infoValue: l.infoValue, + warnValue: l.warnValue, + errorValue: l.errorValue, + critValue: l.critValue, + } +} + +// Debug returns a debug level logger. +func (l Levels) Debug() log.Logger { + return l.ctx.WithPrefix(l.levelKey, l.debugValue) +} + +// Info returns an info level logger. +func (l Levels) Info() log.Logger { + return l.ctx.WithPrefix(l.levelKey, l.infoValue) +} + +// Warn returns a warning level logger. +func (l Levels) Warn() log.Logger { + return l.ctx.WithPrefix(l.levelKey, l.warnValue) +} + +// Error returns an error level logger. +func (l Levels) Error() log.Logger { + return l.ctx.WithPrefix(l.levelKey, l.errorValue) +} + +// Crit returns a critical level logger. +func (l Levels) Crit() log.Logger { + return l.ctx.WithPrefix(l.levelKey, l.critValue) +} + +// Option sets a parameter for leveled loggers. +type Option func(*Levels) + +// Key sets the key for the field used to indicate log level. By default, +// the key is "level". +func Key(key string) Option { + return func(l *Levels) { l.levelKey = key } +} + +// DebugValue sets the value for the field used to indicate the debug log +// level. By default, the value is "debug". +func DebugValue(value string) Option { + return func(l *Levels) { l.debugValue = value } +} + +// InfoValue sets the value for the field used to indicate the info log level. +// By default, the value is "info". +func InfoValue(value string) Option { + return func(l *Levels) { l.infoValue = value } +} + +// WarnValue sets the value for the field used to indicate the warning log +// level. By default, the value is "warn". +func WarnValue(value string) Option { + return func(l *Levels) { l.warnValue = value } +} + +// ErrorValue sets the value for the field used to indicate the error log +// level. By default, the value is "error". +func ErrorValue(value string) Option { + return func(l *Levels) { l.errorValue = value } +} + +// CritValue sets the value for the field used to indicate the critical log +// level. By default, the value is "crit". +func CritValue(value string) Option { + return func(l *Levels) { l.critValue = value } +} diff --git a/log/deprecated_levels/levels_test.go b/log/deprecated_levels/levels_test.go new file mode 100644 index 0000000..8d4a7f5 --- /dev/null +++ b/log/deprecated_levels/levels_test.go @@ -0,0 +1,65 @@ +package levels_test + +import ( + "bytes" + "os" + "testing" + + "github.com/go-kit/kit/log" + levels "github.com/go-kit/kit/log/deprecated_levels" +) + +func TestDefaultLevels(t *testing.T) { + buf := bytes.Buffer{} + logger := levels.New(log.NewLogfmtLogger(&buf)) + + logger.Debug().Log("msg", "résumé") // of course you'd want to do this + if want, have := "level=debug msg=résumé\n", buf.String(); want != have { + t.Errorf("want %#v, have %#v", want, have) + } + + buf.Reset() + logger.Info().Log("msg", "Åhus") + if want, have := "level=info msg=Åhus\n", buf.String(); want != have { + t.Errorf("want %#v, have %#v", want, have) + } + + buf.Reset() + logger.Error().Log("msg", "© violation") + if want, have := "level=error msg=\"© violation\"\n", buf.String(); want != have { + t.Errorf("want %#v, have %#v", want, have) + } + + buf.Reset() + logger.Crit().Log("msg", " ") + if want, have := "level=crit msg=\"\\t\"\n", buf.String(); want != have { + t.Errorf("want %#v, have %#v", want, have) + } +} + +func TestModifiedLevels(t *testing.T) { + buf := bytes.Buffer{} + logger := levels.New( + log.NewJSONLogger(&buf), + levels.Key("l"), + levels.DebugValue("dbg"), + levels.InfoValue("nfo"), + levels.WarnValue("wrn"), + levels.ErrorValue("err"), + levels.CritValue("crt"), + ) + logger.With("easter_island", "176°").Debug().Log("msg", "moai") + if want, have := `{"easter_island":"176°","l":"dbg","msg":"moai"}`+"\n", buf.String(); want != have { + t.Errorf("want %#v, have %#v", want, have) + } +} + +func ExampleLevels() { + logger := levels.New(log.NewLogfmtLogger(os.Stdout)) + logger.Debug().Log("msg", "hello") + logger.With("context", "foo").Warn().Log("err", "error") + + // Output: + // level=debug msg=hello + // level=warn context=foo err=error +} diff --git a/log/levels/levels.go b/log/levels/levels.go deleted file mode 100644 index da6b681..0000000 --- a/log/levels/levels.go +++ /dev/null @@ -1,127 +0,0 @@ -package levels - -import "github.com/go-kit/kit/log" - -// Levels provides a leveled logging wrapper around a logger. It has five -// levels: debug, info, warning (warn), error, and critical (crit). If you -// want a different set of levels, you can create your own levels type very -// easily, and you can elide the configuration. -type Levels struct { - ctx *log.Context - levelKey string - - // We have a choice between storing level values in string fields or - // making a separate context for each level. When using string fields the - // Log method must combine the base context, the level data, and the - // logged keyvals; but the With method only requires updating one context. - // If we instead keep a separate context for each level the Log method - // must only append the new keyvals; but the With method would have to - // update all five contexts. - - // Roughly speaking, storing multiple contexts breaks even if the ratio of - // Log/With calls is more than the number of levels. We have chosen to - // make the With method cheap and the Log method a bit more costly because - // we do not expect most applications to Log more than five times for each - // call to With. - - debugValue string - infoValue string - warnValue string - errorValue string - critValue string -} - -// New creates a new leveled logger, wrapping the passed logger. -func New(logger log.Logger, options ...Option) Levels { - l := Levels{ - ctx: log.NewContext(logger), - levelKey: "level", - - debugValue: "debug", - infoValue: "info", - warnValue: "warn", - errorValue: "error", - critValue: "crit", - } - for _, option := range options { - option(&l) - } - return l -} - -// With returns a new leveled logger that includes keyvals in all log events. -func (l Levels) With(keyvals ...interface{}) Levels { - return Levels{ - ctx: l.ctx.With(keyvals...), - levelKey: l.levelKey, - debugValue: l.debugValue, - infoValue: l.infoValue, - warnValue: l.warnValue, - errorValue: l.errorValue, - critValue: l.critValue, - } -} - -// Debug returns a debug level logger. -func (l Levels) Debug() log.Logger { - return l.ctx.WithPrefix(l.levelKey, l.debugValue) -} - -// Info returns an info level logger. -func (l Levels) Info() log.Logger { - return l.ctx.WithPrefix(l.levelKey, l.infoValue) -} - -// Warn returns a warning level logger. -func (l Levels) Warn() log.Logger { - return l.ctx.WithPrefix(l.levelKey, l.warnValue) -} - -// Error returns an error level logger. -func (l Levels) Error() log.Logger { - return l.ctx.WithPrefix(l.levelKey, l.errorValue) -} - -// Crit returns a critical level logger. -func (l Levels) Crit() log.Logger { - return l.ctx.WithPrefix(l.levelKey, l.critValue) -} - -// Option sets a parameter for leveled loggers. -type Option func(*Levels) - -// Key sets the key for the field used to indicate log level. By default, -// the key is "level". -func Key(key string) Option { - return func(l *Levels) { l.levelKey = key } -} - -// DebugValue sets the value for the field used to indicate the debug log -// level. By default, the value is "debug". -func DebugValue(value string) Option { - return func(l *Levels) { l.debugValue = value } -} - -// InfoValue sets the value for the field used to indicate the info log level. -// By default, the value is "info". -func InfoValue(value string) Option { - return func(l *Levels) { l.infoValue = value } -} - -// WarnValue sets the value for the field used to indicate the warning log -// level. By default, the value is "warn". -func WarnValue(value string) Option { - return func(l *Levels) { l.warnValue = value } -} - -// ErrorValue sets the value for the field used to indicate the error log -// level. By default, the value is "error". -func ErrorValue(value string) Option { - return func(l *Levels) { l.errorValue = value } -} - -// CritValue sets the value for the field used to indicate the critical log -// level. By default, the value is "crit". -func CritValue(value string) Option { - return func(l *Levels) { l.critValue = value } -} diff --git a/log/levels/levels_test.go b/log/levels/levels_test.go deleted file mode 100644 index 270963c..0000000 --- a/log/levels/levels_test.go +++ /dev/null @@ -1,65 +0,0 @@ -package levels_test - -import ( - "bytes" - "os" - "testing" - - "github.com/go-kit/kit/log" - "github.com/go-kit/kit/log/levels" -) - -func TestDefaultLevels(t *testing.T) { - buf := bytes.Buffer{} - logger := levels.New(log.NewLogfmtLogger(&buf)) - - logger.Debug().Log("msg", "résumé") // of course you'd want to do this - if want, have := "level=debug msg=résumé\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } - - buf.Reset() - logger.Info().Log("msg", "Åhus") - if want, have := "level=info msg=Åhus\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } - - buf.Reset() - logger.Error().Log("msg", "© violation") - if want, have := "level=error msg=\"© violation\"\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } - - buf.Reset() - logger.Crit().Log("msg", " ") - if want, have := "level=crit msg=\"\\t\"\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } -} - -func TestModifiedLevels(t *testing.T) { - buf := bytes.Buffer{} - logger := levels.New( - log.NewJSONLogger(&buf), - levels.Key("l"), - levels.DebugValue("dbg"), - levels.InfoValue("nfo"), - levels.WarnValue("wrn"), - levels.ErrorValue("err"), - levels.CritValue("crt"), - ) - logger.With("easter_island", "176°").Debug().Log("msg", "moai") - if want, have := `{"easter_island":"176°","l":"dbg","msg":"moai"}`+"\n", buf.String(); want != have { - t.Errorf("want %#v, have %#v", want, have) - } -} - -func ExampleLevels() { - logger := levels.New(log.NewLogfmtLogger(os.Stdout)) - logger.Debug().Log("msg", "hello") - logger.With("context", "foo").Warn().Log("err", "error") - - // Output: - // level=debug msg=hello - // level=warn context=foo err=error -}