github.com/oarkflow/log@v1.0.78/logger.go (about) 1 package log 2 3 import ( 4 "context" 5 "encoding/json" 6 "fmt" 7 "io" 8 "math" 9 "net" 10 "net/netip" 11 "os" 12 "reflect" 13 "runtime" 14 "strconv" 15 "sync" 16 "sync/atomic" 17 "time" 18 "unsafe" 19 20 "github.com/oarkflow/log/fqdn" 21 ) 22 23 // DefaultLogger is the global logger. 24 var DefaultLogger = Logger{ 25 Level: DebugLevel, 26 LogNode: false, 27 EnableTracing: true, 28 TraceIDField: "trace_id", 29 Caller: 0, 30 TimeField: "", 31 TimeFormat: "", 32 Writer: IOWriter{os.Stderr}, 33 } 34 35 // Entry represents a log entry. It is instanced by one of the level method of Logger and finalized by the Msg or Msgf method. 36 type Entry struct { 37 buf []byte 38 Level Level 39 logger *Logger 40 context context.Context 41 w Writer 42 } 43 44 // Writer defines an entry writer interface. 45 type Writer interface { 46 WriteEntry(*Entry) (int, error) 47 } 48 49 // The WriterFunc type is an adapter to allow the use of 50 // ordinary functions as log writers. If f is a function 51 // with the appropriate signature, WriterFunc(f) is a 52 // [Writer] that calls f. 53 type WriterFunc func(*Entry) (int, error) 54 55 // WriteEntry calls f(e). 56 func (f WriterFunc) WriteEntry(e *Entry) (int, error) { 57 return f(e) 58 } 59 60 // IOWriter wraps an io.Writer to Writer. 61 type IOWriter struct { 62 io.Writer 63 } 64 65 // WriteEntry implements Writer. 66 func (w IOWriter) WriteEntry(e *Entry) (n int, err error) { 67 return w.Writer.Write(e.buf) 68 } 69 70 // IOWriteCloser wraps an io.IOWriteCloser to Writer. 71 type IOWriteCloser struct { 72 io.WriteCloser 73 } 74 75 // WriteEntry implements Writer. 76 func (w IOWriteCloser) WriteEntry(e *Entry) (n int, err error) { 77 return w.WriteCloser.Write(e.buf) 78 } 79 80 // Close implements Writer. 81 func (w IOWriteCloser) Close() (err error) { 82 return w.WriteCloser.Close() 83 } 84 85 // ObjectMarshaler provides a strongly-typed and encoding-agnostic interface 86 // to be implemented by types used with Entry's Object methods. 87 type ObjectMarshaler interface { 88 MarshalObject(e *Entry) 89 } 90 91 // A Logger represents an active logging object that generates lines of JSON output to an io.Writer. 92 type Logger struct { 93 // Level defines log levels. 94 Level Level 95 96 LogNode bool 97 98 EnableTracing bool 99 100 TraceIDField string 101 102 // Caller determines if adds the file:line of the "caller" key. 103 // If Caller is negative, adds the full /path/to/file:line of the "caller" key. 104 Caller int 105 106 // TimeField defines the time field name in output. It uses "time" in if empty. 107 TimeField string 108 109 // TimeFormat specifies the time format in output. It uses time.RFC3339 with milliseconds if empty. 110 // If set with `TimeFormatUnix`, `TimeFormatUnixMs`, times are formated as UNIX timestamp. 111 TimeFormat string 112 113 // TimeLocation specifices that the location which TimeFormat used. It uses time.Local if empty. 114 TimeLocation *time.Location 115 116 // Context specifies an optional context of logger. 117 Context Context 118 119 // Writer specifies the writer of output. It uses a wrapped os.Stderr Writer in if empty. 120 Writer Writer 121 } 122 123 // TimeFormatUnix defines a time format that makes time fields to be 124 // serialized as Unix timestamp integers. 125 const TimeFormatUnix = "\x01" 126 127 // TimeFormatUnixMs defines a time format that makes time fields to be 128 // serialized as Unix timestamp integers in milliseconds. 129 const TimeFormatUnixMs = "\x02" 130 131 // TimeFormatUnixWithMs defines a time format that makes time fields to be 132 // serialized as Unix timestamp timestamp floats. 133 const TimeFormatUnixWithMs = "\x03" 134 135 // Trace starts a new message with trace level. 136 func Trace() (e *Entry) { 137 if DefaultLogger.silent(TraceLevel) { 138 return nil 139 } 140 e = DefaultLogger.header(TraceLevel) 141 if caller, full := DefaultLogger.Caller, false; caller != 0 { 142 if caller < 0 { 143 caller, full = -caller, true 144 } 145 var pc uintptr 146 e.caller(caller1(caller, &pc, 1, 1), pc, full) 147 } 148 return 149 } 150 151 // Debug starts a new message with debug level. 152 func Debug() (e *Entry) { 153 if DefaultLogger.silent(DebugLevel) { 154 return nil 155 } 156 e = DefaultLogger.header(DebugLevel) 157 if caller, full := DefaultLogger.Caller, false; caller != 0 { 158 if caller < 0 { 159 caller, full = -caller, true 160 } 161 var pc uintptr 162 e.caller(caller1(caller, &pc, 1, 1), pc, full) 163 } 164 return 165 } 166 167 // Info starts a new message with info level. 168 func Info() (e *Entry) { 169 if DefaultLogger.silent(InfoLevel) { 170 return nil 171 } 172 e = DefaultLogger.header(InfoLevel) 173 if caller, full := DefaultLogger.Caller, false; caller != 0 { 174 if caller < 0 { 175 caller, full = -caller, true 176 } 177 var pc uintptr 178 e.caller(caller1(caller, &pc, 1, 1), pc, full) 179 } 180 return 181 } 182 183 // Warn starts a new message with warning level. 184 func Warn() (e *Entry) { 185 if DefaultLogger.silent(WarnLevel) { 186 return nil 187 } 188 e = DefaultLogger.header(WarnLevel) 189 if caller, full := DefaultLogger.Caller, false; caller != 0 { 190 if caller < 0 { 191 caller, full = -caller, true 192 } 193 var pc uintptr 194 e.caller(caller1(caller, &pc, 1, 1), pc, full) 195 } 196 return 197 } 198 199 // Error starts a new message with error level. 200 func Error() (e *Entry) { 201 if DefaultLogger.silent(ErrorLevel) { 202 return nil 203 } 204 e = DefaultLogger.header(ErrorLevel) 205 if caller, full := DefaultLogger.Caller, false; caller != 0 { 206 if caller < 0 { 207 caller, full = -caller, true 208 } 209 var pc uintptr 210 e.caller(caller1(caller, &pc, 1, 1), pc, full) 211 } 212 return 213 } 214 215 // Fatal starts a new message with fatal level. 216 func Fatal() (e *Entry) { 217 if DefaultLogger.silent(FatalLevel) { 218 return nil 219 } 220 e = DefaultLogger.header(FatalLevel) 221 if caller, full := DefaultLogger.Caller, false; caller != 0 { 222 if caller < 0 { 223 caller, full = -caller, true 224 } 225 var pc uintptr 226 e.caller(caller1(caller, &pc, 1, 1), pc, full) 227 } 228 return 229 } 230 231 // Panic starts a new message with panic level. 232 func Panic() (e *Entry) { 233 if DefaultLogger.silent(PanicLevel) { 234 return nil 235 } 236 e = DefaultLogger.header(PanicLevel) 237 if caller, full := DefaultLogger.Caller, false; caller != 0 { 238 if caller < 0 { 239 caller, full = -caller, true 240 } 241 var pc uintptr 242 e.caller(caller1(caller, &pc, 1, 1), pc, full) 243 } 244 return 245 } 246 247 // Printf sends a log entry without extra field. Arguments are handled in the manner of fmt.Printf. 248 func Printf(format string, v ...interface{}) { 249 e := DefaultLogger.header(noLevel) 250 if caller, full := DefaultLogger.Caller, false; caller != 0 { 251 if caller < 0 { 252 caller, full = -caller, true 253 } 254 var pc uintptr 255 e.caller(caller1(caller, &pc, 1, 1), pc, full) 256 } 257 e.Msgf(format, v...) 258 } 259 260 // Trace starts a new message with trace level. 261 func (l *Logger) Trace() (e *Entry) { 262 if l.silent(TraceLevel) { 263 return nil 264 } 265 e = l.header(TraceLevel) 266 if caller, full := l.Caller, false; caller != 0 { 267 if caller < 0 { 268 caller, full = -caller, true 269 } 270 var pc uintptr 271 e.caller(caller1(caller, &pc, 1, 1), pc, full) 272 } 273 return 274 } 275 276 // Debug starts a new message with debug level. 277 func (l *Logger) Debug() (e *Entry) { 278 if l.silent(DebugLevel) { 279 return nil 280 } 281 e = l.header(DebugLevel) 282 if caller, full := l.Caller, false; caller != 0 { 283 if caller < 0 { 284 caller, full = -caller, true 285 } 286 var pc uintptr 287 e.caller(caller1(caller, &pc, 1, 1), pc, full) 288 } 289 return 290 } 291 292 // Info starts a new message with info level. 293 func (l *Logger) Info() (e *Entry) { 294 if l.silent(InfoLevel) { 295 return nil 296 } 297 e = l.header(InfoLevel) 298 if caller, full := l.Caller, false; caller != 0 { 299 if caller < 0 { 300 caller, full = -caller, true 301 } 302 var pc uintptr 303 e.caller(caller1(caller, &pc, 1, 1), pc, full) 304 } 305 return 306 } 307 308 // Warn starts a new message with warning level. 309 func (l *Logger) Warn() (e *Entry) { 310 if l.silent(WarnLevel) { 311 return nil 312 } 313 e = l.header(WarnLevel) 314 if caller, full := l.Caller, false; caller != 0 { 315 if caller < 0 { 316 caller, full = -caller, true 317 } 318 var pc uintptr 319 e.caller(caller1(caller, &pc, 1, 1), pc, full) 320 } 321 return 322 } 323 324 // Error starts a new message with error level. 325 func (l *Logger) Error() (e *Entry) { 326 if l.silent(ErrorLevel) { 327 return nil 328 } 329 e = l.header(ErrorLevel) 330 if caller, full := l.Caller, false; caller != 0 { 331 if caller < 0 { 332 caller, full = -caller, true 333 } 334 var pc uintptr 335 e.caller(caller1(caller, &pc, 1, 1), pc, full) 336 } 337 return 338 } 339 340 // Fatal starts a new message with fatal level. 341 func (l *Logger) Fatal() (e *Entry) { 342 if l.silent(FatalLevel) { 343 return nil 344 } 345 e = l.header(FatalLevel) 346 if caller, full := l.Caller, false; caller != 0 { 347 if caller < 0 { 348 caller, full = -caller, true 349 } 350 var pc uintptr 351 e.caller(caller1(caller, &pc, 1, 1), pc, full) 352 } 353 return 354 } 355 356 // Panic starts a new message with panic level. 357 func (l *Logger) Panic() (e *Entry) { 358 if l.silent(PanicLevel) { 359 return nil 360 } 361 e = l.header(PanicLevel) 362 if caller, full := l.Caller, false; caller != 0 { 363 if caller < 0 { 364 caller, full = -caller, true 365 } 366 var pc uintptr 367 e.caller(caller1(caller, &pc, 1, 1), pc, full) 368 } 369 return 370 } 371 372 // Log starts a new message with no level. 373 func (l *Logger) Log() (e *Entry) { 374 e = l.header(noLevel) 375 if caller, full := l.Caller, false; caller != 0 { 376 if caller < 0 { 377 caller, full = -caller, true 378 } 379 var pc uintptr 380 e.caller(caller1(caller, &pc, 1, 1), pc, full) 381 } 382 return 383 } 384 385 // WithLevel starts a new message with level. 386 func (l *Logger) WithLevel(level Level) (e *Entry) { 387 if l.silent(level) { 388 return nil 389 } 390 e = l.header(level) 391 if caller, full := l.Caller, false; caller != 0 { 392 if caller < 0 { 393 caller, full = -caller, true 394 } 395 var pc uintptr 396 e.caller(caller1(caller, &pc, 1, 1), pc, full) 397 } 398 return 399 } 400 401 // Err starts a new message with error level with err as a field if not nil or with info level if err is nil. 402 func (l *Logger) Err(err error) (e *Entry) { 403 var level = InfoLevel 404 if err != nil { 405 level = ErrorLevel 406 } 407 if l.silent(level) { 408 return nil 409 } 410 e = l.header(level) 411 if e == nil { 412 return nil 413 } 414 if level == ErrorLevel { 415 e = e.Err(err) 416 } 417 if caller, full := l.Caller, false; caller != 0 { 418 if caller < 0 { 419 caller, full = -caller, true 420 } 421 var pc uintptr 422 e.caller(caller1(caller, &pc, 1, 1), pc, full) 423 } 424 return 425 } 426 427 // SetLevel changes logger default level. 428 func (l *Logger) SetLevel(level Level) { 429 atomic.StoreUint32((*uint32)(&l.Level), uint32(level)) 430 } 431 432 // Printf sends a log entry without extra field. Arguments are handled in the manner of fmt.Printf. 433 func (l *Logger) Printf(format string, v ...interface{}) { 434 e := l.header(noLevel) 435 if e != nil { 436 if caller, full := l.Caller, false; caller != 0 { 437 if caller < 0 { 438 caller, full = -caller, true 439 } 440 var pc uintptr 441 e.caller(caller1(caller, &pc, 1, 1), pc, full) 442 } 443 } 444 e.Msgf(format, v...) 445 } 446 447 var epool = sync.Pool{ 448 New: func() interface{} { 449 return &Entry{ 450 buf: make([]byte, 0, 1024), 451 } 452 }, 453 } 454 455 const bbcap = 1 << 16 456 457 const smallsString = "00010203040506070809" + 458 "10111213141516171819" + 459 "20212223242526272829" + 460 "30313233343536373839" + 461 "40414243444546474849" + 462 "50515253545556575859" + 463 "60616263646566676869" + 464 "70717273747576777879" + 465 "80818283848586878889" + 466 "90919293949596979899" 467 468 var timeNow = time.Now 469 var timeOffset, timeZone = func() (int64, string) { 470 now := timeNow() 471 _, n := now.Zone() 472 s := now.Format("Z07:00") 473 return int64(n), s 474 }() 475 476 func (l *Logger) header(level Level) *Entry { 477 e := epool.Get().(*Entry) 478 e.buf = e.buf[:0] 479 e.Level = level 480 if l.Writer != nil { 481 e.w = l.Writer 482 } else { 483 e.w = IOWriter{os.Stderr} 484 } 485 // time 486 if l.TimeField == "" { 487 e.buf = append(e.buf, "{\"time\":"...) 488 } else { 489 e.buf = append(e.buf, '{', '"') 490 e.buf = append(e.buf, l.TimeField...) 491 e.buf = append(e.buf, '"', ':') 492 } 493 offset := timeOffset 494 if l.TimeLocation != nil { 495 if l.TimeLocation == time.UTC { 496 offset = 0 497 } else if l.TimeLocation == time.Local { 498 offset = timeOffset 499 } else { 500 format := l.TimeFormat 501 if format == "" { 502 format = "2006-01-02T15:04:05.999Z07:00" 503 } 504 e.buf = append(e.buf, '"') 505 e.buf = timeNow().In(l.TimeLocation).AppendFormat(e.buf, format) 506 e.buf = append(e.buf, '"') 507 goto headerlevel 508 } 509 } 510 switch l.TimeFormat { 511 case "": 512 sec, nsec, _ := now() 513 var tmp [32]byte 514 var buf []byte 515 if offset == 0 { 516 // "2006-01-02T15:04:05.999Z" 517 tmp[25] = '"' 518 tmp[24] = 'Z' 519 buf = tmp[:26] 520 } else { 521 // "2006-01-02T15:04:05.999Z07:00" 522 tmp[30] = '"' 523 tmp[29] = timeZone[5] 524 tmp[28] = timeZone[4] 525 tmp[27] = timeZone[3] 526 tmp[26] = timeZone[2] 527 tmp[25] = timeZone[1] 528 tmp[24] = timeZone[0] 529 buf = tmp[:31] 530 } 531 // date time 532 sec += 9223372028715321600 + offset // unixToInternal + internalToAbsolute + timeOffset 533 year, month, day, _ := absDate(uint64(sec), true) 534 hour, minute, second := absClock(uint64(sec)) 535 // year 536 a := year / 100 * 2 537 b := year % 100 * 2 538 tmp[0] = '"' 539 tmp[1] = smallsString[a] 540 tmp[2] = smallsString[a+1] 541 tmp[3] = smallsString[b] 542 tmp[4] = smallsString[b+1] 543 // month 544 month *= 2 545 tmp[5] = '-' 546 tmp[6] = smallsString[month] 547 tmp[7] = smallsString[month+1] 548 // day 549 day *= 2 550 tmp[8] = '-' 551 tmp[9] = smallsString[day] 552 tmp[10] = smallsString[day+1] 553 // hour 554 hour *= 2 555 tmp[11] = 'T' 556 tmp[12] = smallsString[hour] 557 tmp[13] = smallsString[hour+1] 558 // minute 559 minute *= 2 560 tmp[14] = ':' 561 tmp[15] = smallsString[minute] 562 tmp[16] = smallsString[minute+1] 563 // second 564 second *= 2 565 tmp[17] = ':' 566 tmp[18] = smallsString[second] 567 tmp[19] = smallsString[second+1] 568 // milli seconds 569 a = int(nsec) / 1000000 570 b = a % 100 * 2 571 tmp[20] = '.' 572 tmp[21] = byte('0' + a/100) 573 tmp[22] = smallsString[b] 574 tmp[23] = smallsString[b+1] 575 // append to e.buf 576 e.buf = append(e.buf, buf...) 577 case TimeFormatUnix: 578 sec, _, _ := now() 579 // 1595759807 580 var tmp [10]byte 581 // seconds 582 b := sec % 100 * 2 583 sec /= 100 584 tmp[9] = smallsString[b+1] 585 tmp[8] = smallsString[b] 586 b = sec % 100 * 2 587 sec /= 100 588 tmp[7] = smallsString[b+1] 589 tmp[6] = smallsString[b] 590 b = sec % 100 * 2 591 sec /= 100 592 tmp[5] = smallsString[b+1] 593 tmp[4] = smallsString[b] 594 b = sec % 100 * 2 595 sec /= 100 596 tmp[3] = smallsString[b+1] 597 tmp[2] = smallsString[b] 598 b = sec % 100 * 2 599 tmp[1] = smallsString[b+1] 600 tmp[0] = smallsString[b] 601 // append to e.buf 602 e.buf = append(e.buf, tmp[:]...) 603 case TimeFormatUnixMs: 604 sec, nsec, _ := now() 605 // 1595759807105 606 var tmp [13]byte 607 // milli seconds 608 a := int64(nsec) / 1000000 609 b := a % 100 * 2 610 tmp[12] = smallsString[b+1] 611 tmp[11] = smallsString[b] 612 tmp[10] = byte('0' + a/100) 613 // seconds 614 b = sec % 100 * 2 615 sec /= 100 616 tmp[9] = smallsString[b+1] 617 tmp[8] = smallsString[b] 618 b = sec % 100 * 2 619 sec /= 100 620 tmp[7] = smallsString[b+1] 621 tmp[6] = smallsString[b] 622 b = sec % 100 * 2 623 sec /= 100 624 tmp[5] = smallsString[b+1] 625 tmp[4] = smallsString[b] 626 b = sec % 100 * 2 627 sec /= 100 628 tmp[3] = smallsString[b+1] 629 tmp[2] = smallsString[b] 630 b = sec % 100 * 2 631 tmp[1] = smallsString[b+1] 632 tmp[0] = smallsString[b] 633 // append to e.buf 634 e.buf = append(e.buf, tmp[:]...) 635 case TimeFormatUnixWithMs: 636 sec, nsec, _ := now() 637 // 1595759807.105 638 var tmp [14]byte 639 // milli seconds 640 a := int64(nsec) / 1000000 641 b := a % 100 * 2 642 tmp[13] = smallsString[b+1] 643 tmp[12] = smallsString[b] 644 tmp[11] = byte('0' + a/100) 645 tmp[10] = '.' 646 // seconds 647 b = sec % 100 * 2 648 sec /= 100 649 tmp[9] = smallsString[b+1] 650 tmp[8] = smallsString[b] 651 b = sec % 100 * 2 652 sec /= 100 653 tmp[7] = smallsString[b+1] 654 tmp[6] = smallsString[b] 655 b = sec % 100 * 2 656 sec /= 100 657 tmp[5] = smallsString[b+1] 658 tmp[4] = smallsString[b] 659 b = sec % 100 * 2 660 sec /= 100 661 tmp[3] = smallsString[b+1] 662 tmp[2] = smallsString[b] 663 b = sec % 100 * 2 664 tmp[1] = smallsString[b+1] 665 tmp[0] = smallsString[b] 666 // append to e.buf 667 e.buf = append(e.buf, tmp[:]...) 668 default: 669 e.buf = append(e.buf, '"') 670 if l.TimeLocation == time.UTC { 671 e.buf = timeNow().UTC().AppendFormat(e.buf, l.TimeFormat) 672 } else { 673 e.buf = timeNow().AppendFormat(e.buf, l.TimeFormat) 674 } 675 e.buf = append(e.buf, '"') 676 } 677 headerlevel: 678 // level 679 switch level { 680 case DebugLevel: 681 e.buf = append(e.buf, ",\"level\":\"debug\""...) 682 case InfoLevel: 683 e.buf = append(e.buf, ",\"level\":\"info\""...) 684 case WarnLevel: 685 e.buf = append(e.buf, ",\"level\":\"warn\""...) 686 case ErrorLevel: 687 e.buf = append(e.buf, ",\"level\":\"error\""...) 688 case TraceLevel: 689 e.buf = append(e.buf, ",\"level\":\"trace\""...) 690 case FatalLevel: 691 e.buf = append(e.buf, ",\"level\":\"fatal\""...) 692 case PanicLevel: 693 e.buf = append(e.buf, ",\"level\":\"panic\""...) 694 } 695 // context 696 if l.Context != nil { 697 e.buf = append(e.buf, l.Context...) 698 } 699 return e 700 } 701 702 // WithContext use context 703 func (e *Entry) WithContext(ctx context.Context) *Entry { 704 e.context = ctx 705 return e 706 } 707 708 // Time append t formatted as string using time.RFC3339Nano. 709 func (e *Entry) Time(key string, t time.Time) *Entry { 710 if e == nil { 711 return nil 712 } 713 e.buf = append(e.buf, ',', '"') 714 e.buf = append(e.buf, key...) 715 e.buf = append(e.buf, '"', ':', '"') 716 e.buf = t.AppendFormat(e.buf, "2006-01-02T15:04:05.999Z07:00") 717 e.buf = append(e.buf, '"') 718 return e 719 } 720 721 // TimeFormat append t formatted as string using timefmt. 722 func (e *Entry) TimeFormat(key string, timefmt string, t time.Time) *Entry { 723 if e == nil { 724 return nil 725 } 726 e.buf = append(e.buf, ',', '"') 727 e.buf = append(e.buf, key...) 728 e.buf = append(e.buf, '"', ':') 729 switch timefmt { 730 case TimeFormatUnix: 731 e.buf = strconv.AppendInt(e.buf, t.Unix(), 10) 732 case TimeFormatUnixMs: 733 e.buf = strconv.AppendInt(e.buf, t.UnixNano()/1000000, 10) 734 case TimeFormatUnixWithMs: 735 e.buf = strconv.AppendInt(e.buf, t.Unix(), 10) 736 e.buf = append(e.buf, '.') 737 e.buf = strconv.AppendInt(e.buf, t.UnixNano()/1000000%1000, 10) 738 default: 739 e.buf = append(e.buf, '"') 740 e.buf = t.AppendFormat(e.buf, timefmt) 741 e.buf = append(e.buf, '"') 742 } 743 return e 744 } 745 746 // Times append a formatted as string array using time.RFC3339Nano. 747 func (e *Entry) Times(key string, a []time.Time) *Entry { 748 if e == nil { 749 return nil 750 } 751 e.buf = append(e.buf, ',', '"') 752 e.buf = append(e.buf, key...) 753 e.buf = append(e.buf, '"', ':', '[') 754 for i, t := range a { 755 if i != 0 { 756 e.buf = append(e.buf, ',') 757 } 758 e.buf = append(e.buf, '"') 759 e.buf = t.AppendFormat(e.buf, time.RFC3339Nano) 760 e.buf = append(e.buf, '"') 761 } 762 e.buf = append(e.buf, ']') 763 764 return e 765 } 766 767 // TimesFormat append a formatted as string array using timefmt. 768 func (e *Entry) TimesFormat(key string, timefmt string, a []time.Time) *Entry { 769 if e == nil { 770 return nil 771 } 772 e.buf = append(e.buf, ',', '"') 773 e.buf = append(e.buf, key...) 774 e.buf = append(e.buf, '"', ':', '[') 775 for i, t := range a { 776 if i != 0 { 777 e.buf = append(e.buf, ',') 778 } 779 switch timefmt { 780 case TimeFormatUnix: 781 e.buf = strconv.AppendInt(e.buf, t.Unix(), 10) 782 case TimeFormatUnixMs: 783 e.buf = strconv.AppendInt(e.buf, t.UnixNano()/1000000, 10) 784 case TimeFormatUnixWithMs: 785 e.buf = strconv.AppendInt(e.buf, t.Unix(), 10) 786 e.buf = append(e.buf, '.') 787 e.buf = strconv.AppendInt(e.buf, t.UnixNano()/1000000%1000, 10) 788 default: 789 e.buf = append(e.buf, '"') 790 e.buf = t.AppendFormat(e.buf, timefmt) 791 e.buf = append(e.buf, '"') 792 } 793 } 794 e.buf = append(e.buf, ']') 795 796 return e 797 } 798 799 // Bool append the val as a bool to the entry. 800 func (e *Entry) Bool(key string, b bool) *Entry { 801 if e == nil { 802 return nil 803 } 804 e.buf = append(e.buf, ',', '"') 805 e.buf = append(e.buf, key...) 806 e.buf = append(e.buf, '"', ':') 807 e.buf = strconv.AppendBool(e.buf, b) 808 return e 809 } 810 811 // Bools adds the field key with val as a []bool to the entry. 812 func (e *Entry) Bools(key string, b []bool) *Entry { 813 if e == nil { 814 return nil 815 } 816 e.buf = append(e.buf, ',', '"') 817 e.buf = append(e.buf, key...) 818 e.buf = append(e.buf, '"', ':', '[') 819 for i, a := range b { 820 if i != 0 { 821 e.buf = append(e.buf, ',') 822 } 823 e.buf = strconv.AppendBool(e.buf, a) 824 } 825 e.buf = append(e.buf, ']') 826 return e 827 } 828 829 // Dur adds the field key with duration d to the entry. 830 func (e *Entry) Dur(key string, d time.Duration) *Entry { 831 if e == nil { 832 return nil 833 } 834 e.buf = append(e.buf, ',', '"') 835 e.buf = append(e.buf, key...) 836 e.buf = append(e.buf, '"', ':') 837 if d < 0 { 838 d = -d 839 e.buf = append(e.buf, '-') 840 } 841 e.buf = strconv.AppendInt(e.buf, int64(d/time.Millisecond), 10) 842 if n := (d % time.Millisecond); n != 0 { 843 var tmp [7]byte 844 b := n % 100 * 2 845 n /= 100 846 tmp[6] = smallsString[b+1] 847 tmp[5] = smallsString[b] 848 b = n % 100 * 2 849 n /= 100 850 tmp[4] = smallsString[b+1] 851 tmp[3] = smallsString[b] 852 b = n % 100 * 2 853 tmp[2] = smallsString[b+1] 854 tmp[1] = smallsString[b] 855 tmp[0] = '.' 856 e.buf = append(e.buf, tmp[:]...) 857 } 858 return e 859 } 860 861 // TimeDiff adds the field key with positive duration between time t and start. 862 // If time t is not greater than start, duration will be 0. 863 // Duration format follows the same principle as Dur(). 864 func (e *Entry) TimeDiff(key string, t time.Time, start time.Time) *Entry { 865 if e == nil { 866 return e 867 } 868 var d time.Duration 869 if t.After(start) { 870 d = t.Sub(start) 871 } 872 e.buf = append(e.buf, ',', '"') 873 e.buf = append(e.buf, key...) 874 e.buf = append(e.buf, '"', ':') 875 e.buf = strconv.AppendInt(e.buf, int64(d/time.Millisecond), 10) 876 if n := (d % time.Millisecond); n != 0 { 877 var tmp [7]byte 878 b := n % 100 * 2 879 n /= 100 880 tmp[6] = smallsString[b+1] 881 tmp[5] = smallsString[b] 882 b = n % 100 * 2 883 n /= 100 884 tmp[4] = smallsString[b+1] 885 tmp[3] = smallsString[b] 886 b = n % 100 * 2 887 tmp[2] = smallsString[b+1] 888 tmp[1] = smallsString[b] 889 tmp[0] = '.' 890 e.buf = append(e.buf, tmp[:]...) 891 } 892 return e 893 } 894 895 // Durs adds the field key with val as a []time.Duration to the entry. 896 func (e *Entry) Durs(key string, d []time.Duration) *Entry { 897 if e == nil { 898 return nil 899 } 900 e.buf = append(e.buf, ',', '"') 901 e.buf = append(e.buf, key...) 902 e.buf = append(e.buf, '"', ':', '[') 903 for i, a := range d { 904 if i != 0 { 905 e.buf = append(e.buf, ',') 906 } 907 if a < 0 { 908 a = -a 909 e.buf = append(e.buf, '-') 910 } 911 e.buf = strconv.AppendInt(e.buf, int64(a/time.Millisecond), 10) 912 if n := (a % time.Millisecond); n != 0 { 913 var tmp [7]byte 914 b := n % 100 * 2 915 n /= 100 916 tmp[6] = smallsString[b+1] 917 tmp[5] = smallsString[b] 918 b = n % 100 * 2 919 n /= 100 920 tmp[4] = smallsString[b+1] 921 tmp[3] = smallsString[b] 922 b = n % 100 * 2 923 tmp[2] = smallsString[b+1] 924 tmp[1] = smallsString[b] 925 tmp[0] = '.' 926 e.buf = append(e.buf, tmp[:]...) 927 } 928 } 929 e.buf = append(e.buf, ']') 930 return e 931 } 932 933 // Err adds the field "error" with serialized err to the entry. 934 func (e *Entry) Err(err error) *Entry { 935 return e.AnErr("error", err) 936 } 937 938 // AnErr adds the field key with serialized err to the logger context. 939 func (e *Entry) AnErr(key string, err error) *Entry { 940 if e == nil { 941 return nil 942 } 943 944 if err == nil { 945 e.buf = append(e.buf, ',', '"') 946 e.buf = append(e.buf, key...) 947 e.buf = append(e.buf, "\":null"...) 948 return e 949 } 950 951 e.buf = append(e.buf, ',', '"') 952 e.buf = append(e.buf, key...) 953 e.buf = append(e.buf, '"', ':') 954 if o, ok := err.(ObjectMarshaler); ok { 955 o.MarshalObject(e) 956 } else { 957 e.buf = append(e.buf, '"') 958 e.string(err.Error()) 959 e.buf = append(e.buf, '"') 960 } 961 return e 962 } 963 964 // Errs adds the field key with errs as an array of serialized errors to the entry. 965 func (e *Entry) Errs(key string, errs []error) *Entry { 966 if e == nil { 967 return nil 968 } 969 970 e.buf = append(e.buf, ',', '"') 971 e.buf = append(e.buf, key...) 972 e.buf = append(e.buf, '"', ':', '[') 973 for i, err := range errs { 974 if i != 0 { 975 e.buf = append(e.buf, ',') 976 } 977 if err == nil { 978 e.buf = append(e.buf, "null"...) 979 } else { 980 e.buf = append(e.buf, '"') 981 e.string(err.Error()) 982 e.buf = append(e.buf, '"') 983 } 984 } 985 e.buf = append(e.buf, ']') 986 return e 987 } 988 989 // https://github.com/golang/go/blob/master/src/encoding/json/encode.go#L541 990 func appendFloat(b []byte, f float64, bits int) []byte { 991 switch { 992 case math.IsNaN(f): 993 return append(b, `"NaN"`...) 994 case math.IsInf(f, 1): 995 return append(b, `"+Inf"`...) 996 case math.IsInf(f, -1): 997 return append(b, `"-Inf"`...) 998 } 999 abs := math.Abs(f) 1000 fmt := byte('f') 1001 // Note: Must use float32 comparisons for underlying float32 value to get precise cutoffs right. 1002 if abs != 0 { 1003 if bits == 64 && (abs < 1e-6 || abs >= 1e21) || bits == 32 && (float32(abs) < 1e-6 || float32(abs) >= 1e21) { 1004 fmt = 'e' 1005 } 1006 } 1007 b = strconv.AppendFloat(b, f, fmt, -1, int(bits)) 1008 if fmt == 'e' { 1009 // clean up e-09 to e-9 1010 n := len(b) 1011 if n >= 4 && b[n-4] == 'e' && b[n-3] == '-' && b[n-2] == '0' { 1012 b[n-2] = b[n-1] 1013 b = b[:n-1] 1014 } 1015 } 1016 return b 1017 } 1018 1019 // Float64 adds the field key with f as a float64 to the entry. 1020 func (e *Entry) Float64(key string, f float64) *Entry { 1021 if e == nil { 1022 return nil 1023 } 1024 e.buf = append(e.buf, ',', '"') 1025 e.buf = append(e.buf, key...) 1026 e.buf = append(e.buf, '"', ':') 1027 e.buf = appendFloat(e.buf, f, 64) 1028 return e 1029 } 1030 1031 // Float32 adds the field key with f as a float32 to the entry. 1032 func (e *Entry) Float32(key string, f float32) *Entry { 1033 if e == nil { 1034 return nil 1035 } 1036 e.buf = append(e.buf, ',', '"') 1037 e.buf = append(e.buf, key...) 1038 e.buf = append(e.buf, '"', ':') 1039 e.buf = appendFloat(e.buf, float64(f), 32) 1040 return e 1041 } 1042 1043 // Floats64 adds the field key with f as a []float64 to the entry. 1044 func (e *Entry) Floats64(key string, f []float64) *Entry { 1045 if e == nil { 1046 return nil 1047 } 1048 e.buf = append(e.buf, ',', '"') 1049 e.buf = append(e.buf, key...) 1050 e.buf = append(e.buf, '"', ':', '[') 1051 for i, a := range f { 1052 if i != 0 { 1053 e.buf = append(e.buf, ',') 1054 } 1055 e.buf = appendFloat(e.buf, a, 64) 1056 } 1057 e.buf = append(e.buf, ']') 1058 return e 1059 } 1060 1061 // Floats32 adds the field key with f as a []float32 to the entry. 1062 func (e *Entry) Floats32(key string, f []float32) *Entry { 1063 if e == nil { 1064 return nil 1065 } 1066 e.buf = append(e.buf, ',', '"') 1067 e.buf = append(e.buf, key...) 1068 e.buf = append(e.buf, '"', ':', '[') 1069 for i, a := range f { 1070 if i != 0 { 1071 e.buf = append(e.buf, ',') 1072 } 1073 e.buf = appendFloat(e.buf, float64(a), 32) 1074 } 1075 e.buf = append(e.buf, ']') 1076 return e 1077 } 1078 1079 // Int64 adds the field key with i as a int64 to the entry. 1080 func (e *Entry) Int64(key string, i int64) *Entry { 1081 if e == nil { 1082 return nil 1083 } 1084 e.buf = append(e.buf, ',', '"') 1085 e.buf = append(e.buf, key...) 1086 e.buf = append(e.buf, '"', ':') 1087 e.buf = strconv.AppendInt(e.buf, i, 10) 1088 return e 1089 } 1090 1091 // Uint adds the field key with i as a uint to the entry. 1092 func (e *Entry) Uint(key string, i uint) *Entry { 1093 if e == nil { 1094 return nil 1095 } 1096 e.buf = append(e.buf, ',', '"') 1097 e.buf = append(e.buf, key...) 1098 e.buf = append(e.buf, '"', ':') 1099 e.buf = strconv.AppendUint(e.buf, uint64(i), 10) 1100 return e 1101 } 1102 1103 // Uint64 adds the field key with i as a uint64 to the entry. 1104 func (e *Entry) Uint64(key string, i uint64) *Entry { 1105 if e == nil { 1106 return nil 1107 } 1108 e.buf = append(e.buf, ',', '"') 1109 e.buf = append(e.buf, key...) 1110 e.buf = append(e.buf, '"', ':') 1111 e.buf = strconv.AppendUint(e.buf, i, 10) 1112 return e 1113 } 1114 1115 // Int adds the field key with i as a int to the entry. 1116 func (e *Entry) Int(key string, i int) *Entry { 1117 return e.Int64(key, int64(i)) 1118 } 1119 1120 // Int32 adds the field key with i as a int32 to the entry. 1121 func (e *Entry) Int32(key string, i int32) *Entry { 1122 return e.Int64(key, int64(i)) 1123 } 1124 1125 // Int16 adds the field key with i as a int16 to the entry. 1126 func (e *Entry) Int16(key string, i int16) *Entry { 1127 return e.Int64(key, int64(i)) 1128 } 1129 1130 // Int8 adds the field key with i as a int8 to the entry. 1131 func (e *Entry) Int8(key string, i int8) *Entry { 1132 return e.Int64(key, int64(i)) 1133 } 1134 1135 // Uint32 adds the field key with i as a uint32 to the entry. 1136 func (e *Entry) Uint32(key string, i uint32) *Entry { 1137 return e.Uint64(key, uint64(i)) 1138 } 1139 1140 // Uint16 adds the field key with i as a uint16 to the entry. 1141 func (e *Entry) Uint16(key string, i uint16) *Entry { 1142 return e.Uint64(key, uint64(i)) 1143 } 1144 1145 // Uint8 adds the field key with i as a uint8 to the entry. 1146 func (e *Entry) Uint8(key string, i uint8) *Entry { 1147 return e.Uint64(key, uint64(i)) 1148 } 1149 1150 // Ints64 adds the field key with i as a []int64 to the entry. 1151 func (e *Entry) Ints64(key string, a []int64) *Entry { 1152 if e == nil { 1153 return nil 1154 } 1155 e.buf = append(e.buf, ',', '"') 1156 e.buf = append(e.buf, key...) 1157 e.buf = append(e.buf, '"', ':', '[') 1158 for i, n := range a { 1159 if i != 0 { 1160 e.buf = append(e.buf, ',') 1161 } 1162 e.buf = strconv.AppendInt(e.buf, n, 10) 1163 } 1164 e.buf = append(e.buf, ']') 1165 return e 1166 } 1167 1168 // Ints32 adds the field key with i as a []int32 to the entry. 1169 func (e *Entry) Ints32(key string, a []int32) *Entry { 1170 if e == nil { 1171 return nil 1172 } 1173 e.buf = append(e.buf, ',', '"') 1174 e.buf = append(e.buf, key...) 1175 e.buf = append(e.buf, '"', ':', '[') 1176 for i, n := range a { 1177 if i != 0 { 1178 e.buf = append(e.buf, ',') 1179 } 1180 e.buf = strconv.AppendInt(e.buf, int64(n), 10) 1181 } 1182 e.buf = append(e.buf, ']') 1183 return e 1184 } 1185 1186 // Ints16 adds the field key with i as a []int16 to the entry. 1187 func (e *Entry) Ints16(key string, a []int16) *Entry { 1188 if e == nil { 1189 return nil 1190 } 1191 e.buf = append(e.buf, ',', '"') 1192 e.buf = append(e.buf, key...) 1193 e.buf = append(e.buf, '"', ':', '[') 1194 for i, n := range a { 1195 if i != 0 { 1196 e.buf = append(e.buf, ',') 1197 } 1198 e.buf = strconv.AppendInt(e.buf, int64(n), 10) 1199 } 1200 e.buf = append(e.buf, ']') 1201 return e 1202 } 1203 1204 // Ints8 adds the field key with i as a []int8 to the entry. 1205 func (e *Entry) Ints8(key string, a []int8) *Entry { 1206 if e == nil { 1207 return nil 1208 } 1209 e.buf = append(e.buf, ',', '"') 1210 e.buf = append(e.buf, key...) 1211 e.buf = append(e.buf, '"', ':', '[') 1212 for i, n := range a { 1213 if i != 0 { 1214 e.buf = append(e.buf, ',') 1215 } 1216 e.buf = strconv.AppendInt(e.buf, int64(n), 10) 1217 } 1218 e.buf = append(e.buf, ']') 1219 return e 1220 } 1221 1222 // Ints adds the field key with i as a []int to the entry. 1223 func (e *Entry) Ints(key string, a []int) *Entry { 1224 if e == nil { 1225 return nil 1226 } 1227 e.buf = append(e.buf, ',', '"') 1228 e.buf = append(e.buf, key...) 1229 e.buf = append(e.buf, '"', ':', '[') 1230 for i, n := range a { 1231 if i != 0 { 1232 e.buf = append(e.buf, ',') 1233 } 1234 e.buf = strconv.AppendInt(e.buf, int64(n), 10) 1235 } 1236 e.buf = append(e.buf, ']') 1237 return e 1238 } 1239 1240 // Uints64 adds the field key with i as a []uint64 to the entry. 1241 func (e *Entry) Uints64(key string, a []uint64) *Entry { 1242 if e == nil { 1243 return nil 1244 } 1245 e.buf = append(e.buf, ',', '"') 1246 e.buf = append(e.buf, key...) 1247 e.buf = append(e.buf, '"', ':', '[') 1248 for i, n := range a { 1249 if i != 0 { 1250 e.buf = append(e.buf, ',') 1251 } 1252 e.buf = strconv.AppendUint(e.buf, n, 10) 1253 } 1254 e.buf = append(e.buf, ']') 1255 return e 1256 } 1257 1258 // Uints32 adds the field key with i as a []uint32 to the entry. 1259 func (e *Entry) Uints32(key string, a []uint32) *Entry { 1260 if e == nil { 1261 return nil 1262 } 1263 e.buf = append(e.buf, ',', '"') 1264 e.buf = append(e.buf, key...) 1265 e.buf = append(e.buf, '"', ':', '[') 1266 for i, n := range a { 1267 if i != 0 { 1268 e.buf = append(e.buf, ',') 1269 } 1270 e.buf = strconv.AppendUint(e.buf, uint64(n), 10) 1271 } 1272 e.buf = append(e.buf, ']') 1273 return e 1274 } 1275 1276 // Uints16 adds the field key with i as a []uint16 to the entry. 1277 func (e *Entry) Uints16(key string, a []uint16) *Entry { 1278 if e == nil { 1279 return nil 1280 } 1281 e.buf = append(e.buf, ',', '"') 1282 e.buf = append(e.buf, key...) 1283 e.buf = append(e.buf, '"', ':', '[') 1284 for i, n := range a { 1285 if i != 0 { 1286 e.buf = append(e.buf, ',') 1287 } 1288 e.buf = strconv.AppendUint(e.buf, uint64(n), 10) 1289 } 1290 e.buf = append(e.buf, ']') 1291 return e 1292 } 1293 1294 // Uints8 adds the field key with i as a []uint8 to the entry. 1295 func (e *Entry) Uints8(key string, a []uint8) *Entry { 1296 if e == nil { 1297 return nil 1298 } 1299 e.buf = append(e.buf, ',', '"') 1300 e.buf = append(e.buf, key...) 1301 e.buf = append(e.buf, '"', ':', '[') 1302 for i, n := range a { 1303 if i != 0 { 1304 e.buf = append(e.buf, ',') 1305 } 1306 e.buf = strconv.AppendUint(e.buf, uint64(n), 10) 1307 } 1308 e.buf = append(e.buf, ']') 1309 return e 1310 } 1311 1312 // Uints adds the field key with i as a []uint to the entry. 1313 func (e *Entry) Uints(key string, a []uint) *Entry { 1314 if e == nil { 1315 return nil 1316 } 1317 e.buf = append(e.buf, ',', '"') 1318 e.buf = append(e.buf, key...) 1319 e.buf = append(e.buf, '"', ':', '[') 1320 for i, n := range a { 1321 if i != 0 { 1322 e.buf = append(e.buf, ',') 1323 } 1324 e.buf = strconv.AppendUint(e.buf, uint64(n), 10) 1325 } 1326 e.buf = append(e.buf, ']') 1327 return e 1328 } 1329 1330 // RawJSON adds already encoded JSON to the log line under key. 1331 func (e *Entry) RawJSON(key string, b []byte) *Entry { 1332 if e == nil { 1333 return nil 1334 } 1335 e.buf = append(e.buf, ',', '"') 1336 e.buf = append(e.buf, key...) 1337 e.buf = append(e.buf, '"', ':') 1338 e.buf = append(e.buf, b...) 1339 return e 1340 } 1341 1342 // RawJSONStr adds already encoded JSON String to the log line under key. 1343 func (e *Entry) RawJSONStr(key string, s string) *Entry { 1344 if e == nil { 1345 return nil 1346 } 1347 e.buf = append(e.buf, ',', '"') 1348 e.buf = append(e.buf, key...) 1349 e.buf = append(e.buf, '"', ':') 1350 e.buf = append(e.buf, s...) 1351 return e 1352 } 1353 1354 // Str adds the field key with val as a string to the entry. 1355 func (e *Entry) Str(key string, val string) *Entry { 1356 if e == nil { 1357 return nil 1358 } 1359 e.buf = append(e.buf, ',', '"') 1360 e.buf = append(e.buf, key...) 1361 e.buf = append(e.buf, '"', ':', '"') 1362 e.string(val) 1363 e.buf = append(e.buf, '"') 1364 return e 1365 } 1366 1367 // StrInt adds the field key with integer val as a string to the entry. 1368 func (e *Entry) StrInt(key string, val int64) *Entry { 1369 if e == nil { 1370 return nil 1371 } 1372 e.buf = append(e.buf, ',', '"') 1373 e.buf = append(e.buf, key...) 1374 e.buf = append(e.buf, '"', ':', '"') 1375 e.buf = strconv.AppendInt(e.buf, val, 10) 1376 e.buf = append(e.buf, '"') 1377 return e 1378 } 1379 1380 // Stringer adds the field key with val.String() to the entry. 1381 func (e *Entry) Stringer(key string, val fmt.Stringer) *Entry { 1382 if e == nil { 1383 return nil 1384 } 1385 e.buf = append(e.buf, ',', '"') 1386 e.buf = append(e.buf, key...) 1387 e.buf = append(e.buf, '"', ':') 1388 if val != nil { 1389 e.buf = append(e.buf, '"') 1390 e.string(val.String()) 1391 e.buf = append(e.buf, '"') 1392 } else { 1393 e.buf = append(e.buf, "null"...) 1394 } 1395 return e 1396 } 1397 1398 // GoStringer adds the field key with val.GoStringer() to the entry. 1399 func (e *Entry) GoStringer(key string, val fmt.GoStringer) *Entry { 1400 if e == nil { 1401 return nil 1402 } 1403 e.buf = append(e.buf, ',', '"') 1404 e.buf = append(e.buf, key...) 1405 e.buf = append(e.buf, '"', ':') 1406 if val != nil { 1407 e.buf = append(e.buf, '"') 1408 e.string(val.GoString()) 1409 e.buf = append(e.buf, '"') 1410 } else { 1411 e.buf = append(e.buf, "null"...) 1412 } 1413 return e 1414 } 1415 1416 // Strs adds the field key with vals as a []string to the entry. 1417 func (e *Entry) Strs(key string, vals []string) *Entry { 1418 if e == nil { 1419 return nil 1420 } 1421 e.buf = append(e.buf, ',', '"') 1422 e.buf = append(e.buf, key...) 1423 e.buf = append(e.buf, '"', ':', '[') 1424 for i, val := range vals { 1425 if i != 0 { 1426 e.buf = append(e.buf, ',') 1427 } 1428 e.buf = append(e.buf, '"') 1429 e.string(val) 1430 e.buf = append(e.buf, '"') 1431 } 1432 e.buf = append(e.buf, ']') 1433 return e 1434 } 1435 1436 // Byte adds the field key with val as a byte to the entry. 1437 func (e *Entry) Byte(key string, val byte) *Entry { 1438 if e == nil { 1439 return nil 1440 } 1441 e.buf = append(e.buf, ',', '"') 1442 e.buf = append(e.buf, key...) 1443 e.buf = append(e.buf, '"', ':') 1444 switch val { 1445 case '"': 1446 e.buf = append(e.buf, "\"\\\"\""...) 1447 case '\\': 1448 e.buf = append(e.buf, "\"\\\\\""...) 1449 case '\n': 1450 e.buf = append(e.buf, "\"\\n\""...) 1451 case '\r': 1452 e.buf = append(e.buf, "\"\\r\""...) 1453 case '\t': 1454 e.buf = append(e.buf, "\"\\t\""...) 1455 case '\f': 1456 e.buf = append(e.buf, "\"\\u000c\""...) 1457 case '\b': 1458 e.buf = append(e.buf, "\"\\u0008\""...) 1459 case '<': 1460 e.buf = append(e.buf, "\"\\u003c\""...) 1461 case '\'': 1462 e.buf = append(e.buf, "\"\\u0027\""...) 1463 case 0: 1464 e.buf = append(e.buf, "\"\\u0000\""...) 1465 default: 1466 e.buf = append(e.buf, '"', val, '"') 1467 } 1468 return e 1469 } 1470 1471 // Bytes adds the field key with val as a string to the entry. 1472 func (e *Entry) Bytes(key string, val []byte) *Entry { 1473 if e == nil { 1474 return nil 1475 } 1476 e.buf = append(e.buf, ',', '"') 1477 e.buf = append(e.buf, key...) 1478 e.buf = append(e.buf, '"', ':', '"') 1479 e.bytes(val) 1480 e.buf = append(e.buf, '"') 1481 return e 1482 } 1483 1484 // BytesOrNil adds the field key with val as a string or nil to the entry. 1485 func (e *Entry) BytesOrNil(key string, val []byte) *Entry { 1486 if e == nil { 1487 return nil 1488 } 1489 e.buf = append(e.buf, ',', '"') 1490 e.buf = append(e.buf, key...) 1491 e.buf = append(e.buf, '"', ':') 1492 if val == nil { 1493 e.buf = append(e.buf, "null"...) 1494 } else { 1495 e.buf = append(e.buf, '"') 1496 e.bytes(val) 1497 e.buf = append(e.buf, '"') 1498 } 1499 return e 1500 } 1501 1502 const hex = "0123456789abcdef" 1503 1504 // Hex adds the field key with val as a hex string to the entry. 1505 func (e *Entry) Hex(key string, val []byte) *Entry { 1506 if e == nil { 1507 return nil 1508 } 1509 e.buf = append(e.buf, ',', '"') 1510 e.buf = append(e.buf, key...) 1511 e.buf = append(e.buf, '"', ':', '"') 1512 for _, v := range val { 1513 e.buf = append(e.buf, hex[v>>4], hex[v&0x0f]) 1514 } 1515 e.buf = append(e.buf, '"') 1516 return e 1517 } 1518 1519 // Encode encodes bytes using enc.AppendEncode to the entry. 1520 func (e *Entry) Encode(key string, val []byte, enc interface { 1521 AppendEncode(dst, src []byte) []byte 1522 }) *Entry { 1523 if e == nil { 1524 return nil 1525 } 1526 e.buf = append(e.buf, ',', '"') 1527 e.buf = append(e.buf, key...) 1528 e.buf = append(e.buf, '"', ':', '"') 1529 e.buf = enc.AppendEncode(e.buf, val) 1530 e.buf = append(e.buf, '"') 1531 return e 1532 } 1533 1534 // Xid adds the field key with xid.ID as a base32 string to the entry. 1535 func (e *Entry) Xid(key string, id int64) *Entry { 1536 if e == nil { 1537 return nil 1538 } 1539 e.buf = append(e.buf, ',', '"') 1540 e.buf = append(e.buf, key...) 1541 e.buf = append(e.buf, '"', ':', '"') 1542 e.buf = append(e.buf, (ID(id)).String()...) 1543 e.buf = append(e.buf, '"') 1544 1545 return e 1546 } 1547 1548 // IPAddr adds IPv4 or IPv6 Address to the entry. 1549 func (e *Entry) IPAddr(key string, ip net.IP) *Entry { 1550 if e == nil { 1551 return nil 1552 } 1553 e.buf = append(e.buf, ',', '"') 1554 e.buf = append(e.buf, key...) 1555 e.buf = append(e.buf, '"', ':', '"') 1556 if ip4 := ip.To4(); ip4 != nil { 1557 _ = ip4[3] 1558 e.buf = strconv.AppendInt(e.buf, int64(ip4[0]), 10) 1559 e.buf = append(e.buf, '.') 1560 e.buf = strconv.AppendInt(e.buf, int64(ip4[1]), 10) 1561 e.buf = append(e.buf, '.') 1562 e.buf = strconv.AppendInt(e.buf, int64(ip4[2]), 10) 1563 e.buf = append(e.buf, '.') 1564 e.buf = strconv.AppendInt(e.buf, int64(ip4[3]), 10) 1565 } else if a, ok := netip.AddrFromSlice(ip); ok { 1566 e.buf = a.AppendTo(e.buf) 1567 } 1568 e.buf = append(e.buf, '"') 1569 return e 1570 } 1571 1572 // IPPrefix adds IPv4 or IPv6 Prefix (address and mask) to the entry. 1573 func (e *Entry) IPPrefix(key string, pfx net.IPNet) *Entry { 1574 if e == nil { 1575 return nil 1576 } 1577 e.buf = append(e.buf, ',', '"') 1578 e.buf = append(e.buf, key...) 1579 e.buf = append(e.buf, '"', ':', '"') 1580 e.buf = append(e.buf, pfx.String()...) 1581 e.buf = append(e.buf, '"') 1582 return e 1583 } 1584 1585 // MACAddr adds MAC address to the entry. 1586 func (e *Entry) MACAddr(key string, ha net.HardwareAddr) *Entry { 1587 if e == nil { 1588 return nil 1589 } 1590 e.buf = append(e.buf, ',', '"') 1591 e.buf = append(e.buf, key...) 1592 e.buf = append(e.buf, '"', ':', '"') 1593 for i, c := range ha { 1594 if i > 0 { 1595 e.buf = append(e.buf, ':') 1596 } 1597 e.buf = append(e.buf, hex[c>>4]) 1598 e.buf = append(e.buf, hex[c&0xF]) 1599 } 1600 e.buf = append(e.buf, '"') 1601 return e 1602 } 1603 1604 // NetIPAddr adds IPv4 or IPv6 Address to the entry. 1605 func (e *Entry) NetIPAddr(key string, ip netip.Addr) *Entry { 1606 if e == nil { 1607 return nil 1608 } 1609 e.buf = append(e.buf, ',', '"') 1610 e.buf = append(e.buf, key...) 1611 e.buf = append(e.buf, '"', ':', '"') 1612 e.buf = ip.AppendTo(e.buf) 1613 e.buf = append(e.buf, '"') 1614 return e 1615 } 1616 1617 // NetIPAddrPort adds IPv4 or IPv6 with Port Address to the entry. 1618 func (e *Entry) NetIPAddrPort(key string, ipPort netip.AddrPort) *Entry { 1619 if e == nil { 1620 return nil 1621 } 1622 e.buf = append(e.buf, ',', '"') 1623 e.buf = append(e.buf, key...) 1624 e.buf = append(e.buf, '"', ':', '"') 1625 e.buf = ipPort.AppendTo(e.buf) 1626 e.buf = append(e.buf, '"') 1627 return e 1628 } 1629 1630 // NetIPPrefix adds IPv4 or IPv6 Prefix (address and mask) to the entry. 1631 func (e *Entry) NetIPPrefix(key string, pfx netip.Prefix) *Entry { 1632 if e == nil { 1633 return nil 1634 } 1635 e.buf = append(e.buf, ',', '"') 1636 e.buf = append(e.buf, key...) 1637 e.buf = append(e.buf, '"', ':', '"') 1638 e.buf = pfx.AppendTo(e.buf) 1639 e.buf = append(e.buf, '"') 1640 return e 1641 } 1642 1643 // Type adds type of the key using reflection to the entry. 1644 func (e *Entry) Type(key string, v interface{}) *Entry { 1645 if e == nil { 1646 return nil 1647 } 1648 e.buf = append(e.buf, ',', '"') 1649 e.buf = append(e.buf, key...) 1650 e.buf = append(e.buf, '"', ':', '"') 1651 e.buf = append(e.buf, reflect.TypeOf(v).String()...) 1652 e.buf = append(e.buf, '"') 1653 return e 1654 } 1655 1656 // Caller adds the file:line of the "caller" key. 1657 // If depth is negative, adds the full /path/to/file:line of the "caller" key. 1658 func (e *Entry) Caller(depth int) *Entry { 1659 if e != nil { 1660 var full bool 1661 var pc uintptr 1662 if depth < 0 { 1663 depth, full = -depth, true 1664 } 1665 e.caller(caller1(depth, &pc, 1, 1), pc, full) 1666 } 1667 return e 1668 } 1669 1670 // Stack enables stack trace printing for the error passed to Err(). 1671 func (e *Entry) Stack() *Entry { 1672 if e != nil { 1673 e.buf = append(e.buf, ",\"stack\":\""...) 1674 e.bytes(stacks(false)) 1675 e.buf = append(e.buf, '"') 1676 } 1677 return e 1678 } 1679 1680 // Enabled return false if the entry is going to be filtered out by log level. 1681 func (e *Entry) Enabled() bool { 1682 return e != nil 1683 } 1684 1685 // Discard disables the entry so Msg(f) won't print it. 1686 func (e *Entry) Discard() *Entry { 1687 if e == nil { 1688 return e 1689 } 1690 if cap(e.buf) <= bbcap { 1691 epool.Put(e) 1692 } 1693 return nil 1694 } 1695 1696 var notTest = true 1697 1698 // Msg sends the entry with msg added as the message field if not empty. 1699 func (e *Entry) Msg(msg string) { 1700 if e == nil { 1701 return 1702 } 1703 if DefaultLogger.EnableTracing { 1704 if e.context == nil { 1705 e.Str(DefaultLogger.TraceIDField, NewID().String()) 1706 } else { 1707 traceID := e.context.Value(DefaultLogger.TraceIDField) 1708 if traceID == nil { 1709 e.Str(DefaultLogger.TraceIDField, NewID().String()) 1710 } else { 1711 switch v := traceID.(type) { 1712 case string: 1713 if v == "" { 1714 e.Str(DefaultLogger.TraceIDField, NewID().String()) 1715 } else { 1716 e.Str(DefaultLogger.TraceIDField, v) 1717 } 1718 case int64: 1719 e.Int64(DefaultLogger.TraceIDField, v) 1720 } 1721 } 1722 } 1723 } 1724 if DefaultLogger.LogNode { 1725 hostname, _ := fqdn.Hostname() 1726 e.Str("host_platform", hostname) 1727 } 1728 if msg != "" { 1729 e.buf = append(e.buf, ",\"message\":\""...) 1730 e.string(msg) 1731 e.buf = append(e.buf, "\"}\n"...) 1732 } else { 1733 e.buf = append(e.buf, '}', '\n') 1734 } 1735 _, _ = e.w.WriteEntry(e) 1736 if (e.Level == FatalLevel) && notTest { 1737 os.Exit(255) 1738 } 1739 if (e.Level == PanicLevel) && notTest { 1740 panic(msg) 1741 } 1742 if cap(e.buf) <= bbcap { 1743 epool.Put(e) 1744 } 1745 } 1746 1747 type bb struct { 1748 B []byte 1749 } 1750 1751 func (b *bb) Write(p []byte) (int, error) { 1752 b.B = append(b.B, p...) 1753 return len(p), nil 1754 } 1755 1756 var bbpool = sync.Pool{ 1757 New: func() interface{} { 1758 return new(bb) 1759 }, 1760 } 1761 1762 func (e *Entry) Copy() Logger { 1763 logger := Logger{ 1764 Context: e.buf, 1765 } 1766 if e.logger != nil { 1767 logger.TimeField = e.logger.TimeField 1768 logger.LogNode = e.logger.LogNode 1769 logger.EnableTracing = e.logger.EnableTracing 1770 logger.TraceIDField = e.logger.TraceIDField 1771 logger.Caller = e.logger.Caller 1772 logger.TimeFormat = e.logger.TimeFormat 1773 logger.TimeLocation = e.logger.TimeLocation 1774 logger.Writer = e.logger.Writer 1775 logger.Level = e.logger.Level 1776 } 1777 return logger 1778 } 1779 1780 // Msgf sends the entry with formatted msg added as the message field if not empty. 1781 func (e *Entry) Msgf(format string, v ...interface{}) { 1782 if e == nil { 1783 return 1784 } 1785 b := bbpool.Get().(*bb) 1786 b.B = b.B[:0] 1787 e.buf = append(e.buf, ",\"message\":\""...) 1788 fmt.Fprintf(b, format, v...) 1789 e.bytes(b.B) 1790 e.buf = append(e.buf, '"') 1791 if cap(b.B) <= bbcap { 1792 bbpool.Put(b) 1793 } 1794 e.Msg("") 1795 } 1796 1797 // Msgs sends the entry with msgs added as the message field if not empty. 1798 func (e *Entry) Msgs(args ...interface{}) { 1799 if e == nil { 1800 return 1801 } 1802 b := bbpool.Get().(*bb) 1803 b.B = b.B[:0] 1804 e.buf = append(e.buf, ",\"message\":\""...) 1805 fmt.Fprint(b, args...) 1806 e.bytes(b.B) 1807 e.buf = append(e.buf, '"') 1808 if cap(b.B) <= bbcap { 1809 bbpool.Put(b) 1810 } 1811 e.Msg("") 1812 } 1813 1814 func (e *Entry) caller(n int, pc uintptr, fullpath bool) { 1815 if n < 1 { 1816 return 1817 } 1818 1819 file, line := pcFileLine(pc) 1820 if !fullpath { 1821 var i, j int 1822 for i = len(file) - 1; i >= 0; i-- { 1823 if file[i] == '/' { 1824 break 1825 } 1826 } 1827 if i > 0 { 1828 for j = i - 1; j >= 0; j-- { 1829 if file[j] == '/' { 1830 break 1831 } 1832 } 1833 if j > 0 { 1834 i = j 1835 } 1836 file = file[i+1:] 1837 } 1838 } 1839 1840 e.buf = append(e.buf, ",\"caller\":\""...) 1841 e.buf = append(e.buf, file...) 1842 e.buf = append(e.buf, ':') 1843 e.buf = strconv.AppendInt(e.buf, int64(line), 10) 1844 e.buf = append(e.buf, "\",\"goid\":"...) 1845 e.buf = strconv.AppendInt(e.buf, int64(goid()), 10) 1846 } 1847 1848 var escapes = [256]bool{ 1849 '"': true, 1850 '<': true, 1851 '\'': true, 1852 '\\': true, 1853 '\b': true, 1854 '\f': true, 1855 '\n': true, 1856 '\r': true, 1857 '\t': true, 1858 } 1859 1860 func (e *Entry) escapeb(b []byte) { 1861 n := len(b) 1862 j := 0 1863 if n > 0 { 1864 // Hint the compiler to remove bounds checks in the loop below. 1865 _ = b[n-1] 1866 } 1867 for i := 0; i < n; i++ { 1868 switch b[i] { 1869 case '"': 1870 e.buf = append(e.buf, b[j:i]...) 1871 e.buf = append(e.buf, '\\', '"') 1872 j = i + 1 1873 case '\\': 1874 e.buf = append(e.buf, b[j:i]...) 1875 e.buf = append(e.buf, '\\', '\\') 1876 j = i + 1 1877 case '\n': 1878 e.buf = append(e.buf, b[j:i]...) 1879 e.buf = append(e.buf, '\\', 'n') 1880 j = i + 1 1881 case '\r': 1882 e.buf = append(e.buf, b[j:i]...) 1883 e.buf = append(e.buf, '\\', 'r') 1884 j = i + 1 1885 case '\t': 1886 e.buf = append(e.buf, b[j:i]...) 1887 e.buf = append(e.buf, '\\', 't') 1888 j = i + 1 1889 case '\f': 1890 e.buf = append(e.buf, b[j:i]...) 1891 e.buf = append(e.buf, '\\', 'u', '0', '0', '0', 'c') 1892 j = i + 1 1893 case '\b': 1894 e.buf = append(e.buf, b[j:i]...) 1895 e.buf = append(e.buf, '\\', 'u', '0', '0', '0', '8') 1896 j = i + 1 1897 case '<': 1898 e.buf = append(e.buf, b[j:i]...) 1899 e.buf = append(e.buf, '\\', 'u', '0', '0', '3', 'c') 1900 j = i + 1 1901 case '\'': 1902 e.buf = append(e.buf, b[j:i]...) 1903 e.buf = append(e.buf, '\\', 'u', '0', '0', '2', '7') 1904 j = i + 1 1905 case 0: 1906 e.buf = append(e.buf, b[j:i]...) 1907 e.buf = append(e.buf, '\\', 'u', '0', '0', '0', '0') 1908 j = i + 1 1909 } 1910 } 1911 e.buf = append(e.buf, b[j:]...) 1912 } 1913 1914 func (e *Entry) escapes(s string) { 1915 n := len(s) 1916 j := 0 1917 if n > 0 { 1918 // Hint the compiler to remove bounds checks in the loop below. 1919 _ = s[n-1] 1920 } 1921 for i := 0; i < n; i++ { 1922 switch s[i] { 1923 case '"': 1924 e.buf = append(e.buf, s[j:i]...) 1925 e.buf = append(e.buf, '\\', '"') 1926 j = i + 1 1927 case '\\': 1928 e.buf = append(e.buf, s[j:i]...) 1929 e.buf = append(e.buf, '\\', '\\') 1930 j = i + 1 1931 case '\n': 1932 e.buf = append(e.buf, s[j:i]...) 1933 e.buf = append(e.buf, '\\', 'n') 1934 j = i + 1 1935 case '\r': 1936 e.buf = append(e.buf, s[j:i]...) 1937 e.buf = append(e.buf, '\\', 'r') 1938 j = i + 1 1939 case '\t': 1940 e.buf = append(e.buf, s[j:i]...) 1941 e.buf = append(e.buf, '\\', 't') 1942 j = i + 1 1943 case '\f': 1944 e.buf = append(e.buf, s[j:i]...) 1945 e.buf = append(e.buf, '\\', 'u', '0', '0', '0', 'c') 1946 j = i + 1 1947 case '\b': 1948 e.buf = append(e.buf, s[j:i]...) 1949 e.buf = append(e.buf, '\\', 'u', '0', '0', '0', '8') 1950 j = i + 1 1951 case '<': 1952 e.buf = append(e.buf, s[j:i]...) 1953 e.buf = append(e.buf, '\\', 'u', '0', '0', '3', 'c') 1954 j = i + 1 1955 case '\'': 1956 e.buf = append(e.buf, s[j:i]...) 1957 e.buf = append(e.buf, '\\', 'u', '0', '0', '2', '7') 1958 j = i + 1 1959 case 0: 1960 e.buf = append(e.buf, s[j:i]...) 1961 e.buf = append(e.buf, '\\', 'u', '0', '0', '0', '0') 1962 j = i + 1 1963 } 1964 } 1965 e.buf = append(e.buf, s[j:]...) 1966 } 1967 1968 func (e *Entry) string(s string) { 1969 for _, c := range []byte(s) { 1970 if escapes[c] { 1971 e.escapes(s) 1972 return 1973 } 1974 } 1975 e.buf = append(e.buf, s...) 1976 } 1977 1978 func (e *Entry) bytes(b []byte) { 1979 for _, c := range b { 1980 if escapes[c] { 1981 e.escapeb(b) 1982 return 1983 } 1984 } 1985 e.buf = append(e.buf, b...) 1986 } 1987 1988 // Interface adds the field key with i marshaled using reflection. 1989 func (e *Entry) Interface(key string, i interface{}) *Entry { 1990 if e == nil { 1991 return nil 1992 } 1993 1994 if o, ok := i.(ObjectMarshaler); ok { 1995 return e.Object(key, o) 1996 } 1997 1998 e.buf = append(e.buf, ',', '"') 1999 e.buf = append(e.buf, key...) 2000 e.buf = append(e.buf, '"', ':', '"') 2001 b := bbpool.Get().(*bb) 2002 b.B = b.B[:0] 2003 enc := json.NewEncoder(b) 2004 enc.SetEscapeHTML(false) 2005 err := enc.Encode(i) 2006 if err != nil { 2007 b.B = b.B[:0] 2008 fmt.Fprintf(b, "marshaling error: %+v", err) 2009 } else { 2010 b.B = b.B[:len(b.B)-1] 2011 } 2012 e.bytes(b.B) 2013 e.buf = append(e.buf, '"') 2014 if cap(b.B) <= bbcap { 2015 bbpool.Put(b) 2016 } 2017 2018 return e 2019 } 2020 2021 // Object marshals an object that implement the ObjectMarshaler interface. 2022 func (e *Entry) Object(key string, obj ObjectMarshaler) *Entry { 2023 if e == nil { 2024 return nil 2025 } 2026 2027 e.buf = append(e.buf, ',', '"') 2028 e.buf = append(e.buf, key...) 2029 e.buf = append(e.buf, '"', ':') 2030 if obj == nil || (*[2]uintptr)(unsafe.Pointer(&obj))[1] == 0 { 2031 e.buf = append(e.buf, "null"...) 2032 return e 2033 } 2034 2035 n := len(e.buf) 2036 obj.MarshalObject(e) 2037 if n < len(e.buf) { 2038 e.buf[n] = '{' 2039 e.buf = append(e.buf, '}') 2040 } else { 2041 e.buf = append(e.buf, "null"...) 2042 } 2043 2044 return e 2045 } 2046 2047 // Func allows an anonymous func to run only if the entry is enabled. 2048 func (e *Entry) Func(f func(e *Entry)) *Entry { 2049 if e != nil { 2050 f(e) 2051 } 2052 return e 2053 } 2054 2055 // EmbedObject marshals and Embeds an object that implement the ObjectMarshaler interface. 2056 func (e *Entry) EmbedObject(obj ObjectMarshaler) *Entry { 2057 if e == nil { 2058 return nil 2059 } 2060 2061 if obj != nil && (*[2]uintptr)(unsafe.Pointer(&obj))[1] != 0 { 2062 obj.MarshalObject(e) 2063 } 2064 return e 2065 } 2066 2067 func (e *Entry) Map(data any) *Entry { 2068 switch data := data.(type) { 2069 case map[string]any: 2070 for key, value := range data { 2071 e.Any(key, value) 2072 } 2073 default: 2074 if reflect.ValueOf(data).Kind() == reflect.Struct { 2075 var mp map[string]any 2076 bt, err := json.Marshal(data) 2077 if err != nil { 2078 err = json.Unmarshal(bt, &mp) 2079 for key, value := range mp { 2080 e.Any(key, value) 2081 } 2082 } 2083 2084 } 2085 } 2086 return e 2087 } 2088 2089 // Any adds the field key with f as an Any value to the entry. 2090 func (e *Entry) Any(key string, value interface{}) *Entry { 2091 if value == nil || (*[2]uintptr)(unsafe.Pointer(&value))[1] == 0 { 2092 e.buf = append(e.buf, ',', '"') 2093 e.buf = append(e.buf, key...) 2094 e.buf = append(e.buf, '"', ':') 2095 e.buf = append(e.buf, "null"...) 2096 return e 2097 } 2098 switch value := value.(type) { 2099 case ObjectMarshaler: 2100 e.buf = append(e.buf, ',', '"') 2101 e.buf = append(e.buf, key...) 2102 e.buf = append(e.buf, '"', ':') 2103 value.MarshalObject(e) 2104 case Context: 2105 e.Dict(key, value) 2106 case map[string]any: 2107 e.Map(value) 2108 case []time.Duration: 2109 e.Durs(key, value) 2110 case time.Duration: 2111 e.Dur(key, value) 2112 case time.Time: 2113 e.Time(key, value) 2114 case net.HardwareAddr: 2115 e.MACAddr(key, value) 2116 case net.IP: 2117 e.IPAddr(key, value) 2118 case net.IPNet: 2119 e.IPPrefix(key, value) 2120 case json.RawMessage: 2121 e.buf = append(e.buf, ',', '"') 2122 e.buf = append(e.buf, key...) 2123 e.buf = append(e.buf, '"', ':') 2124 e.buf = append(e.buf, value...) 2125 case []bool: 2126 e.Bools(key, value) 2127 case []byte: 2128 e.Bytes(key, value) 2129 case []error: 2130 e.Errs(key, value) 2131 case []float32: 2132 e.Floats32(key, value) 2133 case []float64: 2134 e.Floats64(key, value) 2135 case []string: 2136 e.Strs(key, value) 2137 case string: 2138 e.Str(key, value) 2139 case bool: 2140 e.Bool(key, value) 2141 case error: 2142 e.AnErr(key, value) 2143 case float32: 2144 e.Float32(key, value) 2145 case float64: 2146 e.Float64(key, value) 2147 case int16: 2148 e.Int16(key, value) 2149 case int32: 2150 e.Int32(key, value) 2151 case int64: 2152 e.Int64(key, value) 2153 case int8: 2154 e.Int8(key, value) 2155 case int: 2156 e.Int(key, value) 2157 case uint16: 2158 e.Uint16(key, value) 2159 case uint32: 2160 e.Uint32(key, value) 2161 case uint64: 2162 e.Uint64(key, value) 2163 case uint8: 2164 e.Uint8(key, value) 2165 case fmt.GoStringer: 2166 e.GoStringer(key, value) 2167 case fmt.Stringer: 2168 e.Stringer(key, value) 2169 default: 2170 e.buf = append(e.buf, ',', '"') 2171 e.buf = append(e.buf, key...) 2172 e.buf = append(e.buf, '"', ':') 2173 b := bbpool.Get().(*bb) 2174 b.B = b.B[:0] 2175 enc := json.NewEncoder(b) 2176 enc.SetEscapeHTML(false) 2177 err := enc.Encode(value) 2178 if err != nil { 2179 b.B = b.B[:0] 2180 fmt.Fprintf(b, `marshaling error: %+v`, err) 2181 e.buf = append(e.buf, '"') 2182 e.bytes(b.B) 2183 e.buf = append(e.buf, '"') 2184 } else { 2185 b.B = b.B[:len(b.B)-1] 2186 e.buf = append(e.buf, b.B...) 2187 } 2188 if cap(b.B) <= bbcap { 2189 bbpool.Put(b) 2190 } 2191 } 2192 return e 2193 } 2194 2195 // KeysAndValues sends keysAndValues to Entry 2196 func (e *Entry) KeysAndValues(keysAndValues ...interface{}) *Entry { 2197 if e == nil { 2198 return nil 2199 } 2200 var key string 2201 for i, v := range keysAndValues { 2202 if i%2 == 0 { 2203 key, _ = v.(string) 2204 continue 2205 } 2206 e.Any(key, v) 2207 } 2208 return e 2209 } 2210 2211 // Fields type, used to pass to `Fields`. 2212 type Fields map[string]interface{} 2213 2214 // Fields is a helper function to use a map to set fields using type assertion. 2215 func (e *Entry) Fields(fields Fields) *Entry { 2216 if e == nil { 2217 return nil 2218 } 2219 for key, value := range fields { 2220 e.Any(key, value) 2221 } 2222 return e 2223 } 2224 2225 // Context represents contextual fields. 2226 type Context []byte 2227 2228 // NewContext starts a new contextual entry. 2229 func NewContext(dst []byte) (e *Entry) { 2230 e = new(Entry) 2231 e.buf = dst 2232 return 2233 } 2234 2235 func With(logr *Logger) (e *Entry) { 2236 e = new(Entry) 2237 e.buf = logr.Context 2238 e.logger = logr 2239 return 2240 } 2241 2242 // Value builds the contextual fields. 2243 func (e *Entry) Value() Context { 2244 if e == nil { 2245 return nil 2246 } 2247 return e.buf 2248 } 2249 2250 // Context sends the contextual fields to entry. 2251 func (e *Entry) Context(ctx Context) *Entry { 2252 if e == nil { 2253 return nil 2254 } 2255 if len(ctx) != 0 { 2256 e.buf = append(e.buf, ctx...) 2257 } 2258 return e 2259 } 2260 2261 // Dict sends the contextual fields with key to entry. 2262 func (e *Entry) Dict(key string, ctx Context) *Entry { 2263 if e == nil { 2264 return nil 2265 } 2266 e.buf = append(e.buf, ',', '"') 2267 e.buf = append(e.buf, key...) 2268 e.buf = append(e.buf, '"', ':', '{') 2269 if len(ctx) > 0 { 2270 e.buf = append(e.buf, ctx[1:]...) 2271 } 2272 e.buf = append(e.buf, '}') 2273 return e 2274 } 2275 2276 // stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines. 2277 func stacks(all bool) (trace []byte) { 2278 // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though. 2279 n := 10000 2280 if all { 2281 n = 100000 2282 } 2283 for i := 0; i < 5; i++ { 2284 trace = make([]byte, n) 2285 nbytes := runtime.Stack(trace, all) 2286 if nbytes < len(trace) { 2287 trace = trace[:nbytes] 2288 break 2289 } 2290 n *= 2 2291 } 2292 return 2293 } 2294 2295 // wlprintf is a helper function for tests 2296 func wlprintf(w Writer, level Level, format string, args ...interface{}) (int, error) { 2297 return w.WriteEntry(&Entry{ 2298 Level: level, 2299 buf: []byte(fmt.Sprintf(format, args...)), 2300 }) 2301 } 2302 2303 func b2s(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } 2304 2305 //go:noescape 2306 //go:linkname now time.now 2307 func now() (sec int64, nsec int32, mono int64) 2308 2309 //go:noescape 2310 //go:linkname absDate time.absDate 2311 func absDate(abs uint64, full bool) (year int, month time.Month, day int, yday int) 2312 2313 //go:noescape 2314 //go:linkname absClock time.absClock 2315 func absClock(abs uint64) (hour, min, sec int) 2316 2317 //go:noescape 2318 //go:linkname caller1 runtime.callers 2319 func caller1(skip int, pc *uintptr, len, cap int) int