SugaredLogger: Turn error into zap.Error (#1185)
Craig Pastro authored 1 year, 7 months ago
GitHub committed 1 year, 7 months ago
30 | 30 | const ( |
31 | 31 | _oddNumberErrMsg = "Ignored key without a value." |
32 | 32 | _nonStringKeyErrMsg = "Ignored key-value pairs with non-string keys." |
33 | _multipleErrMsg = "Multiple errors without a key." | |
33 | 34 | ) |
34 | 35 | |
35 | 36 | // A SugaredLogger wraps the base Logger functionality in a slower, but less |
335 | 336 | return nil |
336 | 337 | } |
337 | 338 | |
338 | // Allocate enough space for the worst case; if users pass only structured | |
339 | // fields, we shouldn't penalize them with extra allocations. | |
340 | fields := make([]Field, 0, len(args)) | |
341 | var invalid invalidPairs | |
339 | var ( | |
340 | // Allocate enough space for the worst case; if users pass only structured | |
341 | // fields, we shouldn't penalize them with extra allocations. | |
342 | fields = make([]Field, 0, len(args)) | |
343 | invalid invalidPairs | |
344 | seenError bool | |
345 | ) | |
342 | 346 | |
343 | 347 | for i := 0; i < len(args); { |
344 | 348 | // This is a strongly-typed field. Consume it and move on. |
345 | 349 | if f, ok := args[i].(Field); ok { |
346 | 350 | fields = append(fields, f) |
351 | i++ | |
352 | continue | |
353 | } | |
354 | ||
355 | // If it is an error, consume it and move on. | |
356 | if err, ok := args[i].(error); ok { | |
357 | if !seenError { | |
358 | seenError = true | |
359 | fields = append(fields, Error(err)) | |
360 | } else { | |
361 | s.base.Error(_multipleErrMsg, Error(err)) | |
362 | } | |
347 | 363 | i++ |
348 | 364 | continue |
349 | 365 | } |
20 | 20 | package zap |
21 | 21 | |
22 | 22 | import ( |
23 | "errors" | |
23 | 24 | "testing" |
24 | 25 | |
25 | 26 | "go.uber.org/zap/internal/exit" |
45 | 46 | Context: []Field{Array("invalid", invalidPairs(pairs))}, |
46 | 47 | } |
47 | 48 | } |
49 | ignoredError := func(err error) observer.LoggedEntry { | |
50 | return observer.LoggedEntry{ | |
51 | Entry: zapcore.Entry{Level: ErrorLevel, Message: _multipleErrMsg}, | |
52 | Context: []Field{Error(err)}, | |
53 | } | |
54 | } | |
48 | 55 | |
49 | 56 | tests := []struct { |
50 | 57 | desc string |
119 | 126 | errLogs: []observer.LoggedEntry{ |
120 | 127 | ignored("dangling"), |
121 | 128 | nonString(invalidPair{2, true, "bar"}, invalidPair{5, 42, "reversed"}), |
129 | }, | |
130 | }, | |
131 | { | |
132 | desc: "multiple errors", | |
133 | args: []interface{}{errors.New("first"), errors.New("second"), errors.New("third")}, | |
134 | expected: []Field{Error(errors.New("first"))}, | |
135 | errLogs: []observer.LoggedEntry{ | |
136 | ignoredError(errors.New("second")), | |
137 | ignoredError(errors.New("third")), | |
122 | 138 | }, |
123 | 139 | }, |
124 | 140 | } |
197 | 213 | } |
198 | 214 | |
199 | 215 | // Common to all test cases. |
200 | context := []interface{}{"foo", "bar"} | |
201 | extra := []interface{}{"baz", false} | |
202 | expectedFields := []Field{String("foo", "bar"), Bool("baz", false)} | |
203 | ||
216 | var ( | |
217 | err = errors.New("qux") | |
218 | context = []interface{}{"foo", "bar"} | |
219 | extra = []interface{}{err, "baz", false} | |
220 | expectedFields = []Field{String("foo", "bar"), Error(err), Bool("baz", false)} | |
221 | ) | |
222 | ||
204 | 223 | for _, tt := range tests { |
205 | 224 | withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { |
206 | 225 | logger.With(context...).Debugw(tt.msg, extra...) |