github.com/Laisky/zap@v1.27.0/sugar_test.go (about) 1 // Copyright (c) 2016 Uber Technologies, Inc. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a copy 4 // of this software and associated documentation files (the "Software"), to deal 5 // in the Software without restriction, including without limitation the rights 6 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 // copies of the Software, and to permit persons to whom the Software is 8 // furnished to do so, subject to the following conditions: 9 // 10 // The above copyright notice and this permission notice shall be included in 11 // all copies or substantial portions of the Software. 12 // 13 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 // THE SOFTWARE. 20 21 package zap 22 23 import ( 24 "errors" 25 "fmt" 26 "strconv" 27 "testing" 28 29 "github.com/Laisky/zap/internal/exit" 30 "github.com/Laisky/zap/internal/ztest" 31 "github.com/Laisky/zap/zapcore" 32 "github.com/Laisky/zap/zaptest/observer" 33 34 "github.com/stretchr/testify/assert" 35 "github.com/stretchr/testify/require" 36 ) 37 38 func TestSugarWith(t *testing.T) { 39 // Convenience functions to create expected error logs. 40 ignored := func(msg interface{}) observer.LoggedEntry { 41 return observer.LoggedEntry{ 42 Entry: zapcore.Entry{Level: ErrorLevel, Message: _oddNumberErrMsg}, 43 Context: []Field{Any("ignored", msg)}, 44 } 45 } 46 nonString := func(pairs ...invalidPair) observer.LoggedEntry { 47 return observer.LoggedEntry{ 48 Entry: zapcore.Entry{Level: ErrorLevel, Message: _nonStringKeyErrMsg}, 49 Context: []Field{Array("invalid", invalidPairs(pairs))}, 50 } 51 } 52 ignoredError := func(err error) observer.LoggedEntry { 53 return observer.LoggedEntry{ 54 Entry: zapcore.Entry{Level: ErrorLevel, Message: _multipleErrMsg}, 55 Context: []Field{Error(err)}, 56 } 57 } 58 59 type withAny func(*SugaredLogger, ...interface{}) *SugaredLogger 60 withMethods := []withAny{(*SugaredLogger).With, (*SugaredLogger).WithLazy} 61 62 tests := []struct { 63 desc string 64 args []interface{} 65 expected []Field 66 errLogs []observer.LoggedEntry 67 }{ 68 { 69 desc: "nil args", 70 args: nil, 71 expected: []Field{}, 72 errLogs: nil, 73 }, 74 { 75 desc: "empty slice of args", 76 args: []interface{}{}, 77 expected: []Field{}, 78 errLogs: nil, 79 }, 80 { 81 desc: "just a dangling key", 82 args: []interface{}{"should ignore"}, 83 expected: []Field{}, 84 errLogs: []observer.LoggedEntry{ignored("should ignore")}, 85 }, 86 { 87 desc: "well-formed key-value pairs", 88 args: []interface{}{"foo", 42, "true", "bar"}, 89 expected: []Field{Int("foo", 42), String("true", "bar")}, 90 errLogs: nil, 91 }, 92 { 93 desc: "just a structured field", 94 args: []interface{}{Int("foo", 42)}, 95 expected: []Field{Int("foo", 42)}, 96 errLogs: nil, 97 }, 98 { 99 desc: "structured field and a dangling key", 100 args: []interface{}{Int("foo", 42), "dangling"}, 101 expected: []Field{Int("foo", 42)}, 102 errLogs: []observer.LoggedEntry{ignored("dangling")}, 103 }, 104 { 105 desc: "structured field and a dangling non-string key", 106 args: []interface{}{Int("foo", 42), 13}, 107 expected: []Field{Int("foo", 42)}, 108 errLogs: []observer.LoggedEntry{ignored(13)}, 109 }, 110 { 111 desc: "key-value pair and a dangling key", 112 args: []interface{}{"foo", 42, "dangling"}, 113 expected: []Field{Int("foo", 42)}, 114 errLogs: []observer.LoggedEntry{ignored("dangling")}, 115 }, 116 { 117 desc: "pairs, a structured field, and a dangling key", 118 args: []interface{}{"first", "field", Int("foo", 42), "baz", "quux", "dangling"}, 119 expected: []Field{String("first", "field"), Int("foo", 42), String("baz", "quux")}, 120 errLogs: []observer.LoggedEntry{ignored("dangling")}, 121 }, 122 { 123 desc: "one non-string key", 124 args: []interface{}{"foo", 42, true, "bar"}, 125 expected: []Field{Int("foo", 42)}, 126 errLogs: []observer.LoggedEntry{nonString(invalidPair{2, true, "bar"})}, 127 }, 128 { 129 desc: "pairs, structured fields, non-string keys, and a dangling key", 130 args: []interface{}{"foo", 42, true, "bar", Int("structure", 11), 42, "reversed", "baz", "quux", "dangling"}, 131 expected: []Field{Int("foo", 42), Int("structure", 11), String("baz", "quux")}, 132 errLogs: []observer.LoggedEntry{ 133 ignored("dangling"), 134 nonString(invalidPair{2, true, "bar"}, invalidPair{5, 42, "reversed"}), 135 }, 136 }, 137 { 138 desc: "multiple errors", 139 args: []interface{}{errors.New("first"), errors.New("second"), errors.New("third")}, 140 expected: []Field{Error(errors.New("first"))}, 141 errLogs: []observer.LoggedEntry{ 142 ignoredError(errors.New("second")), 143 ignoredError(errors.New("third")), 144 }, 145 }, 146 } 147 148 for _, tt := range tests { 149 for _, withMethod := range withMethods { 150 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 151 withMethod(logger, tt.args...).Info("") 152 output := logs.AllUntimed() 153 if len(tt.errLogs) > 0 { 154 for i := range tt.errLogs { 155 assert.Equal(t, tt.errLogs[i], output[i], "Unexpected error log at position %d for scenario %s.", i, tt.desc) 156 } 157 } 158 assert.Equal(t, len(tt.errLogs)+1, len(output), "Expected only one non-error message to be logged in scenario %s.", tt.desc) 159 assert.Equal(t, tt.expected, output[len(tt.errLogs)].Context, "Unexpected message context in scenario %s.", tt.desc) 160 }) 161 } 162 } 163 } 164 165 func TestSugarWithCaptures(t *testing.T) { 166 type withAny func(*SugaredLogger, ...interface{}) *SugaredLogger 167 168 tests := []struct { 169 name string 170 withMethods []withAny 171 wantJSON []string 172 }{ 173 { 174 name: "with captures arguments at time of With", 175 withMethods: []withAny{(*SugaredLogger).With}, 176 wantJSON: []string{ 177 `{ 178 "m": "hello 0", 179 "a0": [0], 180 "b0": [1] 181 }`, 182 `{ 183 "m": "world 0", 184 "a0": [0], 185 "c0": [2] 186 }`, 187 }, 188 }, 189 { 190 name: "lazy with captures arguments at time of Logging", 191 withMethods: []withAny{(*SugaredLogger).WithLazy}, 192 wantJSON: []string{ 193 `{ 194 "m": "hello 0", 195 "a0": [1], 196 "b0": [1] 197 }`, 198 `{ 199 "m": "world 0", 200 "a0": [1], 201 "c0": [2] 202 }`, 203 }, 204 }, 205 } 206 207 for _, tt := range tests { 208 t.Run(tt.name, func(t *testing.T) { 209 enc := zapcore.NewJSONEncoder(zapcore.EncoderConfig{ 210 MessageKey: "m", 211 }) 212 213 var bs ztest.Buffer 214 logger := New(zapcore.NewCore(enc, &bs, DebugLevel)).Sugar() 215 216 for i, withMethod := range tt.withMethods { 217 iStr := strconv.Itoa(i) 218 x := 10 * i 219 arr := zapcore.ArrayMarshalerFunc(func(enc zapcore.ArrayEncoder) error { 220 enc.AppendInt(x) 221 return nil 222 }) 223 224 logger = withMethod(logger, Array("a"+iStr, arr)) 225 x++ 226 logger.Infow(fmt.Sprintf("hello %d", i), Array("b"+iStr, arr)) 227 x++ 228 logger = withMethod(logger, Array("c"+iStr, arr)) 229 logger.Infow(fmt.Sprintf("world %d", i)) 230 } 231 232 if lines := bs.Lines(); assert.Len(t, lines, len(tt.wantJSON)) { 233 for i, want := range tt.wantJSON { 234 assert.JSONEq(t, want, lines[i], "Unexpected output from the %d'th log.", i) 235 } 236 } 237 }) 238 } 239 } 240 241 func TestSugaredLoggerLevel(t *testing.T) { 242 levels := []zapcore.Level{ 243 DebugLevel, 244 InfoLevel, 245 WarnLevel, 246 ErrorLevel, 247 DPanicLevel, 248 PanicLevel, 249 FatalLevel, 250 } 251 252 for _, lvl := range levels { 253 lvl := lvl 254 t.Run(lvl.String(), func(t *testing.T) { 255 t.Parallel() 256 257 core, _ := observer.New(lvl) 258 log := New(core).Sugar() 259 assert.Equal(t, lvl, log.Level()) 260 }) 261 } 262 263 t.Run("Nop", func(t *testing.T) { 264 t.Parallel() 265 266 assert.Equal(t, zapcore.InvalidLevel, NewNop().Sugar().Level()) 267 }) 268 } 269 270 func TestSugarFieldsInvalidPairs(t *testing.T) { 271 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 272 logger.With(42, "foo", []string{"bar"}, "baz").Info("") 273 output := logs.AllUntimed() 274 275 // Double-check that the actual message was logged. 276 require.Equal(t, 2, len(output), "Unexpected number of entries logged.") 277 require.Equal(t, observer.LoggedEntry{Context: []Field{}}, output[1], "Unexpected non-error log entry.") 278 279 // Assert that the error message's structured fields serialize properly. 280 require.Equal(t, 1, len(output[0].Context), "Expected one field in error entry context.") 281 enc := zapcore.NewMapObjectEncoder() 282 output[0].Context[0].AddTo(enc) 283 assert.Equal(t, []interface{}{ 284 map[string]interface{}{"position": int64(0), "key": int64(42), "value": "foo"}, 285 map[string]interface{}{"position": int64(2), "key": []interface{}{"bar"}, "value": "baz"}, 286 }, enc.Fields["invalid"], "Unexpected output when logging invalid key-value pairs.") 287 }) 288 } 289 290 func TestSugarStructuredLogging(t *testing.T) { 291 tests := []struct { 292 msg string 293 expectMsg string 294 }{ 295 {"foo", "foo"}, 296 {"", ""}, 297 } 298 299 // Common to all test cases. 300 var ( 301 err = errors.New("qux") 302 context = []interface{}{"foo", "bar"} 303 extra = []interface{}{err, "baz", false} 304 expectedFields = []Field{String("foo", "bar"), Error(err), Bool("baz", false)} 305 ) 306 307 for _, tt := range tests { 308 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 309 logger.With(context...).Debugw(tt.msg, extra...) 310 logger.With(context...).Infow(tt.msg, extra...) 311 logger.With(context...).Warnw(tt.msg, extra...) 312 logger.With(context...).Errorw(tt.msg, extra...) 313 logger.With(context...).DPanicw(tt.msg, extra...) 314 logger.With(context...).Logw(WarnLevel, tt.msg, extra...) 315 316 expected := make([]observer.LoggedEntry, 6) 317 for i, lvl := range []zapcore.Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, DPanicLevel, WarnLevel} { 318 expected[i] = observer.LoggedEntry{ 319 Entry: zapcore.Entry{Message: tt.expectMsg, Level: lvl}, 320 Context: expectedFields, 321 } 322 } 323 assert.Equal(t, expected, logs.AllUntimed(), "Unexpected log output.") 324 }) 325 } 326 } 327 328 func TestSugarConcatenatingLogging(t *testing.T) { 329 tests := []struct { 330 args []interface{} 331 expect string 332 }{ 333 {[]interface{}{nil}, "<nil>"}, 334 } 335 336 // Common to all test cases. 337 context := []interface{}{"foo", "bar"} 338 expectedFields := []Field{String("foo", "bar")} 339 340 for _, tt := range tests { 341 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 342 logger.With(context...).Debug(tt.args...) 343 logger.With(context...).Info(tt.args...) 344 logger.With(context...).Warn(tt.args...) 345 logger.With(context...).Error(tt.args...) 346 logger.With(context...).DPanic(tt.args...) 347 logger.With(context...).Log(InfoLevel, tt.args...) 348 349 expected := make([]observer.LoggedEntry, 6) 350 for i, lvl := range []zapcore.Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, DPanicLevel, InfoLevel} { 351 expected[i] = observer.LoggedEntry{ 352 Entry: zapcore.Entry{Message: tt.expect, Level: lvl}, 353 Context: expectedFields, 354 } 355 } 356 assert.Equal(t, expected, logs.AllUntimed(), "Unexpected log output.") 357 }) 358 } 359 } 360 361 func TestSugarTemplatedLogging(t *testing.T) { 362 tests := []struct { 363 format string 364 args []interface{} 365 expect string 366 }{ 367 {"", nil, ""}, 368 {"foo", nil, "foo"}, 369 // If the user fails to pass a template, degrade to fmt.Sprint. 370 {"", []interface{}{"foo"}, "foo"}, 371 } 372 373 // Common to all test cases. 374 context := []interface{}{"foo", "bar"} 375 expectedFields := []Field{String("foo", "bar")} 376 377 for _, tt := range tests { 378 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 379 logger.With(context...).Debugf(tt.format, tt.args...) 380 logger.With(context...).Infof(tt.format, tt.args...) 381 logger.With(context...).Warnf(tt.format, tt.args...) 382 logger.With(context...).Errorf(tt.format, tt.args...) 383 logger.With(context...).DPanicf(tt.format, tt.args...) 384 logger.With(context...).Logf(ErrorLevel, tt.format, tt.args...) 385 386 expected := make([]observer.LoggedEntry, 6) 387 for i, lvl := range []zapcore.Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, DPanicLevel, ErrorLevel} { 388 expected[i] = observer.LoggedEntry{ 389 Entry: zapcore.Entry{Message: tt.expect, Level: lvl}, 390 Context: expectedFields, 391 } 392 } 393 assert.Equal(t, expected, logs.AllUntimed(), "Unexpected log output.") 394 }) 395 } 396 } 397 398 func TestSugarLnLogging(t *testing.T) { 399 tests := []struct { 400 args []interface{} 401 expect string 402 }{ 403 {nil, ""}, 404 {[]interface{}{}, ""}, 405 {[]interface{}{""}, ""}, 406 {[]interface{}{"foo"}, "foo"}, 407 {[]interface{}{"foo", "bar"}, "foo bar"}, 408 } 409 410 // Common to all test cases. 411 context := []interface{}{"foo", "bar"} 412 expectedFields := []Field{String("foo", "bar")} 413 414 for _, tt := range tests { 415 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 416 logger.With(context...).Debugln(tt.args...) 417 logger.With(context...).Infoln(tt.args...) 418 logger.With(context...).Warnln(tt.args...) 419 logger.With(context...).Errorln(tt.args...) 420 logger.With(context...).DPanicln(tt.args...) 421 logger.With(context...).Logln(InfoLevel, tt.args...) 422 423 expected := make([]observer.LoggedEntry, 6) 424 for i, lvl := range []zapcore.Level{DebugLevel, InfoLevel, WarnLevel, ErrorLevel, DPanicLevel, InfoLevel} { 425 expected[i] = observer.LoggedEntry{ 426 Entry: zapcore.Entry{Message: tt.expect, Level: lvl}, 427 Context: expectedFields, 428 } 429 } 430 assert.Equal(t, expected, logs.AllUntimed(), "Unexpected log output.") 431 }) 432 } 433 } 434 435 func TestSugarLnLoggingIgnored(t *testing.T) { 436 withSugar(t, WarnLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 437 logger.Infoln("hello") 438 assert.Zero(t, logs.Len(), "Expected zero log statements.") 439 }) 440 } 441 442 func TestSugarPanicLogging(t *testing.T) { 443 tests := []struct { 444 loggerLevel zapcore.Level 445 f func(*SugaredLogger) 446 expectedMsg string 447 }{ 448 {FatalLevel, func(s *SugaredLogger) { s.Panic("foo") }, ""}, 449 {PanicLevel, func(s *SugaredLogger) { s.Panic("foo") }, "foo"}, 450 {DebugLevel, func(s *SugaredLogger) { s.Panic("foo") }, "foo"}, 451 {FatalLevel, func(s *SugaredLogger) { s.Panicf("%s", "foo") }, ""}, 452 {PanicLevel, func(s *SugaredLogger) { s.Panicf("%s", "foo") }, "foo"}, 453 {DebugLevel, func(s *SugaredLogger) { s.Panicf("%s", "foo") }, "foo"}, 454 {FatalLevel, func(s *SugaredLogger) { s.Panicw("foo") }, ""}, 455 {PanicLevel, func(s *SugaredLogger) { s.Panicw("foo") }, "foo"}, 456 {DebugLevel, func(s *SugaredLogger) { s.Panicw("foo") }, "foo"}, 457 {FatalLevel, func(s *SugaredLogger) { s.Panicln("foo") }, ""}, 458 {PanicLevel, func(s *SugaredLogger) { s.Panicln("foo") }, "foo"}, 459 {DebugLevel, func(s *SugaredLogger) { s.Panicln("foo") }, "foo"}, 460 } 461 462 for _, tt := range tests { 463 withSugar(t, tt.loggerLevel, nil, func(sugar *SugaredLogger, logs *observer.ObservedLogs) { 464 assert.Panics(t, func() { tt.f(sugar) }, "Expected panic-level logger calls to panic.") 465 if tt.expectedMsg != "" { 466 assert.Equal(t, []observer.LoggedEntry{{ 467 Context: []Field{}, 468 Entry: zapcore.Entry{Message: tt.expectedMsg, Level: PanicLevel}, 469 }}, logs.AllUntimed(), "Unexpected log output.") 470 } else { 471 assert.Equal(t, 0, logs.Len(), "Didn't expect any log output.") 472 } 473 }) 474 } 475 } 476 477 func TestSugarFatalLogging(t *testing.T) { 478 tests := []struct { 479 loggerLevel zapcore.Level 480 f func(*SugaredLogger) 481 expectedMsg string 482 }{ 483 {FatalLevel + 1, func(s *SugaredLogger) { s.Fatal("foo") }, ""}, 484 {FatalLevel, func(s *SugaredLogger) { s.Fatal("foo") }, "foo"}, 485 {DebugLevel, func(s *SugaredLogger) { s.Fatal("foo") }, "foo"}, 486 {FatalLevel + 1, func(s *SugaredLogger) { s.Fatalf("%s", "foo") }, ""}, 487 {FatalLevel, func(s *SugaredLogger) { s.Fatalf("%s", "foo") }, "foo"}, 488 {DebugLevel, func(s *SugaredLogger) { s.Fatalf("%s", "foo") }, "foo"}, 489 {FatalLevel + 1, func(s *SugaredLogger) { s.Fatalw("foo") }, ""}, 490 {FatalLevel, func(s *SugaredLogger) { s.Fatalw("foo") }, "foo"}, 491 {DebugLevel, func(s *SugaredLogger) { s.Fatalw("foo") }, "foo"}, 492 {FatalLevel + 1, func(s *SugaredLogger) { s.Fatalln("foo") }, ""}, 493 {FatalLevel, func(s *SugaredLogger) { s.Fatalln("foo") }, "foo"}, 494 {DebugLevel, func(s *SugaredLogger) { s.Fatalln("foo") }, "foo"}, 495 } 496 497 for _, tt := range tests { 498 withSugar(t, tt.loggerLevel, nil, func(sugar *SugaredLogger, logs *observer.ObservedLogs) { 499 stub := exit.WithStub(func() { tt.f(sugar) }) 500 assert.True(t, stub.Exited, "Expected all calls to fatal logger methods to exit process.") 501 if tt.expectedMsg != "" { 502 assert.Equal(t, []observer.LoggedEntry{{ 503 Context: []Field{}, 504 Entry: zapcore.Entry{Message: tt.expectedMsg, Level: FatalLevel}, 505 }}, logs.AllUntimed(), "Unexpected log output.") 506 } else { 507 assert.Equal(t, 0, logs.Len(), "Didn't expect any log output.") 508 } 509 }) 510 } 511 } 512 513 func TestSugarAddCaller(t *testing.T) { 514 tests := []struct { 515 options []Option 516 pat string 517 }{ 518 {opts(AddCaller()), `.+/sugar_test.go:[\d]+$`}, 519 {opts(AddCaller(), AddCallerSkip(1), AddCallerSkip(-1)), `.+/sugar_test.go:[\d]+$`}, 520 {opts(AddCaller(), AddCallerSkip(1)), `.+/common_test.go:[\d]+$`}, 521 {opts(AddCaller(), AddCallerSkip(1), AddCallerSkip(5)), `.+/src/runtime/.*:[\d]+$`}, 522 } 523 for _, tt := range tests { 524 withSugar(t, DebugLevel, tt.options, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 525 logger.Info("") 526 output := logs.AllUntimed() 527 assert.Equal(t, 1, len(output), "Unexpected number of logs written out.") 528 assert.Regexp( 529 t, 530 tt.pat, 531 output[0].Caller, 532 "Expected to find package name and file name in output.", 533 ) 534 }) 535 } 536 } 537 538 func TestSugarAddCallerFail(t *testing.T) { 539 errBuf := &ztest.Buffer{} 540 withSugar(t, DebugLevel, opts(AddCaller(), AddCallerSkip(1e3), ErrorOutput(errBuf)), func(log *SugaredLogger, logs *observer.ObservedLogs) { 541 log.Info("Failure.") 542 assert.Regexp( 543 t, 544 `Logger.check error: failed to get caller`, 545 errBuf.String(), 546 "Didn't find expected failure message.", 547 ) 548 assert.Equal( 549 t, 550 logs.AllUntimed()[0].Message, 551 "Failure.", 552 "Expected original message to survive failures in runtime.Caller.") 553 }) 554 } 555 556 func TestSugarWithOptionsIncreaseLevel(t *testing.T) { 557 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 558 logger = logger.WithOptions(IncreaseLevel(WarnLevel)) 559 logger.Info("logger.Info") 560 logger.Warn("logger.Warn") 561 logger.Error("logger.Error") 562 require.Equal(t, 2, logs.Len(), "expected only warn + error logs due to IncreaseLevel.") 563 assert.Equal( 564 t, 565 logs.AllUntimed()[0].Message, 566 "logger.Warn", 567 "Expected first logged message to be warn level message", 568 ) 569 }) 570 } 571 572 func TestSugarLnWithOptionsIncreaseLevel(t *testing.T) { 573 withSugar(t, DebugLevel, nil, func(logger *SugaredLogger, logs *observer.ObservedLogs) { 574 logger = logger.WithOptions(IncreaseLevel(WarnLevel)) 575 logger.Infoln("logger.Infoln") 576 logger.Warnln("logger.Warnln") 577 logger.Errorln("logger.Errorln") 578 require.Equal(t, 2, logs.Len(), "expected only warn + error logs due to IncreaseLevel.") 579 assert.Equal( 580 t, 581 logs.AllUntimed()[0].Message, 582 "logger.Warnln", 583 "Expected first logged message to be warn level message", 584 ) 585 }) 586 } 587 588 func BenchmarkSugarSingleStrArg(b *testing.B) { 589 withSugar(b, InfoLevel, nil /* opts* */, func(log *SugaredLogger, logs *observer.ObservedLogs) { 590 for i := 0; i < b.N; i++ { 591 log.Info("hello world") 592 } 593 }) 594 } 595 596 func BenchmarkLnSugarSingleStrArg(b *testing.B) { 597 withSugar(b, InfoLevel, nil /* opts* */, func(log *SugaredLogger, logs *observer.ObservedLogs) { 598 for i := 0; i < b.N; i++ { 599 log.Infoln("hello world") 600 } 601 }) 602 }