github.com/qiniu/x@v1.11.9/log/logext.go (about) 1 package log 2 3 import ( 4 "bytes" 5 "fmt" 6 "io" 7 "os" 8 "runtime" 9 "strings" 10 "sync" 11 "time" 12 ) 13 14 // These flags define which text to prefix to each log entry generated by the Logger. 15 const ( 16 // Bits or'ed together to control what's printed. There is no control over the 17 // order they appear (the order listed here) or the format they present (as 18 // described in the comments). A colon appears after these items: 19 // 2009/0123 01:23:23.123123 /a/b/c/d.go:23: message 20 Ldate = 1 << iota // the date: 2009/0123 21 Ltime // the time: 01:23:23 22 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. 23 Llongfile // full file name and line number: /a/b/c/d.go:23 24 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile 25 Lmodule // module name 26 Llevel // level: 0(Debug), 1(Info), 2(Warn), 3(Error), 4(Panic), 5(Fatal) 27 LstdFlags = Ldate | Ltime | Lmicroseconds // initial values for the standard logger 28 Ldefault = Lmodule | Llevel | Lshortfile | LstdFlags 29 ) // [prefix][time][level][module][shortfile|longfile] 30 31 const ( 32 // Ldebug is a log output level that prints debug information. 33 Ldebug = iota 34 // Linfo is a log output level that prints prompting information. 35 Linfo 36 // Lwarn is a log output level that prints warning information. 37 Lwarn 38 // Lerror is a log output level that prints error information. 39 Lerror 40 // Lpanic is a log output level that prints error information. 41 Lpanic 42 // Lfatal is a log output level that prints fatal information. 43 Lfatal 44 ) 45 46 var levels = []string{ 47 "[DEBUG]", 48 "[INFO]", 49 "[WARN]", 50 "[ERROR]", 51 "[PANIC]", 52 "[FATAL]", 53 } 54 55 // A Logger represents an active logging object that generates lines of 56 // output to an io.Writer. Each logging operation makes a single call to 57 // the Writer's Write method. A Logger can be used simultaneously from 58 // multiple goroutines; it guarantees to serialize access to the Writer. 59 type Logger struct { 60 mu sync.Mutex // ensures atomic writes; protects the following fields 61 prefix string // prefix to write at beginning of each line 62 flag int // properties 63 Level int // debug level 64 out io.Writer // destination for output 65 buf bytes.Buffer // for accumulating text to write 66 levelStats [6]int64 67 } 68 69 // New creates a new Logger. 70 // The out variable sets the destination to which log data will be written. 71 // The prefix appears at the beginning of each generated log line. 72 // The flag argument defines the logging properties. 73 func New(out io.Writer, prefix string, flag int) *Logger { 74 return &Logger{out: out, prefix: prefix, Level: 1, flag: flag} 75 } 76 77 // Std *Logger. 78 var Std = New(os.Stderr, "", Ldefault) 79 80 // Cheap integer to fixed-width decimal ASCII. Give a negative width to avoid zero-padding. 81 // Knows the buffer has capacity. 82 func itoa(buf *bytes.Buffer, i int, wid int) { 83 var u uint = uint(i) 84 if u == 0 && wid <= 1 { 85 buf.WriteByte('0') 86 return 87 } 88 89 // Assemble decimal in reverse order. 90 var b [32]byte 91 bp := len(b) 92 for ; u > 0 || wid > 0; u /= 10 { 93 bp-- 94 wid-- 95 b[bp] = byte(u%10) + '0' 96 } 97 98 // avoid slicing b to avoid an allocation. 99 for bp < len(b) { 100 buf.WriteByte(b[bp]) 101 bp++ 102 } 103 } 104 105 func shortFile(file string, flag int) string { 106 sep := "/" 107 if (flag & Lmodule) != 0 { 108 sep = "/src/" 109 } 110 pos := strings.LastIndex(file, sep) 111 if pos != -1 { 112 return file[pos+5:] 113 } 114 return file 115 } 116 117 func (l *Logger) formatHeader(buf *bytes.Buffer, t time.Time, file string, line int, lvl int, reqID string) { 118 if l.prefix != "" { 119 buf.WriteString(l.prefix) 120 } 121 flag := l.flag 122 if flag&(Ldate|Ltime|Lmicroseconds) != 0 { 123 if flag&Ldate != 0 { 124 year, month, day := t.Date() 125 itoa(buf, year, 4) 126 buf.WriteByte('/') 127 itoa(buf, int(month), 2) 128 buf.WriteByte('/') 129 itoa(buf, day, 2) 130 buf.WriteByte(' ') 131 } 132 if flag&(Ltime|Lmicroseconds) != 0 { 133 hour, min, sec := t.Clock() 134 itoa(buf, hour, 2) 135 buf.WriteByte(':') 136 itoa(buf, min, 2) 137 buf.WriteByte(':') 138 itoa(buf, sec, 2) 139 if flag&Lmicroseconds != 0 { 140 buf.WriteByte('.') 141 itoa(buf, t.Nanosecond()/1e3, 6) 142 } 143 buf.WriteByte(' ') 144 } 145 } 146 if reqID != "" { 147 buf.WriteByte('[') 148 buf.WriteString(reqID) 149 buf.WriteByte(']') 150 } 151 if flag&Llevel != 0 { 152 buf.WriteString(levels[lvl]) 153 } 154 if flag&(Lshortfile|Llongfile) != 0 { 155 if flag&Lshortfile != 0 { 156 file = shortFile(file, flag) 157 } 158 buf.WriteByte(' ') 159 buf.WriteString(file) 160 buf.WriteByte(':') 161 itoa(buf, line, -1) 162 buf.WriteString(": ") 163 } else if flag&Llevel != 0 { 164 buf.WriteByte(' ') 165 } 166 } 167 168 // Output writes the output for a logging event. The string s contains 169 // the text to print after the prefix specified by the flags of the 170 // Logger. A newline is appended if the last character of s is not 171 // already a newline. Calldepth is used to recover the PC and is 172 // provided for generality, although at the moment on all pre-defined 173 // paths it will be 2. 174 func (l *Logger) Output(reqID string, lvl int, calldepth int, s string) error { 175 if lvl < l.Level { 176 return nil 177 } 178 now := time.Now() // get this early. 179 var file string 180 var line int 181 l.mu.Lock() 182 defer l.mu.Unlock() 183 if l.flag&(Lshortfile|Llongfile|Lmodule) != 0 { 184 // release lock while getting caller info - it's expensive. 185 l.mu.Unlock() 186 var ok bool 187 _, file, line, ok = runtime.Caller(calldepth) 188 if !ok { 189 file = "???" 190 line = 0 191 } 192 l.mu.Lock() 193 } 194 l.levelStats[lvl]++ 195 l.buf.Reset() 196 l.formatHeader(&l.buf, now, file, line, lvl, reqID) 197 l.buf.WriteString(s) 198 if len(s) > 0 && s[len(s)-1] != '\n' { 199 l.buf.WriteByte('\n') 200 } 201 _, err := l.out.Write(l.buf.Bytes()) 202 return err 203 } 204 205 // ----------------------------------------- 206 207 // Printf calls l.Output to print to the logger. 208 // Arguments are handled in the manner of fmt.Printf. 209 func (l *Logger) Printf(format string, v ...interface{}) { 210 l.Output("", Linfo, 2, fmt.Sprintf(format, v...)) 211 } 212 213 // Print calls l.Output to print to the logger. 214 // Arguments are handled in the manner of fmt.Print. 215 func (l *Logger) Print(v ...interface{}) { l.Output("", Linfo, 2, fmt.Sprint(v...)) } 216 217 // Println calls l.Output to print to the logger. 218 // Arguments are handled in the manner of fmt.Println. 219 func (l *Logger) Println(v ...interface{}) { l.Output("", Linfo, 2, fmt.Sprintln(v...)) } 220 221 // ----------------------------------------- 222 223 // Debugf prints a debug information. 224 func (l *Logger) Debugf(format string, v ...interface{}) { 225 if Ldebug < l.Level { 226 return 227 } 228 l.Output("", Ldebug, 2, fmt.Sprintf(format, v...)) 229 } 230 231 // Debug prints a debug information. 232 func (l *Logger) Debug(v ...interface{}) { 233 if Ldebug < l.Level { 234 return 235 } 236 l.Output("", Ldebug, 2, fmt.Sprintln(v...)) 237 } 238 239 // ----------------------------------------- 240 241 // Infof prints a prompting information. 242 func (l *Logger) Infof(format string, v ...interface{}) { 243 if Linfo < l.Level { 244 return 245 } 246 l.Output("", Linfo, 2, fmt.Sprintf(format, v...)) 247 } 248 249 // Info prints a prompting information. 250 func (l *Logger) Info(v ...interface{}) { 251 if Linfo < l.Level { 252 return 253 } 254 l.Output("", Linfo, 2, fmt.Sprintln(v...)) 255 } 256 257 // ----------------------------------------- 258 259 // Warnf prints a warning information. 260 func (l *Logger) Warnf(format string, v ...interface{}) { 261 l.Output("", Lwarn, 2, fmt.Sprintf(format, v...)) 262 } 263 264 // Warn prints a warning information. 265 func (l *Logger) Warn(v ...interface{}) { l.Output("", Lwarn, 2, fmt.Sprintln(v...)) } 266 267 // ----------------------------------------- 268 269 // Errorf prints an error information. 270 func (l *Logger) Errorf(format string, v ...interface{}) { 271 l.Output("", Lerror, 2, fmt.Sprintf(format, v...)) 272 } 273 274 // Error prints an error information. 275 func (l *Logger) Error(v ...interface{}) { l.Output("", Lerror, 2, fmt.Sprintln(v...)) } 276 277 // ----------------------------------------- 278 279 // Fatal prints an error information and exit app. 280 func (l *Logger) Fatal(v ...interface{}) { 281 l.Output("", Lfatal, 2, fmt.Sprint(v...)) 282 os.Exit(1) 283 } 284 285 // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1). 286 func (l *Logger) Fatalf(format string, v ...interface{}) { 287 l.Output("", Lfatal, 2, fmt.Sprintf(format, v...)) 288 os.Exit(1) 289 } 290 291 // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). 292 func (l *Logger) Fatalln(v ...interface{}) { 293 l.Output("", Lfatal, 2, fmt.Sprintln(v...)) 294 os.Exit(1) 295 } 296 297 // ----------------------------------------- 298 299 // Panic is equivalent to l.Print() followed by a call to panic(). 300 func (l *Logger) Panic(v ...interface{}) { 301 s := fmt.Sprint(v...) 302 l.Output("", Lpanic, 2, s) 303 panic(s) 304 } 305 306 // Panicf is equivalent to l.Printf() followed by a call to panic(). 307 func (l *Logger) Panicf(format string, v ...interface{}) { 308 s := fmt.Sprintf(format, v...) 309 l.Output("", Lpanic, 2, s) 310 panic(s) 311 } 312 313 // Panicln is equivalent to l.Println() followed by a call to panic(). 314 func (l *Logger) Panicln(v ...interface{}) { 315 s := fmt.Sprintln(v...) 316 l.Output("", Lpanic, 2, s) 317 panic(s) 318 } 319 320 // ----------------------------------------- 321 322 // Stack prints a stack trace of all goroutines. 323 func (l *Logger) Stack(v ...interface{}) { 324 s := fmt.Sprint(v...) 325 s += "\n" 326 buf := make([]byte, 1024*1024) 327 n := runtime.Stack(buf, true) 328 s += string(buf[:n]) 329 s += "\n" 330 l.Output("", Lerror, 2, s) 331 } 332 333 // SingleStack prints a stack trace of the calling goroutines. 334 func (l *Logger) SingleStack(v ...interface{}) { 335 s := fmt.Sprint(v...) 336 s += "\n" 337 buf := make([]byte, 1024*1024) 338 n := runtime.Stack(buf, false) 339 s += string(buf[:n]) 340 s += "\n" 341 l.Output("", Lerror, 2, s) 342 } 343 344 // ----------------------------------------- 345 346 // Stat func. 347 func (l *Logger) Stat() (stats []int64) { 348 l.mu.Lock() 349 v := l.levelStats 350 l.mu.Unlock() 351 return v[:] 352 } 353 354 // Flags returns the output flags for the logger. 355 func (l *Logger) Flags() int { 356 l.mu.Lock() 357 defer l.mu.Unlock() 358 return l.flag 359 } 360 361 // SetFlags sets the output flags for the logger. 362 func (l *Logger) SetFlags(flag int) { 363 l.mu.Lock() 364 defer l.mu.Unlock() 365 l.flag = flag 366 } 367 368 // Prefix returns the output prefix for the logger. 369 func (l *Logger) Prefix() string { 370 l.mu.Lock() 371 defer l.mu.Unlock() 372 return l.prefix 373 } 374 375 // SetPrefix sets the output prefix for the logger. 376 func (l *Logger) SetPrefix(prefix string) { 377 l.mu.Lock() 378 defer l.mu.Unlock() 379 l.prefix = prefix 380 } 381 382 // SetOutputLevel sets the output level for the logger. 383 func (l *Logger) SetOutputLevel(lvl int) { 384 l.mu.Lock() 385 defer l.mu.Unlock() 386 l.Level = lvl 387 } 388 389 // SetOutput sets the output destination for the standard logger. 390 func SetOutput(w io.Writer) { 391 Std.mu.Lock() 392 defer Std.mu.Unlock() 393 Std.out = w 394 } 395 396 // Flags returns the output flags for the standard logger. 397 func Flags() int { 398 return Std.Flags() 399 } 400 401 // SetFlags sets the output flags for the standard logger. 402 func SetFlags(flag int) { 403 Std.SetFlags(flag) 404 } 405 406 // Prefix returns the output prefix for the standard logger. 407 func Prefix() string { 408 return Std.Prefix() 409 } 410 411 // SetPrefix sets the output prefix for the standard logger. 412 func SetPrefix(prefix string) { 413 Std.SetPrefix(prefix) 414 } 415 416 // SetOutputLevel sets output level. 417 func SetOutputLevel(lvl int) { 418 Std.SetOutputLevel(lvl) 419 } 420 421 // GetOutputLevel returns output level. 422 func GetOutputLevel() int { 423 return Std.Level 424 } 425 426 // CanOutput returns to output a message or not. 427 func CanOutput(lvl int) bool { 428 return lvl >= Std.Level 429 } 430 431 // ----------------------------------------- 432 433 // Print calls Output to print to the standard logger. 434 // Arguments are handled in the manner of fmt.Print. 435 func Print(v ...interface{}) { 436 Std.Output("", Linfo, 2, fmt.Sprint(v...)) 437 } 438 439 // Printf calls Output to print to the standard logger. 440 // Arguments are handled in the manner of fmt.Printf. 441 func Printf(format string, v ...interface{}) { 442 Std.Output("", Linfo, 2, fmt.Sprintf(format, v...)) 443 } 444 445 // Println calls Output to print to the standard logger. 446 // Arguments are handled in the manner of fmt.Println. 447 func Println(v ...interface{}) { 448 Std.Output("", Linfo, 2, fmt.Sprintln(v...)) 449 } 450 451 // ----------------------------------------- 452 453 // Debugf prints a debug information. 454 func Debugf(format string, v ...interface{}) { 455 if Ldebug < Std.Level { 456 return 457 } 458 Std.Output("", Ldebug, 2, fmt.Sprintf(format, v...)) 459 } 460 461 // Debug prints a debug information. 462 func Debug(v ...interface{}) { 463 if Ldebug < Std.Level { 464 return 465 } 466 Std.Output("", Ldebug, 2, fmt.Sprintln(v...)) 467 } 468 469 // ----------------------------------------- 470 471 // Infof prints a prompting information. 472 func Infof(format string, v ...interface{}) { 473 if Linfo < Std.Level { 474 return 475 } 476 Std.Output("", Linfo, 2, fmt.Sprintf(format, v...)) 477 } 478 479 // Info prints a prompting information. 480 func Info(v ...interface{}) { 481 if Linfo < Std.Level { 482 return 483 } 484 Std.Output("", Linfo, 2, fmt.Sprintln(v...)) 485 } 486 487 // ----------------------------------------- 488 489 // Warnf prints a warning information. 490 func Warnf(format string, v ...interface{}) { 491 Std.Output("", Lwarn, 2, fmt.Sprintf(format, v...)) 492 } 493 494 // Warn prints a warning information. 495 func Warn(v ...interface{}) { Std.Output("", Lwarn, 2, fmt.Sprintln(v...)) } 496 497 // ----------------------------------------- 498 499 // Errorf prints an error information. 500 func Errorf(format string, v ...interface{}) { 501 Std.Output("", Lerror, 2, fmt.Sprintf(format, v...)) 502 } 503 504 // Error prints an error information. 505 func Error(v ...interface{}) { Std.Output("", Lerror, 2, fmt.Sprintln(v...)) } 506 507 // ----------------------------------------- 508 509 // Fatal is equivalent to Print() followed by a call to os.Exit(1). 510 func Fatal(v ...interface{}) { 511 Std.Output("", Lfatal, 2, fmt.Sprint(v...)) 512 os.Exit(1) 513 } 514 515 // Fatalf is equivalent to Printf() followed by a call to os.Exit(1). 516 func Fatalf(format string, v ...interface{}) { 517 Std.Output("", Lfatal, 2, fmt.Sprintf(format, v...)) 518 os.Exit(1) 519 } 520 521 // Fatalln is equivalent to Println() followed by a call to os.Exit(1). 522 func Fatalln(v ...interface{}) { 523 Std.Output("", Lfatal, 2, fmt.Sprintln(v...)) 524 os.Exit(1) 525 } 526 527 // ----------------------------------------- 528 529 // Panic is equivalent to Print() followed by a call to panic(). 530 func Panic(v ...interface{}) { 531 s := fmt.Sprint(v...) 532 Std.Output("", Lpanic, 2, s) 533 panic(s) 534 } 535 536 // Panicf is equivalent to Printf() followed by a call to panic(). 537 func Panicf(format string, v ...interface{}) { 538 s := fmt.Sprintf(format, v...) 539 Std.Output("", Lpanic, 2, s) 540 panic(s) 541 } 542 543 // Panicln is equivalent to Println() followed by a call to panic(). 544 func Panicln(v ...interface{}) { 545 s := fmt.Sprintln(v...) 546 Std.Output("", Lpanic, 2, s) 547 panic(s) 548 } 549 550 // ----------------------------------------- 551 552 // Stack prints a stack trace of all goroutines. 553 func Stack(v ...interface{}) { 554 Std.Stack(v...) 555 } 556 557 // SingleStack prints a stack trace of the calling goroutines. 558 func SingleStack(v ...interface{}) { 559 Std.SingleStack(v...) 560 }