github.com/digdeepmining/go-atheios@v1.5.13-0.20180902133602-d5687a2e6f43/logger/glog/glog.go (about) 1 // Go support for leveled logs, analogous to https://code.google.com/p/google-glog/ 2 // 3 // Copyright 2013 Google Inc. All Rights Reserved. 4 // 5 // Licensed under the Apache License, Version 2.0 (the "License"); 6 // you may not use this file except in compliance with the License. 7 // You may obtain a copy of the License at 8 // 9 // http://www.apache.org/licenses/LICENSE-2.0 10 // 11 // Unless required by applicable law or agreed to in writing, software 12 // distributed under the License is distributed on an "AS IS" BASIS, 13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 // See the License for the specific language governing permissions and 15 // limitations under the License. 16 17 // Package glog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup. 18 // It provides functions Info, Warning, Error, Fatal, plus formatting variants such as 19 // Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags. 20 // 21 // Basic examples: 22 // 23 // glog.Info("Prepare to repel boarders") 24 // 25 // glog.Fatalf("Initialization failed: %s", err) 26 // 27 // See the documentation for the V function for an explanation of these examples: 28 // 29 // if glog.V(2) { 30 // glog.Info("Starting transaction...") 31 // } 32 // 33 // glog.V(2).Infoln("Processed", nItems, "elements") 34 // 35 // Log output is buffered and written periodically using Flush. Programs 36 // should call Flush before exiting to guarantee all log output is written. 37 // 38 // By default, all log statements write to files in a temporary directory. 39 // This package provides several flags that modify this behavior. 40 // As a result, flag.Parse must be called before any logging is done. 41 // 42 // -logtostderr=false 43 // Logs are written to standard error instead of to files. 44 // -alsologtostderr=false 45 // Logs are written to standard error as well as to files. 46 // -stderrthreshold=ERROR 47 // Log events at or above this severity are logged to standard 48 // error as well as to files. 49 // -log_dir="" 50 // Log files will be written to this directory instead of the 51 // default temporary directory. 52 // 53 // Other flags provide aids to debugging. 54 // 55 // -log_backtrace_at="" 56 // When set to a file and line number holding a logging statement, 57 // such as 58 // -log_backtrace_at=gopherflakes.go:234 59 // a stack trace will be written to the Info log whenever execution 60 // hits that statement. (Unlike with -vmodule, the ".go" must be 61 // present.) 62 // -v=0 63 // Enable V-leveled logging at the specified level. 64 // -vmodule="" 65 // The syntax of the argument is a comma-separated list of pattern=N, 66 // where pattern is a literal file name or "glob" pattern matching 67 // and N is a V level. For instance, 68 // 69 // -vmodule=gopher.go=3 70 // sets the V level to 3 in all Go files named "gopher.go". 71 // 72 // -vmodule=foo=3 73 // sets V to 3 in all files of any packages whose import path ends in "foo". 74 // 75 // -vmodule=foo/*=3 76 // sets V to 3 in all files of any packages whose import path contains "foo". 77 package glog 78 79 import ( 80 "bufio" 81 "bytes" 82 "errors" 83 "fmt" 84 "io" 85 stdLog "log" 86 "os" 87 "regexp" 88 "runtime" 89 "strconv" 90 "strings" 91 "sync" 92 "sync/atomic" 93 "time" 94 ) 95 96 // severity identifies the sort of log: info, warning etc. It also implements 97 // the flag.Value interface. The -stderrthreshold flag is of type severity and 98 // should be modified only through the flag.Value interface. The values match 99 // the corresponding constants in C++. 100 type severity int32 // sync/atomic int32 101 102 // These constants identify the log levels in order of increasing severity. 103 // A message written to a high-severity log file is also written to each 104 // lower-severity log file. 105 const ( 106 infoLog severity = iota 107 warningLog 108 errorLog 109 fatalLog 110 numSeverity = 4 111 ) 112 113 const severityChar = "IWEF" 114 115 var severityName = []string{ 116 infoLog: "INFO", 117 warningLog: "WARNING", 118 errorLog: "ERROR", 119 fatalLog: "FATAL", 120 } 121 122 // these path prefixes are trimmed for display, but not when 123 // matching vmodule filters. 124 var trimPrefixes = []string{ 125 "/github.com/atheioschain/go-atheios", 126 "/github.com/ethereum/ethash", 127 } 128 129 func trimToImportPath(file string) string { 130 if root := strings.LastIndex(file, "src/"); root != 0 { 131 file = file[root+3:] 132 } 133 return file 134 } 135 136 // SetV sets the global verbosity level 137 func SetV(v int) { 138 logging.verbosity.set(Level(v)) 139 } 140 141 // SetToStderr sets the global output style 142 func SetToStderr(toStderr bool) { 143 logging.mu.Lock() 144 logging.toStderr = toStderr 145 logging.mu.Unlock() 146 } 147 148 // GetTraceLocation returns the global TraceLocation flag. 149 func GetTraceLocation() *TraceLocation { 150 return &logging.traceLocation 151 } 152 153 // GetVModule returns the global verbosity pattern flag. 154 func GetVModule() *moduleSpec { 155 return &logging.vmodule 156 } 157 158 // GetVerbosity returns the global verbosity level flag. 159 func GetVerbosity() *Level { 160 return &logging.verbosity 161 } 162 163 // get returns the value of the severity. 164 func (s *severity) get() severity { 165 return severity(atomic.LoadInt32((*int32)(s))) 166 } 167 168 // set sets the value of the severity. 169 func (s *severity) set(val severity) { 170 atomic.StoreInt32((*int32)(s), int32(val)) 171 } 172 173 // String is part of the flag.Value interface. 174 func (s *severity) String() string { 175 return strconv.FormatInt(int64(*s), 10) 176 } 177 178 // Get is part of the flag.Value interface. 179 func (s *severity) Get() interface{} { 180 return *s 181 } 182 183 // Set is part of the flag.Value interface. 184 func (s *severity) Set(value string) error { 185 var threshold severity 186 // Is it a known name? 187 if v, ok := severityByName(value); ok { 188 threshold = v 189 } else { 190 v, err := strconv.Atoi(value) 191 if err != nil { 192 return err 193 } 194 threshold = severity(v) 195 } 196 logging.stderrThreshold.set(threshold) 197 return nil 198 } 199 200 func severityByName(s string) (severity, bool) { 201 s = strings.ToUpper(s) 202 for i, name := range severityName { 203 if name == s { 204 return severity(i), true 205 } 206 } 207 return 0, false 208 } 209 210 // OutputStats tracks the number of output lines and bytes written. 211 type OutputStats struct { 212 lines int64 213 bytes int64 214 } 215 216 // Lines returns the number of lines written. 217 func (s *OutputStats) Lines() int64 { 218 return atomic.LoadInt64(&s.lines) 219 } 220 221 // Bytes returns the number of bytes written. 222 func (s *OutputStats) Bytes() int64 { 223 return atomic.LoadInt64(&s.bytes) 224 } 225 226 // Stats tracks the number of lines of output and number of bytes 227 // per severity level. Values must be read with atomic.LoadInt64. 228 var Stats struct { 229 Info, Warning, Error OutputStats 230 } 231 232 var severityStats = [numSeverity]*OutputStats{ 233 infoLog: &Stats.Info, 234 warningLog: &Stats.Warning, 235 errorLog: &Stats.Error, 236 } 237 238 // Level is exported because it appears in the arguments to V and is 239 // the type of the v flag, which can be set programmatically. 240 // It's a distinct type because we want to discriminate it from logType. 241 // Variables of type level are only changed under logging.mu. 242 // The -v flag is read only with atomic ops, so the state of the logging 243 // module is consistent. 244 245 // Level is treated as a sync/atomic int32. 246 247 // Level specifies a level of verbosity for V logs. *Level implements 248 // flag.Value; the -v flag is of type Level and should be modified 249 // only through the flag.Value interface. 250 type Level int32 251 252 // get returns the value of the Level. 253 func (l *Level) get() Level { 254 return Level(atomic.LoadInt32((*int32)(l))) 255 } 256 257 // set sets the value of the Level. 258 func (l *Level) set(val Level) { 259 atomic.StoreInt32((*int32)(l), int32(val)) 260 } 261 262 // String is part of the flag.Value interface. 263 func (l *Level) String() string { 264 return strconv.FormatInt(int64(*l), 10) 265 } 266 267 // Get is part of the flag.Value interface. 268 func (l *Level) Get() interface{} { 269 return *l 270 } 271 272 // Set is part of the flag.Value interface. 273 func (l *Level) Set(value string) error { 274 v, err := strconv.Atoi(value) 275 if err != nil { 276 return err 277 } 278 logging.mu.Lock() 279 defer logging.mu.Unlock() 280 logging.setVState(Level(v), logging.vmodule.filter, false) 281 return nil 282 } 283 284 // moduleSpec represents the setting of the -vmodule flag. 285 type moduleSpec struct { 286 filter []modulePat 287 } 288 289 // modulePat contains a filter for the -vmodule flag. 290 // It holds a verbosity level and a file pattern to match. 291 type modulePat struct { 292 pattern *regexp.Regexp 293 level Level 294 } 295 296 func (m *moduleSpec) String() string { 297 // Lock because the type is not atomic. TODO: clean this up. 298 logging.mu.Lock() 299 defer logging.mu.Unlock() 300 var b bytes.Buffer 301 for i, f := range m.filter { 302 if i > 0 { 303 b.WriteRune(',') 304 } 305 fmt.Fprintf(&b, "%s=%d", f.pattern, f.level) 306 } 307 return b.String() 308 } 309 310 // Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the 311 // struct is not exported. 312 func (m *moduleSpec) Get() interface{} { 313 return nil 314 } 315 316 var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N") 317 318 // Syntax: -vmodule=recordio=2,file=1,gfs*=3 319 func (m *moduleSpec) Set(value string) error { 320 var filter []modulePat 321 for _, pat := range strings.Split(value, ",") { 322 if len(pat) == 0 { 323 // Empty strings such as from a trailing comma can be ignored. 324 continue 325 } 326 patLev := strings.Split(pat, "=") 327 if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { 328 return errVmoduleSyntax 329 } 330 pattern := patLev[0] 331 v, err := strconv.Atoi(patLev[1]) 332 if err != nil { 333 return errors.New("syntax error: expect comma-separated list of filename=N") 334 } 335 if v < 0 { 336 return errors.New("negative value for vmodule level") 337 } 338 if v == 0 { 339 continue // Ignore. It's harmless but no point in paying the overhead. 340 } 341 // TODO: check syntax of filter? 342 re, _ := compileModulePattern(pattern) 343 filter = append(filter, modulePat{re, Level(v)}) 344 } 345 logging.mu.Lock() 346 defer logging.mu.Unlock() 347 logging.setVState(logging.verbosity, filter, true) 348 return nil 349 } 350 351 // compiles a vmodule pattern to a regular expression. 352 func compileModulePattern(pat string) (*regexp.Regexp, error) { 353 re := ".*" 354 for _, comp := range strings.Split(pat, "/") { 355 if comp == "*" { 356 re += "(/.*)?" 357 } else if comp != "" { 358 // TODO: maybe return error if comp contains * 359 re += "/" + regexp.QuoteMeta(comp) 360 } 361 } 362 if !strings.HasSuffix(pat, ".go") { 363 re += "/[^/]+\\.go" 364 } 365 return regexp.Compile(re + "$") 366 } 367 368 // traceLocation represents the setting of the -log_backtrace_at flag. 369 type TraceLocation struct { 370 file string 371 line int 372 } 373 374 // isSet reports whether the trace location has been specified. 375 // logging.mu is held. 376 func (t *TraceLocation) isSet() bool { 377 return t.line > 0 378 } 379 380 // match reports whether the specified file and line matches the trace location. 381 // The argument file name is the full path, not the basename specified in the flag. 382 // logging.mu is held. 383 func (t *TraceLocation) match(file string, line int) bool { 384 if t.line != line { 385 return false 386 } 387 if i := strings.LastIndex(file, "/"); i >= 0 { 388 file = file[i+1:] 389 } 390 return t.file == file 391 } 392 393 func (t *TraceLocation) String() string { 394 // Lock because the type is not atomic. TODO: clean this up. 395 logging.mu.Lock() 396 defer logging.mu.Unlock() 397 return fmt.Sprintf("%s:%d", t.file, t.line) 398 } 399 400 // Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the 401 // struct is not exported 402 func (t *TraceLocation) Get() interface{} { 403 return nil 404 } 405 406 var errTraceSyntax = errors.New("syntax error: expect file.go:234") 407 408 // Syntax: -log_backtrace_at=gopherflakes.go:234 409 // Note that unlike vmodule the file extension is included here. 410 func (t *TraceLocation) Set(value string) error { 411 if value == "" { 412 // Unset. 413 logging.mu.Lock() 414 t.line = 0 415 t.file = "" 416 logging.mu.Unlock() 417 return nil 418 } 419 420 fields := strings.Split(value, ":") 421 if len(fields) != 2 { 422 return errTraceSyntax 423 } 424 file, line := fields[0], fields[1] 425 if !strings.Contains(file, ".") { 426 return errTraceSyntax 427 } 428 v, err := strconv.Atoi(line) 429 if err != nil { 430 return errTraceSyntax 431 } 432 if v <= 0 { 433 return errors.New("negative or zero value for level") 434 } 435 logging.mu.Lock() 436 defer logging.mu.Unlock() 437 t.line = v 438 t.file = file 439 return nil 440 } 441 442 // flushSyncWriter is the interface satisfied by logging destinations. 443 type flushSyncWriter interface { 444 Flush() error 445 Sync() error 446 io.Writer 447 } 448 449 func init() { 450 //flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files") 451 //flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files") 452 //flag.Var(&logging.verbosity, "v", "log level for V logs") 453 //flag.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") 454 //flag.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") 455 //flag.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") 456 457 // Default stderrThreshold is ERROR. 458 logging.stderrThreshold = errorLog 459 logging.setVState(3, nil, false) 460 go logging.flushDaemon() 461 } 462 463 // Flush flushes all pending log I/O. 464 func Flush() { 465 logging.lockAndFlushAll() 466 } 467 468 // loggingT collects all the global state of the logging setup. 469 type loggingT struct { 470 // Boolean flags. Not handled atomically because the flag.Value interface 471 // does not let us avoid the =true, and that shorthand is necessary for 472 // compatibility. TODO: does this matter enough to fix? Seems unlikely. 473 toStderr bool // The -logtostderr flag. 474 alsoToStderr bool // The -alsologtostderr flag. 475 476 // Level flag. Handled atomically. 477 stderrThreshold severity // The -stderrthreshold flag. 478 479 // freeList is a list of byte buffers, maintained under freeListMu. 480 freeList *buffer 481 // freeListMu maintains the free list. It is separate from the main mutex 482 // so buffers can be grabbed and printed to without holding the main lock, 483 // for better parallelization. 484 freeListMu sync.Mutex 485 486 // mu protects the remaining elements of this structure and is 487 // used to synchronize logging. 488 mu sync.Mutex 489 // file holds writer for each of the log types. 490 file [numSeverity]flushSyncWriter 491 // pcs is used in V to avoid an allocation when computing the caller's PC. 492 pcs [1]uintptr 493 // vmap is a cache of the V Level for each V() call site, identified by PC. 494 // It is wiped whenever the vmodule flag changes state. 495 vmap map[uintptr]Level 496 // filterLength stores the length of the vmodule filter chain. If greater 497 // than zero, it means vmodule is enabled. It may be read safely 498 // using sync.LoadInt32, but is only modified under mu. 499 filterLength int32 500 // traceLocation is the state of the -log_backtrace_at flag. 501 traceLocation TraceLocation 502 // These flags are modified only under lock, although verbosity may be fetched 503 // safely using atomic.LoadInt32. 504 vmodule moduleSpec // The state of the -vmodule flag. 505 verbosity Level // V logging level, the value of the -v flag/ 506 } 507 508 // buffer holds a byte Buffer for reuse. The zero value is ready for use. 509 type buffer struct { 510 bytes.Buffer 511 tmp [64]byte // temporary byte array for creating headers. 512 next *buffer 513 } 514 515 var logging loggingT 516 517 // setVState sets a consistent state for V logging. 518 // l.mu is held. 519 func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) { 520 // Turn verbosity off so V will not fire while we are in transition. 521 logging.verbosity.set(0) 522 // Ditto for filter length. 523 atomic.StoreInt32(&logging.filterLength, 0) 524 525 // Set the new filters and wipe the pc->Level map if the filter has changed. 526 if setFilter { 527 logging.vmodule.filter = filter 528 logging.vmap = make(map[uintptr]Level) 529 } 530 531 // Things are consistent now, so enable filtering and verbosity. 532 // They are enabled in order opposite to that in V. 533 atomic.StoreInt32(&logging.filterLength, int32(len(filter))) 534 logging.verbosity.set(verbosity) 535 } 536 537 // getBuffer returns a new, ready-to-use buffer. 538 func (l *loggingT) getBuffer() *buffer { 539 l.freeListMu.Lock() 540 b := l.freeList 541 if b != nil { 542 l.freeList = b.next 543 } 544 l.freeListMu.Unlock() 545 if b == nil { 546 b = new(buffer) 547 } else { 548 b.next = nil 549 b.Reset() 550 } 551 return b 552 } 553 554 // putBuffer returns a buffer to the free list. 555 func (l *loggingT) putBuffer(b *buffer) { 556 if b.Len() >= 256 { 557 // Let big buffers die a natural death. 558 return 559 } 560 l.freeListMu.Lock() 561 b.next = l.freeList 562 l.freeList = b 563 l.freeListMu.Unlock() 564 } 565 566 var timeNow = time.Now // Stubbed out for testing. 567 568 /* 569 header formats a log header as defined by the C++ implementation. 570 It returns a buffer containing the formatted header and the user's file and line number. 571 The depth specifies how many stack frames above lives the source line to be identified in the log message. 572 573 Log lines have this form: 574 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... 575 where the fields are defined as follows: 576 L A single character, representing the log level (eg 'I' for INFO) 577 mm The month (zero padded; ie May is '05') 578 dd The day (zero padded) 579 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 580 threadid The space-padded thread ID as returned by GetTID() 581 file The file name 582 line The line number 583 msg The user-supplied message 584 */ 585 func (l *loggingT) header(s severity, depth int) (*buffer, string, int) { 586 _, file, line, ok := runtime.Caller(3 + depth) 587 if !ok { 588 file = "???" 589 line = 1 590 } else { 591 file = trimToImportPath(file) 592 for _, p := range trimPrefixes { 593 if strings.HasPrefix(file, p) { 594 file = file[len(p):] 595 break 596 } 597 } 598 file = file[1:] // drop '/' 599 } 600 return l.formatHeader(s, file, line), file, line 601 } 602 603 // formatHeader formats a log header using the provided file name and line number. 604 func (l *loggingT) formatHeader(s severity, file string, line int) *buffer { 605 now := timeNow() 606 if line < 0 { 607 line = 0 // not a real line number, but acceptable to someDigits 608 } 609 if s > fatalLog { 610 s = infoLog // for safety. 611 } 612 buf := l.getBuffer() 613 614 // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand. 615 // It's worth about 3X. Fprintf is hard. 616 _, month, day := now.Date() 617 hour, minute, second := now.Clock() 618 // Lmmdd hh:mm:ss.uuuuuu threadid file:line] 619 buf.tmp[0] = severityChar[s] 620 buf.twoDigits(1, int(month)) 621 buf.twoDigits(3, day) 622 buf.tmp[5] = ' ' 623 buf.twoDigits(6, hour) 624 buf.tmp[8] = ':' 625 buf.twoDigits(9, minute) 626 buf.tmp[11] = ':' 627 buf.twoDigits(12, second) 628 buf.tmp[14] = '.' 629 buf.nDigits(6, 15, now.Nanosecond()/1000, '0') 630 buf.tmp[21] = ' ' 631 buf.Write(buf.tmp[:22]) 632 buf.WriteString(file) 633 buf.tmp[0] = ':' 634 n := buf.someDigits(1, line) 635 buf.tmp[n+1] = ']' 636 buf.tmp[n+2] = ' ' 637 buf.Write(buf.tmp[:n+3]) 638 return buf 639 } 640 641 // Some custom tiny helper functions to print the log header efficiently. 642 643 const digits = "0123456789" 644 645 // twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i]. 646 func (buf *buffer) twoDigits(i, d int) { 647 buf.tmp[i+1] = digits[d%10] 648 d /= 10 649 buf.tmp[i] = digits[d%10] 650 } 651 652 // nDigits formats an n-digit integer at buf.tmp[i], 653 // padding with pad on the left. 654 // It assumes d >= 0. 655 func (buf *buffer) nDigits(n, i, d int, pad byte) { 656 j := n - 1 657 for ; j >= 0 && d > 0; j-- { 658 buf.tmp[i+j] = digits[d%10] 659 d /= 10 660 } 661 for ; j >= 0; j-- { 662 buf.tmp[i+j] = pad 663 } 664 } 665 666 // someDigits formats a zero-prefixed variable-width integer at buf.tmp[i]. 667 func (buf *buffer) someDigits(i, d int) int { 668 // Print into the top, then copy down. We know there's space for at least 669 // a 10-digit number. 670 j := len(buf.tmp) 671 for { 672 j-- 673 buf.tmp[j] = digits[d%10] 674 d /= 10 675 if d == 0 { 676 break 677 } 678 } 679 return copy(buf.tmp[i:], buf.tmp[j:]) 680 } 681 682 func (l *loggingT) println(s severity, args ...interface{}) { 683 buf, file, line := l.header(s, 0) 684 fmt.Fprintln(buf, args...) 685 l.output(s, buf, file, line, false) 686 } 687 688 func (l *loggingT) print(s severity, args ...interface{}) { 689 l.printDepth(s, 1, args...) 690 } 691 692 func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) { 693 buf, file, line := l.header(s, depth) 694 fmt.Fprint(buf, args...) 695 if buf.Bytes()[buf.Len()-1] != '\n' { 696 buf.WriteByte('\n') 697 } 698 l.output(s, buf, file, line, false) 699 } 700 701 func (l *loggingT) printfmt(s severity, format string, args ...interface{}) { 702 buf, file, line := l.header(s, 0) 703 fmt.Fprintf(buf, format, args...) 704 if buf.Bytes()[buf.Len()-1] != '\n' { 705 buf.WriteByte('\n') 706 } 707 l.output(s, buf, file, line, false) 708 } 709 710 // printWithFileLine behaves like print but uses the provided file and line number. If 711 // alsoLogToStderr is true, the log message always appears on standard error; it 712 // will also appear in the log file unless --logtostderr is set. 713 func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) { 714 buf := l.formatHeader(s, file, line) 715 fmt.Fprint(buf, args...) 716 if buf.Bytes()[buf.Len()-1] != '\n' { 717 buf.WriteByte('\n') 718 } 719 l.output(s, buf, file, line, alsoToStderr) 720 } 721 722 // output writes the data to the log files and releases the buffer. 723 func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) { 724 l.mu.Lock() 725 if l.traceLocation.isSet() { 726 if l.traceLocation.match(file, line) { 727 buf.Write(stacks(false)) 728 } 729 } 730 data := buf.Bytes() 731 if l.toStderr { 732 os.Stderr.Write(data) 733 } else { 734 if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { 735 os.Stderr.Write(data) 736 } 737 if l.file[s] == nil { 738 if err := l.createFiles(s); err != nil { 739 os.Stderr.Write(data) // Make sure the message appears somewhere. 740 l.exit(err) 741 } 742 } 743 switch s { 744 case fatalLog: 745 l.file[fatalLog].Write(data) 746 fallthrough 747 case errorLog: 748 l.file[errorLog].Write(data) 749 fallthrough 750 case warningLog: 751 l.file[warningLog].Write(data) 752 fallthrough 753 case infoLog: 754 l.file[infoLog].Write(data) 755 } 756 } 757 if s == fatalLog { 758 // If we got here via Exit rather than Fatal, print no stacks. 759 if atomic.LoadUint32(&fatalNoStacks) > 0 { 760 l.mu.Unlock() 761 timeoutFlush(10 * time.Second) 762 os.Exit(1) 763 } 764 // Dump all goroutine stacks before exiting. 765 // First, make sure we see the trace for the current goroutine on standard error. 766 // If -logtostderr has been specified, the loop below will do that anyway 767 // as the first stack in the full dump. 768 if !l.toStderr { 769 os.Stderr.Write(stacks(false)) 770 } 771 // Write the stack trace for all goroutines to the files. 772 trace := stacks(true) 773 logExitFunc = func(error) {} // If we get a write error, we'll still exit below. 774 for log := fatalLog; log >= infoLog; log-- { 775 if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. 776 f.Write(trace) 777 } 778 } 779 l.mu.Unlock() 780 timeoutFlush(10 * time.Second) 781 os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway. 782 } 783 l.putBuffer(buf) 784 l.mu.Unlock() 785 if stats := severityStats[s]; stats != nil { 786 atomic.AddInt64(&stats.lines, 1) 787 atomic.AddInt64(&stats.bytes, int64(len(data))) 788 } 789 } 790 791 // timeoutFlush calls Flush and returns when it completes or after timeout 792 // elapses, whichever happens first. This is needed because the hooks invoked 793 // by Flush may deadlock when glog.Fatal is called from a hook that holds 794 // a lock. 795 func timeoutFlush(timeout time.Duration) { 796 done := make(chan bool, 1) 797 go func() { 798 Flush() // calls logging.lockAndFlushAll() 799 done <- true 800 }() 801 select { 802 case <-done: 803 case <-time.After(timeout): 804 fmt.Fprintln(os.Stderr, "glog: Flush took longer than", timeout) 805 } 806 } 807 808 // stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines. 809 func stacks(all bool) []byte { 810 // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though. 811 n := 10000 812 if all { 813 n = 100000 814 } 815 var trace []byte 816 for i := 0; i < 5; i++ { 817 trace = make([]byte, n) 818 nbytes := runtime.Stack(trace, all) 819 if nbytes < len(trace) { 820 return trace[:nbytes] 821 } 822 n *= 2 823 } 824 return trace 825 } 826 827 // logExitFunc provides a simple mechanism to override the default behavior 828 // of exiting on error. Used in testing and to guarantee we reach a required exit 829 // for fatal logs. Instead, exit could be a function rather than a method but that 830 // would make its use clumsier. 831 var logExitFunc func(error) 832 833 // exit is called if there is trouble creating or writing log files. 834 // It flushes the logs and exits the program; there's no point in hanging around. 835 // l.mu is held. 836 func (l *loggingT) exit(err error) { 837 fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err) 838 // If logExitFunc is set, we do that instead of exiting. 839 if logExitFunc != nil { 840 logExitFunc(err) 841 return 842 } 843 l.flushAll() 844 os.Exit(2) 845 } 846 847 // syncBuffer joins a bufio.Writer to its underlying file, providing access to the 848 // file's Sync method and providing a wrapper for the Write method that provides log 849 // file rotation. There are conflicting methods, so the file cannot be embedded. 850 // l.mu is held for all its methods. 851 type syncBuffer struct { 852 logger *loggingT 853 *bufio.Writer 854 file *os.File 855 sev severity 856 nbytes uint64 // The number of bytes written to this file 857 } 858 859 func (sb *syncBuffer) Sync() error { 860 return sb.file.Sync() 861 } 862 863 func (sb *syncBuffer) Write(p []byte) (n int, err error) { 864 if sb.nbytes+uint64(len(p)) >= MaxSize { 865 if err := sb.rotateFile(time.Now()); err != nil { 866 sb.logger.exit(err) 867 } 868 } 869 n, err = sb.Writer.Write(p) 870 sb.nbytes += uint64(n) 871 if err != nil { 872 sb.logger.exit(err) 873 } 874 return 875 } 876 877 // rotateFile closes the syncBuffer's file and starts a new one. 878 func (sb *syncBuffer) rotateFile(now time.Time) error { 879 if sb.file != nil { 880 sb.Flush() 881 sb.file.Close() 882 } 883 var err error 884 sb.file, _, err = create(severityName[sb.sev], now) 885 sb.nbytes = 0 886 if err != nil { 887 return err 888 } 889 890 sb.Writer = bufio.NewWriterSize(sb.file, bufferSize) 891 892 // Write header. 893 var buf bytes.Buffer 894 fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05")) 895 fmt.Fprintf(&buf, "Running on machine: %s\n", host) 896 fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH) 897 fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n") 898 n, err := sb.file.Write(buf.Bytes()) 899 sb.nbytes += uint64(n) 900 return err 901 } 902 903 // bufferSize sizes the buffer associated with each log file. It's large 904 // so that log records can accumulate without the logging thread blocking 905 // on disk I/O. The flushDaemon will block instead. 906 const bufferSize = 256 * 1024 907 908 // createFiles creates all the log files for severity from sev down to infoLog. 909 // l.mu is held. 910 func (l *loggingT) createFiles(sev severity) error { 911 now := time.Now() 912 // Files are created in decreasing severity order, so as soon as we find one 913 // has already been created, we can stop. 914 for s := sev; s >= infoLog && l.file[s] == nil; s-- { 915 sb := &syncBuffer{ 916 logger: l, 917 sev: s, 918 } 919 if err := sb.rotateFile(now); err != nil { 920 return err 921 } 922 l.file[s] = sb 923 } 924 return nil 925 } 926 927 const flushInterval = 30 * time.Second 928 929 // flushDaemon periodically flushes the log file buffers. 930 func (l *loggingT) flushDaemon() { 931 for range time.NewTicker(flushInterval).C { 932 l.lockAndFlushAll() 933 } 934 } 935 936 // lockAndFlushAll is like flushAll but locks l.mu first. 937 func (l *loggingT) lockAndFlushAll() { 938 l.mu.Lock() 939 l.flushAll() 940 l.mu.Unlock() 941 } 942 943 // flushAll flushes all the logs and attempts to "sync" their data to disk. 944 // l.mu is held. 945 func (l *loggingT) flushAll() { 946 // Flush from fatal down, in case there's trouble flushing. 947 for s := fatalLog; s >= infoLog; s-- { 948 file := l.file[s] 949 if file != nil { 950 file.Flush() // ignore error 951 file.Sync() // ignore error 952 } 953 } 954 } 955 956 // CopyStandardLogTo arranges for messages written to the Go "log" package's 957 // default logs to also appear in the Google logs for the named and lower 958 // severities. Subsequent changes to the standard log's default output location 959 // or format may break this behavior. 960 // 961 // Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not 962 // recognized, CopyStandardLogTo panics. 963 func CopyStandardLogTo(name string) { 964 sev, ok := severityByName(name) 965 if !ok { 966 panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name)) 967 } 968 // Set a log format that captures the user's file and line: 969 // d.go:23: message 970 stdLog.SetFlags(stdLog.Lshortfile) 971 stdLog.SetOutput(logBridge(sev)) 972 } 973 974 // logBridge provides the Write method that enables CopyStandardLogTo to connect 975 // Go's standard logs to the logs provided by this package. 976 type logBridge severity 977 978 // Write parses the standard logging line and passes its components to the 979 // logger for severity(lb). 980 func (lb logBridge) Write(b []byte) (n int, err error) { 981 var ( 982 file = "???" 983 line = 1 984 text string 985 ) 986 // Split "d.go:23: message" into "d.go", "23", and "message". 987 if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 { 988 text = fmt.Sprintf("bad log format: %s", b) 989 } else { 990 file = string(parts[0]) 991 text = string(parts[2][1:]) // skip leading space 992 line, err = strconv.Atoi(string(parts[1])) 993 if err != nil { 994 text = fmt.Sprintf("bad line number: %s", b) 995 line = 1 996 } 997 } 998 // printWithFileLine with alsoToStderr=true, so standard log messages 999 // always appear on standard error. 1000 logging.printWithFileLine(severity(lb), file, line, true, text) 1001 return len(b), nil 1002 } 1003 1004 // setV computes and remembers the V level for a given PC 1005 // when vmodule is enabled. 1006 // File pattern matching takes the basename of the file, stripped 1007 // of its .go suffix, and uses filepath.Match, which is a little more 1008 // general than the *? matching used in C++. 1009 // l.mu is held. 1010 func (l *loggingT) setV(pc uintptr) Level { 1011 fn := runtime.FuncForPC(pc) 1012 file, _ := fn.FileLine(pc) 1013 file = trimToImportPath(file) 1014 for _, filter := range l.vmodule.filter { 1015 if filter.pattern.MatchString(file) { 1016 l.vmap[pc] = filter.level 1017 return filter.level 1018 } 1019 } 1020 l.vmap[pc] = 0 1021 return 0 1022 } 1023 1024 // Verbose is a boolean type that implements Infof (like Printf) etc. 1025 // See the documentation of V for more information. 1026 type Verbose bool 1027 1028 // V reports whether verbosity at the call site is at least the requested level. 1029 // The returned value is a boolean of type Verbose, which implements Info, Infoln 1030 // and Infof. These methods will write to the Info log if called. 1031 // Thus, one may write either 1032 // if glog.V(2) { glog.Info("log this") } 1033 // or 1034 // glog.V(2).Info("log this") 1035 // The second form is shorter but the first is cheaper if logging is off because it does 1036 // not evaluate its arguments. 1037 // 1038 // Whether an individual call to V generates a log record depends on the setting of 1039 // the -v and --vmodule flags; both are off by default. If the level in the call to 1040 // V is at least the value of -v, or of -vmodule for the source file containing the 1041 // call, the V call will log. 1042 func V(level Level) Verbose { 1043 // This function tries hard to be cheap unless there's work to do. 1044 // The fast path is two atomic loads and compares. 1045 1046 // Here is a cheap but safe test to see if V logging is enabled globally. 1047 if logging.verbosity.get() >= level { 1048 return Verbose(true) 1049 } 1050 1051 // It's off globally but it vmodule may still be set. 1052 // Here is another cheap but safe test to see if vmodule is enabled. 1053 if atomic.LoadInt32(&logging.filterLength) > 0 { 1054 // Now we need a proper lock to use the logging structure. The pcs field 1055 // is shared so we must lock before accessing it. This is fairly expensive, 1056 // but if V logging is enabled we're slow anyway. 1057 logging.mu.Lock() 1058 defer logging.mu.Unlock() 1059 if runtime.Callers(2, logging.pcs[:]) == 0 { 1060 return Verbose(false) 1061 } 1062 v, ok := logging.vmap[logging.pcs[0]] 1063 if !ok { 1064 v = logging.setV(logging.pcs[0]) 1065 } 1066 return Verbose(v >= level) 1067 } 1068 return Verbose(false) 1069 } 1070 1071 // Info is equivalent to the global Info function, guarded by the value of v. 1072 // See the documentation of V for usage. 1073 func (v Verbose) Info(args ...interface{}) { 1074 if v { 1075 logging.print(infoLog, args...) 1076 } 1077 } 1078 1079 // Infoln is equivalent to the global Infoln function, guarded by the value of v. 1080 // See the documentation of V for usage. 1081 func (v Verbose) Infoln(args ...interface{}) { 1082 if v { 1083 logging.println(infoLog, args...) 1084 } 1085 } 1086 1087 // Infof is equivalent to the global Infof function, guarded by the value of v. 1088 // See the documentation of V for usage. 1089 func (v Verbose) Infof(format string, args ...interface{}) { 1090 if v { 1091 logging.printfmt(infoLog, format, args...) 1092 } 1093 } 1094 1095 // Info logs to the INFO log. 1096 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1097 func Info(args ...interface{}) { 1098 logging.print(infoLog, args...) 1099 } 1100 1101 // InfoDepth acts as Info but uses depth to determine which call frame to log. 1102 // InfoDepth(0, "msg") is the same as Info("msg"). 1103 func InfoDepth(depth int, args ...interface{}) { 1104 logging.printDepth(infoLog, depth, args...) 1105 } 1106 1107 // Infoln logs to the INFO log. 1108 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1109 func Infoln(args ...interface{}) { 1110 logging.print(infoLog, args...) 1111 } 1112 1113 // Infof logs to the INFO log. 1114 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1115 func Infof(format string, args ...interface{}) { 1116 logging.printfmt(infoLog, format, args...) 1117 } 1118 1119 // Warning logs to the WARNING and INFO logs. 1120 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1121 func Warning(args ...interface{}) { 1122 logging.print(warningLog, args...) 1123 } 1124 1125 // WarningDepth acts as Warning but uses depth to determine which call frame to log. 1126 // WarningDepth(0, "msg") is the same as Warning("msg"). 1127 func WarningDepth(depth int, args ...interface{}) { 1128 logging.printDepth(warningLog, depth, args...) 1129 } 1130 1131 // Warningln logs to the WARNING and INFO logs. 1132 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1133 func Warningln(args ...interface{}) { 1134 logging.println(warningLog, args...) 1135 } 1136 1137 // Warningf logs to the WARNING and INFO logs. 1138 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1139 func Warningf(format string, args ...interface{}) { 1140 logging.printfmt(warningLog, format, args...) 1141 } 1142 1143 // Error logs to the ERROR, WARNING, and INFO logs. 1144 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1145 func Error(args ...interface{}) { 1146 logging.print(errorLog, args...) 1147 } 1148 1149 // ErrorDepth acts as Error but uses depth to determine which call frame to log. 1150 // ErrorDepth(0, "msg") is the same as Error("msg"). 1151 func ErrorDepth(depth int, args ...interface{}) { 1152 logging.printDepth(errorLog, depth, args...) 1153 } 1154 1155 // Errorln logs to the ERROR, WARNING, and INFO logs. 1156 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1157 func Errorln(args ...interface{}) { 1158 logging.println(errorLog, args...) 1159 } 1160 1161 // Errorf logs to the ERROR, WARNING, and INFO logs. 1162 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1163 func Errorf(format string, args ...interface{}) { 1164 logging.printfmt(errorLog, format, args...) 1165 } 1166 1167 // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs, 1168 // including a stack trace of all running goroutines, then calls os.Exit(255). 1169 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1170 func Fatal(args ...interface{}) { 1171 logging.print(fatalLog, args...) 1172 } 1173 1174 // FatalDepth acts as Fatal but uses depth to determine which call frame to log. 1175 // FatalDepth(0, "msg") is the same as Fatal("msg"). 1176 func FatalDepth(depth int, args ...interface{}) { 1177 logging.printDepth(fatalLog, depth, args...) 1178 } 1179 1180 // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs, 1181 // including a stack trace of all running goroutines, then calls os.Exit(255). 1182 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1183 func Fatalln(args ...interface{}) { 1184 logging.println(fatalLog, args...) 1185 } 1186 1187 // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs, 1188 // including a stack trace of all running goroutines, then calls os.Exit(255). 1189 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1190 func Fatalf(format string, args ...interface{}) { 1191 logging.printfmt(fatalLog, format, args...) 1192 } 1193 1194 // fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks. 1195 // It allows Exit and relatives to use the Fatal logs. 1196 var fatalNoStacks uint32 1197 1198 // Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). 1199 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1200 func Exit(args ...interface{}) { 1201 atomic.StoreUint32(&fatalNoStacks, 1) 1202 logging.print(fatalLog, args...) 1203 } 1204 1205 // ExitDepth acts as Exit but uses depth to determine which call frame to log. 1206 // ExitDepth(0, "msg") is the same as Exit("msg"). 1207 func ExitDepth(depth int, args ...interface{}) { 1208 atomic.StoreUint32(&fatalNoStacks, 1) 1209 logging.printDepth(fatalLog, depth, args...) 1210 } 1211 1212 // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). 1213 func Exitln(args ...interface{}) { 1214 atomic.StoreUint32(&fatalNoStacks, 1) 1215 logging.println(fatalLog, args...) 1216 } 1217 1218 // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). 1219 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1220 func Exitf(format string, args ...interface{}) { 1221 atomic.StoreUint32(&fatalNoStacks, 1) 1222 logging.printfmt(fatalLog, format, args...) 1223 }