1 package level_test
2
3 import (
4 "bytes"
5 "errors"
6 "io"
7 "strings"
8 "testing"
9
10 "github.com/go-kit/log"
11 "github.com/go-kit/log/level"
12 )
13
14 func TestVariousLevels(t *testing.T) {
15 testCases := []struct {
16 name string
17 allowed level.Option
18 want string
19 }{
20 {
21 "Allow(DebugValue)",
22 level.Allow(level.DebugValue()),
23 strings.Join([]string{
24 `{"level":"debug","this is":"debug log"}`,
25 `{"level":"info","this is":"info log"}`,
26 `{"level":"warn","this is":"warn log"}`,
27 `{"level":"error","this is":"error log"}`,
28 }, "\n"),
29 },
30 {
31 "Allow(InfoValue)",
32 level.Allow(level.InfoValue()),
33 strings.Join([]string{
34 `{"level":"info","this is":"info log"}`,
35 `{"level":"warn","this is":"warn log"}`,
36 `{"level":"error","this is":"error log"}`,
37 }, "\n"),
38 },
39 {
40 "Allow(WarnValue)",
41 level.Allow(level.WarnValue()),
42 strings.Join([]string{
43 `{"level":"warn","this is":"warn log"}`,
44 `{"level":"error","this is":"error log"}`,
45 }, "\n"),
46 },
47 {
48 "Allow(ErrorValue)",
49 level.Allow(level.ErrorValue()),
50 strings.Join([]string{
51 `{"level":"error","this is":"error log"}`,
52 }, "\n"),
53 },
54 {
55 "Allow(nil)",
56 level.Allow(nil),
57 strings.Join([]string{}, "\n"),
58 },
59 {
60 "AllowAll",
61 level.AllowAll(),
62 strings.Join([]string{
63 `{"level":"debug","this is":"debug log"}`,
64 `{"level":"info","this is":"info log"}`,
65 `{"level":"warn","this is":"warn log"}`,
66 `{"level":"error","this is":"error log"}`,
67 }, "\n"),
68 },
69 {
70 "AllowDebug",
71 level.AllowDebug(),
72 strings.Join([]string{
73 `{"level":"debug","this is":"debug log"}`,
74 `{"level":"info","this is":"info log"}`,
75 `{"level":"warn","this is":"warn log"}`,
76 `{"level":"error","this is":"error log"}`,
77 }, "\n"),
78 },
79 {
80 "AllowInfo",
81 level.AllowInfo(),
82 strings.Join([]string{
83 `{"level":"info","this is":"info log"}`,
84 `{"level":"warn","this is":"warn log"}`,
85 `{"level":"error","this is":"error log"}`,
86 }, "\n"),
87 },
88 {
89 "AllowWarn",
90 level.AllowWarn(),
91 strings.Join([]string{
92 `{"level":"warn","this is":"warn log"}`,
93 `{"level":"error","this is":"error log"}`,
94 }, "\n"),
95 },
96 {
97 "AllowError",
98 level.AllowError(),
99 strings.Join([]string{
100 `{"level":"error","this is":"error log"}`,
101 }, "\n"),
102 },
103 {
104 "AllowNone",
105 level.AllowNone(),
106 ``,
107 },
108 }
109
110 for _, tc := range testCases {
111 t.Run(tc.name, func(t *testing.T) {
112 var buf bytes.Buffer
113 logger := level.NewFilter(log.NewJSONLogger(&buf), tc.allowed)
114
115 level.Debug(logger).Log("this is", "debug log")
116 level.Info(logger).Log("this is", "info log")
117 level.Warn(logger).Log("this is", "warn log")
118 level.Error(logger).Log("this is", "error log")
119
120 if want, have := tc.want, strings.TrimSpace(buf.String()); want != have {
121 t.Errorf("\nwant:\n%s\nhave:\n%s", want, have)
122 }
123 })
124 }
125 }
126
127 func TestErrNotAllowed(t *testing.T) {
128 myError := errors.New("squelched!")
129 opts := []level.Option{
130 level.AllowWarn(),
131 level.ErrNotAllowed(myError),
132 }
133 logger := level.NewFilter(log.NewNopLogger(), opts...)
134
135 if want, have := myError, level.Info(logger).Log("foo", "bar"); want != have {
136 t.Errorf("want %#+v, have %#+v", want, have)
137 }
138
139 if want, have := error(nil), level.Warn(logger).Log("foo", "bar"); want != have {
140 t.Errorf("want %#+v, have %#+v", want, have)
141 }
142 }
143
144 func TestErrNoLevel(t *testing.T) {
145 myError := errors.New("no level specified")
146
147 var buf bytes.Buffer
148 opts := []level.Option{
149 level.SquelchNoLevel(true),
150 level.ErrNoLevel(myError),
151 }
152 logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)
153
154 if want, have := myError, logger.Log("foo", "bar"); want != have {
155 t.Errorf("want %v, have %v", want, have)
156 }
157 if want, have := ``, strings.TrimSpace(buf.String()); want != have {
158 t.Errorf("\nwant '%s'\nhave '%s'", want, have)
159 }
160 }
161
162 func TestAllowNoLevel(t *testing.T) {
163 var buf bytes.Buffer
164 opts := []level.Option{
165 level.SquelchNoLevel(false),
166 level.ErrNoLevel(errors.New("I should never be returned!")),
167 }
168 logger := level.NewFilter(log.NewJSONLogger(&buf), opts...)
169
170 if want, have := error(nil), logger.Log("foo", "bar"); want != have {
171 t.Errorf("want %v, have %v", want, have)
172 }
173 if want, have := `{"foo":"bar"}`, strings.TrimSpace(buf.String()); want != have {
174 t.Errorf("\nwant '%s'\nhave '%s'", want, have)
175 }
176 }
177
178 func TestLevelContext(t *testing.T) {
179 var buf bytes.Buffer
180
181
182
183 var logger log.Logger
184 logger = log.NewLogfmtLogger(&buf)
185 logger = level.NewFilter(logger, level.AllowAll())
186 logger = log.With(logger, "caller", log.DefaultCaller)
187
188 level.Info(logger).Log("foo", "bar")
189 if want, have := `level=info caller=level_test.go:188 foo=bar`, strings.TrimSpace(buf.String()); want != have {
190 t.Errorf("\nwant '%s'\nhave '%s'", want, have)
191 }
192 }
193
194 func TestContextLevel(t *testing.T) {
195 var buf bytes.Buffer
196
197
198
199 var logger log.Logger
200 logger = log.NewLogfmtLogger(&buf)
201 logger = log.With(logger, "caller", log.Caller(5))
202 logger = level.NewFilter(logger, level.AllowAll())
203
204 level.Info(logger).Log("foo", "bar")
205 if want, have := `caller=level_test.go:204 level=info foo=bar`, strings.TrimSpace(buf.String()); want != have {
206 t.Errorf("\nwant '%s'\nhave '%s'", want, have)
207 }
208 }
209
210 func TestLevelFormatting(t *testing.T) {
211 testCases := []struct {
212 name string
213 format func(io.Writer) log.Logger
214 output string
215 }{
216 {
217 name: "logfmt",
218 format: log.NewLogfmtLogger,
219 output: `level=info foo=bar`,
220 },
221 {
222 name: "JSON",
223 format: log.NewJSONLogger,
224 output: `{"foo":"bar","level":"info"}`,
225 },
226 }
227
228 for _, tc := range testCases {
229 t.Run(tc.name, func(t *testing.T) {
230 var buf bytes.Buffer
231
232 logger := tc.format(&buf)
233 level.Info(logger).Log("foo", "bar")
234 if want, have := tc.output, strings.TrimSpace(buf.String()); want != have {
235 t.Errorf("\nwant: '%s'\nhave '%s'", want, have)
236 }
237 })
238 }
239 }
240
241 func TestInjector(t *testing.T) {
242 var (
243 output []interface{}
244 logger log.Logger
245 )
246
247 logger = log.LoggerFunc(func(keyvals ...interface{}) error {
248 output = keyvals
249 return nil
250 })
251 logger = level.NewInjector(logger, level.InfoValue())
252
253 logger.Log("foo", "bar")
254 if got, want := len(output), 4; got != want {
255 t.Errorf("missing level not injected: got len==%d, want len==%d", got, want)
256 }
257 if got, want := output[0], level.Key(); got != want {
258 t.Errorf("wrong level key: got %#v, want %#v", got, want)
259 }
260 if got, want := output[1], level.InfoValue(); got != want {
261 t.Errorf("wrong level value: got %#v, want %#v", got, want)
262 }
263
264 level.Error(logger).Log("foo", "bar")
265 if got, want := len(output), 4; got != want {
266 t.Errorf("leveled record modified: got len==%d, want len==%d", got, want)
267 }
268 if got, want := output[0], level.Key(); got != want {
269 t.Errorf("wrong level key: got %#v, want %#v", got, want)
270 }
271 if got, want := output[1], level.ErrorValue(); got != want {
272 t.Errorf("wrong level value: got %#v, want %#v", got, want)
273 }
274 }
275
276 func TestParse(t *testing.T) {
277 testCases := []struct {
278 name string
279 level string
280 want level.Value
281 wantErr error
282 }{
283 {
284 name: "Debug",
285 level: "debug",
286 want: level.DebugValue(),
287 wantErr: nil,
288 },
289 {
290 name: "Info",
291 level: "info",
292 want: level.InfoValue(),
293 wantErr: nil,
294 },
295 {
296 name: "Warn",
297 level: "warn",
298 want: level.WarnValue(),
299 wantErr: nil,
300 },
301 {
302 name: "Error",
303 level: "error",
304 want: level.ErrorValue(),
305 wantErr: nil,
306 },
307 {
308 name: "Case Insensitive",
309 level: "ErRoR",
310 want: level.ErrorValue(),
311 wantErr: nil,
312 },
313 {
314 name: "Trimmed",
315 level: " Error ",
316 want: level.ErrorValue(),
317 wantErr: nil,
318 },
319 {
320 name: "Invalid",
321 level: "invalid",
322 want: nil,
323 wantErr: level.ErrInvalidLevelString,
324 },
325 }
326
327 for _, tc := range testCases {
328 t.Run(tc.name, func(t *testing.T) {
329 got, err := level.Parse(tc.level)
330 if err != tc.wantErr {
331 t.Errorf("got unexpected error %#v", err)
332 }
333
334 if got != tc.want {
335 t.Errorf("wrong value: got=%#v, want=%#v", got, tc.want)
336 }
337 })
338 }
339 }
340
341 func TestParseDefault(t *testing.T) {
342 testCases := []struct {
343 name string
344 level string
345 want level.Value
346 }{
347 {
348 name: "Debug",
349 level: "debug",
350 want: level.DebugValue(),
351 },
352 {
353 name: "Info",
354 level: "info",
355 want: level.InfoValue(),
356 },
357 {
358 name: "Warn",
359 level: "warn",
360 want: level.WarnValue(),
361 },
362 {
363 name: "Error",
364 level: "error",
365 want: level.ErrorValue(),
366 },
367 {
368 name: "Case Insensitive",
369 level: "ErRoR",
370 want: level.ErrorValue(),
371 },
372 {
373 name: "Trimmed",
374 level: " Error ",
375 want: level.ErrorValue(),
376 },
377 {
378 name: "Invalid",
379 level: "invalid",
380 want: level.InfoValue(),
381 },
382 }
383
384 for _, tc := range testCases {
385 t.Run(tc.name, func(t *testing.T) {
386 got := level.ParseDefault(tc.level, level.InfoValue())
387
388 if got != tc.want {
389 t.Errorf("wrong value: got=%#v, want=%#v", got, tc.want)
390 }
391 })
392 }
393 }
394
View as plain text