1package level 2 3import "github.com/go-kit/kit/log" 4 5// Error returns a logger that includes a Key/ErrorValue pair. 6func Error(logger log.Logger) log.Logger { 7 return log.WithPrefix(logger, Key(), ErrorValue()) 8} 9 10// Warn returns a logger that includes a Key/WarnValue pair. 11func Warn(logger log.Logger) log.Logger { 12 return log.WithPrefix(logger, Key(), WarnValue()) 13} 14 15// Info returns a logger that includes a Key/InfoValue pair. 16func Info(logger log.Logger) log.Logger { 17 return log.WithPrefix(logger, Key(), InfoValue()) 18} 19 20// Debug returns a logger that includes a Key/DebugValue pair. 21func Debug(logger log.Logger) log.Logger { 22 return log.WithPrefix(logger, Key(), DebugValue()) 23} 24 25// NewFilter wraps next and implements level filtering. See the commentary on 26// the Option functions for a detailed description of how to configure levels. 27// If no options are provided, all leveled log events created with Debug, 28// Info, Warn or Error helper methods are squelched and non-leveled log 29// events are passed to next unmodified. 30func NewFilter(next log.Logger, options ...Option) log.Logger { 31 l := &logger{ 32 next: next, 33 } 34 for _, option := range options { 35 option(l) 36 } 37 return l 38} 39 40type logger struct { 41 next log.Logger 42 allowed level 43 squelchNoLevel bool 44 errNotAllowed error 45 errNoLevel error 46} 47 48func (l *logger) Log(keyvals ...interface{}) error { 49 var hasLevel, levelAllowed bool 50 for i := 1; i < len(keyvals); i += 2 { 51 if v, ok := keyvals[i].(*levelValue); ok { 52 hasLevel = true 53 levelAllowed = l.allowed&v.level != 0 54 break 55 } 56 } 57 if !hasLevel && l.squelchNoLevel { 58 return l.errNoLevel 59 } 60 if hasLevel && !levelAllowed { 61 return l.errNotAllowed 62 } 63 return l.next.Log(keyvals...) 64} 65 66// Option sets a parameter for the leveled logger. 67type Option func(*logger) 68 69// AllowAll is an alias for AllowDebug. 70func AllowAll() Option { 71 return AllowDebug() 72} 73 74// AllowDebug allows error, warn, info and debug level log events to pass. 75func AllowDebug() Option { 76 return allowed(levelError | levelWarn | levelInfo | levelDebug) 77} 78 79// AllowInfo allows error, warn and info level log events to pass. 80func AllowInfo() Option { 81 return allowed(levelError | levelWarn | levelInfo) 82} 83 84// AllowWarn allows error and warn level log events to pass. 85func AllowWarn() Option { 86 return allowed(levelError | levelWarn) 87} 88 89// AllowError allows only error level log events to pass. 90func AllowError() Option { 91 return allowed(levelError) 92} 93 94// AllowNone allows no leveled log events to pass. 95func AllowNone() Option { 96 return allowed(0) 97} 98 99func allowed(allowed level) Option { 100 return func(l *logger) { l.allowed = allowed } 101} 102 103// ErrNotAllowed sets the error to return from Log when it squelches a log 104// event disallowed by the configured Allow[Level] option. By default, 105// ErrNotAllowed is nil; in this case the log event is squelched with no 106// error. 107func ErrNotAllowed(err error) Option { 108 return func(l *logger) { l.errNotAllowed = err } 109} 110 111// SquelchNoLevel instructs Log to squelch log events with no level, so that 112// they don't proceed through to the wrapped logger. If SquelchNoLevel is set 113// to true and a log event is squelched in this way, the error value 114// configured with ErrNoLevel is returned to the caller. 115func SquelchNoLevel(squelch bool) Option { 116 return func(l *logger) { l.squelchNoLevel = squelch } 117} 118 119// ErrNoLevel sets the error to return from Log when it squelches a log event 120// with no level. By default, ErrNoLevel is nil; in this case the log event is 121// squelched with no error. 122func ErrNoLevel(err error) Option { 123 return func(l *logger) { l.errNoLevel = err } 124} 125 126// NewInjector wraps next and returns a logger that adds a Key/level pair to 127// the beginning of log events that don't already contain a level. In effect, 128// this gives a default level to logs without a level. 129func NewInjector(next log.Logger, level Value) log.Logger { 130 return &injector{ 131 next: next, 132 level: level, 133 } 134} 135 136type injector struct { 137 next log.Logger 138 level interface{} 139} 140 141func (l *injector) Log(keyvals ...interface{}) error { 142 for i := 1; i < len(keyvals); i += 2 { 143 if _, ok := keyvals[i].(*levelValue); ok { 144 return l.next.Log(keyvals...) 145 } 146 } 147 kvs := make([]interface{}, len(keyvals)+2) 148 kvs[0], kvs[1] = key, l.level 149 copy(kvs[2:], keyvals) 150 return l.next.Log(kvs...) 151} 152 153// Value is the interface that each of the canonical level values implement. 154// It contains unexported methods that prevent types from other packages from 155// implementing it and guaranteeing that NewFilter can distinguish the levels 156// defined in this package from all other values. 157type Value interface { 158 String() string 159 levelVal() 160} 161 162// Key returns the unique key added to log events by the loggers in this 163// package. 164func Key() interface{} { return key } 165 166// ErrorValue returns the unique value added to log events by Error. 167func ErrorValue() Value { return errorValue } 168 169// WarnValue returns the unique value added to log events by Warn. 170func WarnValue() Value { return warnValue } 171 172// InfoValue returns the unique value added to log events by Info. 173func InfoValue() Value { return infoValue } 174 175// DebugValue returns the unique value added to log events by Warn. 176func DebugValue() Value { return debugValue } 177 178var ( 179 // key is of type interface{} so that it allocates once during package 180 // initialization and avoids allocating every time the value is added to a 181 // []interface{} later. 182 key interface{} = "level" 183 184 errorValue = &levelValue{level: levelError, name: "error"} 185 warnValue = &levelValue{level: levelWarn, name: "warn"} 186 infoValue = &levelValue{level: levelInfo, name: "info"} 187 debugValue = &levelValue{level: levelDebug, name: "debug"} 188) 189 190type level byte 191 192const ( 193 levelDebug level = 1 << iota 194 levelInfo 195 levelWarn 196 levelError 197) 198 199type levelValue struct { 200 name string 201 level 202} 203 204func (v *levelValue) String() string { return v.name } 205func (v *levelValue) levelVal() {} 206