| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- package level
- import "github.com/go-kit/kit/log"
- // Error returns a logger that includes a Key/ErrorValue pair.
- func Error(logger log.Logger) log.Logger {
- return log.WithPrefix(logger, Key(), ErrorValue())
- }
- // Warn returns a logger that includes a Key/WarnValue pair.
- func Warn(logger log.Logger) log.Logger {
- return log.WithPrefix(logger, Key(), WarnValue())
- }
- // Info returns a logger that includes a Key/InfoValue pair.
- func Info(logger log.Logger) log.Logger {
- return log.WithPrefix(logger, Key(), InfoValue())
- }
- // Debug returns a logger that includes a Key/DebugValue pair.
- func Debug(logger log.Logger) log.Logger {
- return log.WithPrefix(logger, Key(), DebugValue())
- }
- // NewFilter wraps next and implements level filtering. See the commentary on
- // the Option functions for a detailed description of how to configure levels.
- // If no options are provided, all leveled log events created with Debug,
- // Info, Warn or Error helper methods are squelched and non-leveled log
- // events are passed to next unmodified.
- func NewFilter(next log.Logger, options ...Option) log.Logger {
- l := &logger{
- next: next,
- }
- for _, option := range options {
- option(l)
- }
- return l
- }
- type logger struct {
- next log.Logger
- allowed level
- squelchNoLevel bool
- errNotAllowed error
- errNoLevel error
- }
- func (l *logger) Log(keyvals ...interface{}) error {
- var hasLevel, levelAllowed bool
- for i := 1; i < len(keyvals); i += 2 {
- if v, ok := keyvals[i].(*levelValue); ok {
- hasLevel = true
- levelAllowed = l.allowed&v.level != 0
- break
- }
- }
- if !hasLevel && l.squelchNoLevel {
- return l.errNoLevel
- }
- if hasLevel && !levelAllowed {
- return l.errNotAllowed
- }
- return l.next.Log(keyvals...)
- }
- // Option sets a parameter for the leveled logger.
- type Option func(*logger)
- // AllowAll is an alias for AllowDebug.
- func AllowAll() Option {
- return AllowDebug()
- }
- // AllowDebug allows error, warn, info and debug level log events to pass.
- func AllowDebug() Option {
- return allowed(levelError | levelWarn | levelInfo | levelDebug)
- }
- // AllowInfo allows error, warn and info level log events to pass.
- func AllowInfo() Option {
- return allowed(levelError | levelWarn | levelInfo)
- }
- // AllowWarn allows error and warn level log events to pass.
- func AllowWarn() Option {
- return allowed(levelError | levelWarn)
- }
- // AllowError allows only error level log events to pass.
- func AllowError() Option {
- return allowed(levelError)
- }
- // AllowNone allows no leveled log events to pass.
- func AllowNone() Option {
- return allowed(0)
- }
- func allowed(allowed level) Option {
- return func(l *logger) { l.allowed = allowed }
- }
- // ErrNotAllowed sets the error to return from Log when it squelches a log
- // event disallowed by the configured Allow[Level] option. By default,
- // ErrNotAllowed is nil; in this case the log event is squelched with no
- // error.
- func ErrNotAllowed(err error) Option {
- return func(l *logger) { l.errNotAllowed = err }
- }
- // SquelchNoLevel instructs Log to squelch log events with no level, so that
- // they don't proceed through to the wrapped logger. If SquelchNoLevel is set
- // to true and a log event is squelched in this way, the error value
- // configured with ErrNoLevel is returned to the caller.
- func SquelchNoLevel(squelch bool) Option {
- return func(l *logger) { l.squelchNoLevel = squelch }
- }
- // ErrNoLevel sets the error to return from Log when it squelches a log event
- // with no level. By default, ErrNoLevel is nil; in this case the log event is
- // squelched with no error.
- func ErrNoLevel(err error) Option {
- return func(l *logger) { l.errNoLevel = err }
- }
- // NewInjector wraps next and returns a logger that adds a Key/level pair to
- // the beginning of log events that don't already contain a level. In effect,
- // this gives a default level to logs without a level.
- func NewInjector(next log.Logger, level Value) log.Logger {
- return &injector{
- next: next,
- level: level,
- }
- }
- type injector struct {
- next log.Logger
- level interface{}
- }
- func (l *injector) Log(keyvals ...interface{}) error {
- for i := 1; i < len(keyvals); i += 2 {
- if _, ok := keyvals[i].(*levelValue); ok {
- return l.next.Log(keyvals...)
- }
- }
- kvs := make([]interface{}, len(keyvals)+2)
- kvs[0], kvs[1] = key, l.level
- copy(kvs[2:], keyvals)
- return l.next.Log(kvs...)
- }
- // Value is the interface that each of the canonical level values implement.
- // It contains unexported methods that prevent types from other packages from
- // implementing it and guaranteeing that NewFilter can distinguish the levels
- // defined in this package from all other values.
- type Value interface {
- String() string
- levelVal()
- }
- // Key returns the unique key added to log events by the loggers in this
- // package.
- func Key() interface{} { return key }
- // ErrorValue returns the unique value added to log events by Error.
- func ErrorValue() Value { return errorValue }
- // WarnValue returns the unique value added to log events by Warn.
- func WarnValue() Value { return warnValue }
- // InfoValue returns the unique value added to log events by Info.
- func InfoValue() Value { return infoValue }
- // DebugValue returns the unique value added to log events by Warn.
- func DebugValue() Value { return debugValue }
- var (
- // key is of type interface{} so that it allocates once during package
- // initialization and avoids allocating every time the value is added to a
- // []interface{} later.
- key interface{} = "level"
- errorValue = &levelValue{level: levelError, name: "error"}
- warnValue = &levelValue{level: levelWarn, name: "warn"}
- infoValue = &levelValue{level: levelInfo, name: "info"}
- debugValue = &levelValue{level: levelDebug, name: "debug"}
- )
- type level byte
- const (
- levelDebug level = 1 << iota
- levelInfo
- levelWarn
- levelError
- )
- type levelValue struct {
- name string
- level
- }
- func (v *levelValue) String() string { return v.name }
- func (v *levelValue) levelVal() {}
|