...
1 package level
2
3 import (
4 "errors"
5 "strings"
6
7 "github.com/go-kit/log"
8 )
9
10
11 var ErrInvalidLevelString = errors.New("invalid level string")
12
13
14 func Error(logger log.Logger) log.Logger {
15 return log.WithPrefix(logger, Key(), ErrorValue())
16 }
17
18
19 func Warn(logger log.Logger) log.Logger {
20 return log.WithPrefix(logger, Key(), WarnValue())
21 }
22
23
24 func Info(logger log.Logger) log.Logger {
25 return log.WithPrefix(logger, Key(), InfoValue())
26 }
27
28
29 func Debug(logger log.Logger) log.Logger {
30 return log.WithPrefix(logger, Key(), DebugValue())
31 }
32
33
34
35
36
37
38 func NewFilter(next log.Logger, options ...Option) log.Logger {
39 l := &logger{
40 next: next,
41 }
42 for _, option := range options {
43 option(l)
44 }
45 return l
46 }
47
48 type logger struct {
49 next log.Logger
50 allowed level
51 squelchNoLevel bool
52 errNotAllowed error
53 errNoLevel error
54 }
55
56 func (l *logger) Log(keyvals ...interface{}) error {
57 var hasLevel, levelAllowed bool
58 for i := 1; i < len(keyvals); i += 2 {
59 if v, ok := keyvals[i].(*levelValue); ok {
60 hasLevel = true
61 levelAllowed = l.allowed&v.level != 0
62 break
63 }
64 }
65 if !hasLevel && l.squelchNoLevel {
66 return l.errNoLevel
67 }
68 if hasLevel && !levelAllowed {
69 return l.errNotAllowed
70 }
71 return l.next.Log(keyvals...)
72 }
73
74
75 type Option func(*logger)
76
77
78 func Allow(v Value) Option {
79 switch v {
80 case debugValue:
81 return AllowDebug()
82 case infoValue:
83 return AllowInfo()
84 case warnValue:
85 return AllowWarn()
86 case errorValue:
87 return AllowError()
88 default:
89 return AllowNone()
90 }
91 }
92
93
94 func AllowAll() Option {
95 return AllowDebug()
96 }
97
98
99 func AllowDebug() Option {
100 return allowed(levelError | levelWarn | levelInfo | levelDebug)
101 }
102
103
104 func AllowInfo() Option {
105 return allowed(levelError | levelWarn | levelInfo)
106 }
107
108
109 func AllowWarn() Option {
110 return allowed(levelError | levelWarn)
111 }
112
113
114 func AllowError() Option {
115 return allowed(levelError)
116 }
117
118
119 func AllowNone() Option {
120 return allowed(0)
121 }
122
123 func allowed(allowed level) Option {
124 return func(l *logger) { l.allowed = allowed }
125 }
126
127
128
129
130 func Parse(level string) (Value, error) {
131 switch strings.TrimSpace(strings.ToLower(level)) {
132 case debugValue.name:
133 return debugValue, nil
134 case infoValue.name:
135 return infoValue, nil
136 case warnValue.name:
137 return warnValue, nil
138 case errorValue.name:
139 return errorValue, nil
140 default:
141 return nil, ErrInvalidLevelString
142 }
143 }
144
145
146 func ParseDefault(level string, def Value) Value {
147 v, err := Parse(level)
148 if err != nil {
149 return def
150 }
151 return v
152 }
153
154
155
156
157
158 func ErrNotAllowed(err error) Option {
159 return func(l *logger) { l.errNotAllowed = err }
160 }
161
162
163
164
165
166 func SquelchNoLevel(squelch bool) Option {
167 return func(l *logger) { l.squelchNoLevel = squelch }
168 }
169
170
171
172
173 func ErrNoLevel(err error) Option {
174 return func(l *logger) { l.errNoLevel = err }
175 }
176
177
178
179
180 func NewInjector(next log.Logger, level Value) log.Logger {
181 return &injector{
182 next: next,
183 level: level,
184 }
185 }
186
187 type injector struct {
188 next log.Logger
189 level interface{}
190 }
191
192 func (l *injector) Log(keyvals ...interface{}) error {
193 for i := 1; i < len(keyvals); i += 2 {
194 if _, ok := keyvals[i].(*levelValue); ok {
195 return l.next.Log(keyvals...)
196 }
197 }
198 kvs := make([]interface{}, len(keyvals)+2)
199 kvs[0], kvs[1] = key, l.level
200 copy(kvs[2:], keyvals)
201 return l.next.Log(kvs...)
202 }
203
204
205
206
207
208 type Value interface {
209 String() string
210 levelVal()
211 }
212
213
214
215 func Key() interface{} { return key }
216
217
218 func ErrorValue() Value { return errorValue }
219
220
221 func WarnValue() Value { return warnValue }
222
223
224 func InfoValue() Value { return infoValue }
225
226
227 func DebugValue() Value { return debugValue }
228
229 var (
230
231
232
233 key interface{} = "level"
234
235 errorValue = &levelValue{level: levelError, name: "error"}
236 warnValue = &levelValue{level: levelWarn, name: "warn"}
237 infoValue = &levelValue{level: levelInfo, name: "info"}
238 debugValue = &levelValue{level: levelDebug, name: "debug"}
239 )
240
241 type level byte
242
243 const (
244 levelDebug level = 1 << iota
245 levelInfo
246 levelWarn
247 levelError
248 )
249
250 type levelValue struct {
251 name string
252 level
253 }
254
255 func (v *levelValue) String() string { return v.name }
256 func (v *levelValue) levelVal() {}
257
View as plain text