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