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