8 levelDebug level = 1 << iota
15 allowed level // XOR'd levels for default case
16 allowedKeyvals map[keyval]level // When key-value match, use this level
24 // NewFilter wraps next and implements filtering. See the commentary on the
25 // Option functions for a detailed description of how to configure levels. If
26 // no options are provided, all leveled log events created with Debug, Info or
27 // Error helper methods are squelched.
28 func NewFilter(next Logger, options ...Option) Logger {
31 allowedKeyvals: make(map[keyval]level),
33 for _, option := range options {
39 func (l *filter) Info(msg string, keyvals ...interface{}) {
40 levelAllowed := l.allowed&levelInfo != 0
44 l.next.Info(msg, keyvals...)
47 func (l *filter) Debug(msg string, keyvals ...interface{}) {
48 levelAllowed := l.allowed&levelDebug != 0
52 l.next.Debug(msg, keyvals...)
55 func (l *filter) Error(msg string, keyvals ...interface{}) {
56 levelAllowed := l.allowed&levelError != 0
60 l.next.Error(msg, keyvals...)
63 // With implements Logger by constructing a new filter with a keyvals appended
66 // If custom level was set for a keyval pair using one of the
67 // Allow*With methods, it is used as the logger's level.
70 // logger = log.NewFilter(logger, log.AllowError(), log.AllowInfoWith("module", "crypto"))
71 // logger.With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto"
73 // logger = log.NewFilter(logger, log.AllowError(), log.AllowInfoWith("module", "crypto"), log.AllowNoneWith("user", "Sam"))
74 // logger.With("module", "crypto", "user", "Sam").Info("Hello") # returns nil
76 // logger = log.NewFilter(logger, log.AllowError(), log.AllowInfoWith("module", "crypto"), log.AllowNoneWith("user", "Sam"))
77 // logger.With("user", "Sam").With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto user=Sam"
78 func (l *filter) With(keyvals ...interface{}) Logger {
79 for i := len(keyvals) - 2; i >= 0; i -= 2 {
80 for kv, allowed := range l.allowedKeyvals {
81 if keyvals[i] == kv.key && keyvals[i+1] == kv.value {
82 return &filter{next: l.next.With(keyvals...), allowed: allowed, allowedKeyvals: l.allowedKeyvals}
86 return &filter{next: l.next.With(keyvals...), allowed: l.allowed, allowedKeyvals: l.allowedKeyvals}
89 //--------------------------------------------------------------------------------
91 // Option sets a parameter for the filter.
92 type Option func(*filter)
94 // AllowLevel returns an option for the given level or error if no option exist
96 func AllowLevel(lvl string) (Option, error) {
99 return AllowDebug(), nil
101 return AllowInfo(), nil
103 return AllowError(), nil
105 return AllowNone(), nil
107 return nil, fmt.Errorf("Expected either \"info\", \"debug\", \"error\" or \"none\" level, given %s", lvl)
111 // AllowAll is an alias for AllowDebug.
112 func AllowAll() Option {
116 // AllowDebug allows error, info and debug level log events to pass.
117 func AllowDebug() Option {
118 return allowed(levelError | levelInfo | levelDebug)
121 // AllowInfo allows error and info level log events to pass.
122 func AllowInfo() Option {
123 return allowed(levelError | levelInfo)
126 // AllowError allows only error level log events to pass.
127 func AllowError() Option {
128 return allowed(levelError)
131 // AllowNone allows no leveled log events to pass.
132 func AllowNone() Option {
136 func allowed(allowed level) Option {
137 return func(l *filter) { l.allowed = allowed }
140 // AllowDebugWith allows error, info and debug level log events to pass for a specific key value pair.
141 func AllowDebugWith(key interface{}, value interface{}) Option {
142 return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = levelError | levelInfo | levelDebug }
145 // AllowInfoWith allows error and info level log events to pass for a specific key value pair.
146 func AllowInfoWith(key interface{}, value interface{}) Option {
147 return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = levelError | levelInfo }
150 // AllowErrorWith allows only error level log events to pass for a specific key value pair.
151 func AllowErrorWith(key interface{}, value interface{}) Option {
152 return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = levelError }
155 // AllowNoneWith allows no leveled log events to pass for a specific key value pair.
156 func AllowNoneWith(key interface{}, value interface{}) Option {
157 return func(l *filter) { l.allowedKeyvals[keyval{key, value}] = 0 }