OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / tendermint / tmlibs / log / filter.go
1 package log
2
3 import "fmt"
4
5 type level byte
6
7 const (
8         levelDebug level = 1 << iota
9         levelInfo
10         levelError
11 )
12
13 type filter struct {
14         next           Logger
15         allowed        level            // XOR'd levels for default case
16         allowedKeyvals map[keyval]level // When key-value match, use this level
17 }
18
19 type keyval struct {
20         key   interface{}
21         value interface{}
22 }
23
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 {
29         l := &filter{
30                 next:           next,
31                 allowedKeyvals: make(map[keyval]level),
32         }
33         for _, option := range options {
34                 option(l)
35         }
36         return l
37 }
38
39 func (l *filter) Info(msg string, keyvals ...interface{}) {
40         levelAllowed := l.allowed&levelInfo != 0
41         if !levelAllowed {
42                 return
43         }
44         l.next.Info(msg, keyvals...)
45 }
46
47 func (l *filter) Debug(msg string, keyvals ...interface{}) {
48         levelAllowed := l.allowed&levelDebug != 0
49         if !levelAllowed {
50                 return
51         }
52         l.next.Debug(msg, keyvals...)
53 }
54
55 func (l *filter) Error(msg string, keyvals ...interface{}) {
56         levelAllowed := l.allowed&levelError != 0
57         if !levelAllowed {
58                 return
59         }
60         l.next.Error(msg, keyvals...)
61 }
62
63 // With implements Logger by constructing a new filter with a keyvals appended
64 // to the logger.
65 //
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.
68 //
69 // Examples:
70 //     logger = log.NewFilter(logger, log.AllowError(), log.AllowInfoWith("module", "crypto"))
71 //               logger.With("module", "crypto").Info("Hello") # produces "I... Hello module=crypto"
72 //
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
75 //
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}
83                         }
84                 }
85         }
86         return &filter{next: l.next.With(keyvals...), allowed: l.allowed, allowedKeyvals: l.allowedKeyvals}
87 }
88
89 //--------------------------------------------------------------------------------
90
91 // Option sets a parameter for the filter.
92 type Option func(*filter)
93
94 // AllowLevel returns an option for the given level or error if no option exist
95 // for such level.
96 func AllowLevel(lvl string) (Option, error) {
97         switch lvl {
98         case "debug":
99                 return AllowDebug(), nil
100         case "info":
101                 return AllowInfo(), nil
102         case "error":
103                 return AllowError(), nil
104         case "none":
105                 return AllowNone(), nil
106         default:
107                 return nil, fmt.Errorf("Expected either \"info\", \"debug\", \"error\" or \"none\" level, given %s", lvl)
108         }
109 }
110
111 // AllowAll is an alias for AllowDebug.
112 func AllowAll() Option {
113         return AllowDebug()
114 }
115
116 // AllowDebug allows error, info and debug level log events to pass.
117 func AllowDebug() Option {
118         return allowed(levelError | levelInfo | levelDebug)
119 }
120
121 // AllowInfo allows error and info level log events to pass.
122 func AllowInfo() Option {
123         return allowed(levelError | levelInfo)
124 }
125
126 // AllowError allows only error level log events to pass.
127 func AllowError() Option {
128         return allowed(levelError)
129 }
130
131 // AllowNone allows no leveled log events to pass.
132 func AllowNone() Option {
133         return allowed(0)
134 }
135
136 func allowed(allowed level) Option {
137         return func(l *filter) { l.allowed = allowed }
138 }
139
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 }
143 }
144
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 }
148 }
149
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 }
153 }
154
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 }
158 }