github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/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 // Modifications copyright 2017 ETC Dev Team. All Rights Reserved. 5 // 6 // Licensed under the Apache License, Version 2.0 (the "License"); 7 // you may not use this file except in compliance with the License. 8 // You may obtain a copy of the License at 9 // 10 // http://www.apache.org/licenses/LICENSE-2.0 11 // 12 // Unless required by applicable law or agreed to in writing, software 13 // distributed under the License is distributed on an "AS IS" BASIS, 14 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 // See the License for the specific language governing permissions and 16 // limitations under the License. 17 18 // Package glog implements logging analogous to the Google-internal C++ INFO/ERROR/V setup. 19 // It provides functions Info, Warning, Error, Fatal, plus formatting variants such as 20 // Infof. It also provides V-style logging controlled by the -v and -vmodule=file=2 flags. 21 // 22 // Basic examples: 23 // 24 // glog.Info("Prepare to repel boarders") 25 // 26 // glog.Fatalf("Initialization failed: %s", err) 27 // 28 // See the documentation for the V function for an explanation of these examples: 29 // 30 // if glog.V(2) { 31 // glog.Info("Starting transaction...") 32 // } 33 // 34 // glog.V(2).Infoln("Processed", nItems, "elements") 35 // 36 // Log output is buffered and written periodically using Flush. Programs 37 // should call Flush before exiting to guarantee all log output is written. 38 // 39 // By default, all log statements write to files in a temporary directory. 40 // This package provides several flags that modify this behavior. 41 // As a result, flag.Parse must be called before any logging is done. 42 // 43 // -logtostderr=false 44 // Logs are written to standard error instead of to files. 45 // -alsologtostderr=false 46 // Logs are written to standard error as well as to files. 47 // -stderrthreshold=ERROR 48 // Log events at or above this severity are logged to standard 49 // error as well as to files. 50 // -log_dir="" 51 // Log files will be written to this directory instead of the 52 // default temporary directory. 53 // 54 // Other flags provide aids to debugging. 55 // 56 // -log_backtrace_at="" 57 // When set to a file and line number holding a logging statement, 58 // such as 59 // -log_backtrace_at=gopherflakes.go:234 60 // a stack trace will be written to the Info log whenever execution 61 // hits that statement. (Unlike with -vmodule, the ".go" must be 62 // present.) 63 // -v=0 64 // Enable V-leveled logging at the specified level. 65 // -vmodule="" 66 // The syntax of the argument is a comma-separated list of pattern=N, 67 // where pattern is a literal file name or "glob" pattern matching 68 // and N is a V level. For instance, 69 // 70 // -vmodule=gopher.go=3 71 // sets the V level to 3 in all Go files named "gopher.go". 72 // 73 // -vmodule=foo=3 74 // sets V to 3 in all files of any packages whose import path ends in "foo". 75 // 76 // -vmodule=foo/*=3 77 // sets V to 3 in all files of any packages whose import path contains "foo". 78 // 79 // This fork of original golang/glog adds log rotation functionality. 80 // Logs are rotated after reaching file size limit or age limit. Additionally 81 // limiting total amount of logs is supported (also by both size and age). 82 // To keep it simple, log-rotation is configured with package-level variables: 83 // - MaxSize - maximum file size (in bytes) - default value: 1024 * 1024 * 1800 84 // - MinSize - minimum file size (in bytes) - default 0 (even empty file can be rotated) 85 // - MaxTotalSize - maximum size of all files (in bytes) - default 0 (do not remove old files) 86 // - RotationInterval - how often log should be rotated - default Never 87 // - MaxAge - maximum age (time.Duration) of log file - default 0 (do not remove old files) 88 // - Compress - whether to GZIP compress rotated logs - default - false 89 // 90 // Default values provide backward-compatibility with golang/glog. If compression is used, 91 // all files except the current one are compressed with GZIP. 92 // 93 // Rotation works like this: 94 // - if MaxSize or RotationInterval is reached, and file size is > MinSize, 95 // current file became old file, and new file is created as a current log file 96 // - all log files older than MaxAge are removed 97 // - if compression is enabled, the old file is compressed 98 // - size of all log files in log_dir is recalculated (to handle external removals of files, etc) 99 // - oldest log files are removed until total size of log files doesn't exceed MaxTotalSize-MaxSize 100 // For sanity, this action is executed only when current file is needs to be rotated 101 // 102 package glog 103 104 import ( 105 "bufio" 106 "bytes" 107 "compress/gzip" 108 "errors" 109 "fmt" 110 "io" 111 "io/ioutil" 112 stdLog "log" 113 "os" 114 "path/filepath" 115 "regexp" 116 "runtime" 117 "sort" 118 "strconv" 119 "strings" 120 "sync" 121 "sync/atomic" 122 "time" 123 124 "github.com/ethereumproject/go-ethereum/common" 125 "github.com/fatih/color" 126 ) 127 128 // DefaultVerbosity establishes the default verbosity Level for 129 // to-file (debug) logging. 130 var DefaultVerbosity = 5 131 132 // DefaultDisplay establishes the default verbosity Level for 133 // display (stderr) logging. 134 var DefaultDisplay = 3 135 136 // DefaultToStdErr establishes the default bool toggling whether logging 137 // should be directed ONLY to stderr. 138 var DefaultToStdErr = false 139 140 // DefaultAlsoToStdErr establishes the default bool toggling whether logging 141 // should be written to BOTH file and stderr. 142 var DefaultAlsoToStdErr = false 143 144 // DefaultLogDirName establishes the default directory name for debug (V) logs. 145 // Log files will be written inside this dir. 146 // By default, this directory will be created if it does not exist within the context's chain directory, eg. 147 // <datadir>/<chain>/log/. 148 var DefaultLogDirName = "log" 149 150 // MinSize is a minimum file size qualifying for rotation. This variable can be used 151 // to avoid rotation of empty or almost emtpy files. 152 var MinSize uint64 153 154 // MaxTotalSize is a maximum size of all log files. 155 var MaxTotalSize uint64 156 157 // Interval is a type for rotation interval specification 158 type Interval uint8 159 160 // These constants identify the interval for log rotation. 161 const ( 162 Never Interval = iota 163 Hourly 164 Daily 165 Weekly 166 Monthly 167 ) 168 169 func ParseInterval(str string) (Interval, error) { 170 mapping := map[string]Interval{ 171 "never": Never, 172 "hourly": Hourly, 173 "daily": Daily, 174 "weekly": Weekly, 175 "monthly": Monthly, 176 } 177 178 interval, ok := mapping[strings.ToLower(str)] 179 if !ok { 180 return Never, fmt.Errorf("invalid interval value '%s'", str) 181 } 182 return interval, nil 183 } 184 185 // RotationInterval determines how often log rotation should take place 186 var RotationInterval = Never 187 188 // MaxAge defines the maximum age of the oldest log file. All log files older 189 // than MaxAge will be removed. 190 var MaxAge time.Duration 191 192 // Compress determines whether to compress rotated logs with GZIP or not. 193 var Compress bool 194 195 // severity identifies the sort of log: info, warning etc. It also implements 196 // the flag.Value interface. The -stderrthreshold flag is of type severity and 197 // should be modified only through the flag.Value interface. The values match 198 // the corresponding constants in C++. 199 // Severity is determined by the method called upon receiver Verbose, 200 // eg. glog.V(logger.Debug).Warnf("this log's severity is %v", warningLog) 201 // eg. glog.V(logger.Error).Infof("This log's severity is %v", infoLog) 202 type severity int32 // sync/atomic int32 203 204 // These constants identify the log levels in order of increasing severity. 205 // A message written to a high-severity log file is also written to each 206 // lower-severity log file. 207 const ( 208 infoLog severity = iota 209 warningLog 210 errorLog 211 fatalLog 212 numSeverity = 4 213 ) 214 215 const severityChar = "IWEF" 216 217 const severityColorReset = "\x1b[0m" // reset both foreground and background 218 var severityColor = []string{"\x1b[2m", "\x1b[33m", "\x1b[31m", "\x1b[35m"} // info:dim warn:yellow, error:red, fatal:magenta 219 220 var severityName = []string{ 221 infoLog: "INFO", 222 warningLog: "WARN", 223 errorLog: "ERR ", 224 fatalLog: "FAIL", 225 } 226 227 // these path prefixes are trimmed for display, but not when 228 // matching vmodule filters. 229 var trimPrefixes = []string{ 230 "/github.com/ethereumproject/go-ethereum", 231 "/github.com/ethereumproject/ethash", 232 } 233 234 func trimToImportPath(file string) string { 235 if root := strings.LastIndex(file, "src/"); root != 0 { 236 file = file[root+3:] 237 } 238 return file 239 } 240 241 // SetV sets the global verbosity level 242 func SetV(v int) { 243 logging.verbosity.set(Level(v)) 244 } 245 246 func SetD(v int) { 247 display.verbosity.set(Level(v)) 248 } 249 250 // SetToStderr sets the global output style 251 func SetToStderr(toStderr bool) { 252 logging.mu.Lock() 253 logging.toStderr = toStderr 254 logging.mu.Unlock() 255 } 256 257 // SetAlsoToStderr sets global output option 258 // for logging to both FS and stderr. 259 func SetAlsoToStderr(to bool) { 260 logging.mu.Lock() 261 262 logging.alsoToStderr = to 263 logging.mu.Unlock() 264 } 265 266 // GetTraceLocation returns the global TraceLocation flag. 267 func GetTraceLocation() *TraceLocation { 268 return &logging.traceLocation 269 } 270 271 // GetVModule returns the global verbosity pattern flag. 272 func GetVModule() *moduleSpec { 273 return &logging.vmodule 274 } 275 276 // GetVerbosity returns the global verbosity level flag. 277 func GetVerbosity() *Level { 278 return &logging.verbosity 279 } 280 281 func GetDisplayable() *Level { 282 return &display.verbosity 283 } 284 285 // get returns the value of the severity. 286 func (s *severity) get() severity { 287 return severity(atomic.LoadInt32((*int32)(s))) 288 } 289 290 // set sets the value of the severity. 291 func (s *severity) set(val severity) { 292 atomic.StoreInt32((*int32)(s), int32(val)) 293 } 294 295 // String is part of the flag.Value interface. 296 func (s *severity) String() string { 297 return strconv.FormatInt(int64(*s), 10) 298 } 299 300 // Get is part of the flag.Value interface. 301 func (s *severity) Get() interface{} { 302 return *s 303 } 304 305 // Set is part of the flag.Value interface. 306 func (s *severity) Set(value string) error { 307 var threshold severity 308 // Is it a known name? 309 if v, ok := severityByName(value); ok { 310 threshold = v 311 } else { 312 v, err := strconv.Atoi(value) 313 if err != nil { 314 return err 315 } 316 threshold = severity(v) 317 } 318 logging.stderrThreshold.set(threshold) 319 return nil 320 } 321 322 func severityByName(s string) (severity, bool) { 323 s = strings.ToUpper(s) 324 for i, name := range severityName { 325 if name == s { 326 return severity(i), true 327 } 328 } 329 return 0, false 330 } 331 332 // OutputStats tracks the number of output lines and bytes written. 333 type OutputStats struct { 334 lines int64 335 bytes int64 336 } 337 338 // Lines returns the number of lines written. 339 func (s *OutputStats) Lines() int64 { 340 return atomic.LoadInt64(&s.lines) 341 } 342 343 // Bytes returns the number of bytes written. 344 func (s *OutputStats) Bytes() int64 { 345 return atomic.LoadInt64(&s.bytes) 346 } 347 348 // Stats tracks the number of lines of output and number of bytes 349 // per severity level. Values must be read with atomic.LoadInt64. 350 var Stats struct { 351 Info, Warning, Error OutputStats 352 } 353 354 var severityStats = [numSeverity]*OutputStats{ 355 infoLog: &Stats.Info, 356 warningLog: &Stats.Warning, 357 errorLog: &Stats.Error, 358 } 359 360 // Level is exported because it appears in the arguments to V and is 361 // the type of the v flag, which can be set programmatically. 362 // It's a distinct type because we want to discriminate it from logType. 363 // Variables of type level are only changed under logging.mu. 364 // The -v flag is read only with atomic ops, so the state of the logging 365 // module is consistent. 366 367 // Level is treated as a sync/atomic int32. 368 369 // Level specifies a level of verbosity for V logs. *Level implements 370 // flag.Value; the -v flag is of type Level and should be modified 371 // only through the flag.Value interface. 372 type Level int32 373 374 // get returns the value of the Level. 375 func (l *Level) get() Level { 376 return Level(atomic.LoadInt32((*int32)(l))) 377 } 378 379 // set sets the value of the Level. 380 func (l *Level) set(val Level) { 381 atomic.StoreInt32((*int32)(l), int32(val)) 382 } 383 384 // String is part of the flag.Value interface. 385 func (l *Level) String() string { 386 return strconv.FormatInt(int64(*l), 10) 387 } 388 389 // Get is part of the flag.Value interface. 390 func (l *Level) Get() interface{} { 391 return *l 392 } 393 394 // Set is part of the flag.Value interface. 395 func (l *Level) Set(value string) error { 396 v, err := strconv.Atoi(value) 397 if err != nil { 398 return err 399 } 400 logging.mu.Lock() 401 defer logging.mu.Unlock() 402 logging.setVState(Level(v), logging.vmodule.filter, false) 403 return nil 404 } 405 406 // moduleSpec represents the setting of the -vmodule flag. 407 type moduleSpec struct { 408 filter []modulePat 409 } 410 411 // modulePat contains a filter for the -vmodule flag. 412 // It holds a verbosity level and a file pattern to match. 413 type modulePat struct { 414 pattern *regexp.Regexp 415 level Level 416 } 417 418 func (m *moduleSpec) String() string { 419 // Lock because the type is not atomic. TODO: clean this up. 420 logging.mu.Lock() 421 defer logging.mu.Unlock() 422 var b bytes.Buffer 423 for i, f := range m.filter { 424 if i > 0 { 425 b.WriteRune(',') 426 } 427 fmt.Fprintf(&b, "%s=%d", f.pattern, f.level) 428 } 429 return b.String() 430 } 431 432 // Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the 433 // struct is not exported. 434 func (m *moduleSpec) Get() interface{} { 435 return nil 436 } 437 438 var errVmoduleSyntax = errors.New("syntax error: expect comma-separated list of filename=N") 439 440 // Syntax: -vmodule=recordio=2,file=1,gfs*=3 441 func (m *moduleSpec) Set(value string) error { 442 var filter []modulePat 443 for _, pat := range strings.Split(value, ",") { 444 if len(pat) == 0 { 445 // Empty strings such as from a trailing comma can be ignored. 446 continue 447 } 448 patLev := strings.Split(pat, "=") 449 if len(patLev) != 2 || len(patLev[0]) == 0 || len(patLev[1]) == 0 { 450 return errVmoduleSyntax 451 } 452 pattern := patLev[0] 453 v, err := strconv.Atoi(patLev[1]) 454 if err != nil { 455 return errors.New("syntax error: expect comma-separated list of filename=N") 456 } 457 if v < 0 { 458 return errors.New("negative value for vmodule level") 459 } 460 if v == 0 { 461 continue // Ignore. It's harmless but no point in paying the overhead. 462 } 463 // TODO: check syntax of filter? 464 re, _ := compileModulePattern(pattern) 465 filter = append(filter, modulePat{re, Level(v)}) 466 } 467 logging.mu.Lock() 468 defer logging.mu.Unlock() 469 logging.setVState(logging.verbosity, filter, true) 470 return nil 471 } 472 473 // compiles a vmodule pattern to a regular expression. 474 func compileModulePattern(pat string) (*regexp.Regexp, error) { 475 re := ".*" 476 for _, comp := range strings.Split(pat, "/") { 477 if comp == "*" { 478 re += "(/.*)?" 479 } else if comp != "" { 480 // TODO: maybe return error if comp contains * 481 re += "/" + regexp.QuoteMeta(comp) 482 } 483 } 484 if !strings.HasSuffix(pat, ".go") { 485 re += "/[^/]+\\.go" 486 } 487 return regexp.Compile(re + "$") 488 } 489 490 // traceLocation represents the setting of the -log_backtrace_at flag. 491 type TraceLocation struct { 492 file string 493 line int 494 } 495 496 // isSet reports whether the trace location has been specified. 497 // logging.mu is held. 498 func (t *TraceLocation) isSet() bool { 499 return t.line > 0 500 } 501 502 // match reports whether the specified file and line matches the trace location. 503 // The argument file name is the full path, not the basename specified in the flag. 504 // logging.mu is held. 505 func (t *TraceLocation) match(file string, line int) bool { 506 if t.line != line { 507 return false 508 } 509 if i := strings.LastIndex(file, "/"); i >= 0 { 510 file = file[i+1:] 511 } 512 return t.file == file 513 } 514 515 func (t *TraceLocation) String() string { 516 // Lock because the type is not atomic. TODO: clean this up. 517 logging.mu.Lock() 518 defer logging.mu.Unlock() 519 return fmt.Sprintf("%s:%d", t.file, t.line) 520 } 521 522 // Get is part of the (Go 1.2) flag.Getter interface. It always returns nil for this flag type since the 523 // struct is not exported 524 func (t *TraceLocation) Get() interface{} { 525 return nil 526 } 527 528 var errTraceSyntax = errors.New("syntax error: expect 'file.go:234'") 529 530 // Syntax: -log_backtrace_at=gopherflakes.go:234 531 // Note that unlike vmodule the file extension is included here. 532 func (t *TraceLocation) Set(value string) error { 533 if value == "" { 534 // Unset. 535 logging.mu.Lock() 536 t.line = 0 537 t.file = "" 538 logging.mu.Unlock() 539 return nil 540 } 541 542 fields := strings.Split(value, ":") 543 if len(fields) != 2 { 544 return errTraceSyntax 545 } 546 file, line := fields[0], fields[1] 547 if !strings.Contains(file, ".") { 548 return errTraceSyntax 549 } 550 v, err := strconv.Atoi(line) 551 if err != nil { 552 return errTraceSyntax 553 } 554 if v <= 0 { 555 return errors.New("negative or zero value for level") 556 } 557 logging.mu.Lock() 558 defer logging.mu.Unlock() 559 t.line = v 560 t.file = file 561 return nil 562 } 563 564 // flushSyncWriter is the interface satisfied by logging destinations. 565 type flushSyncWriter interface { 566 Flush() error 567 Sync() error 568 io.Writer 569 } 570 571 type logTName string 572 573 const ( 574 fileLog logTName = "file" 575 displayLog logTName = "display" 576 ) 577 578 // loggingT collects all the global state of the logging setup. 579 type loggingT struct { 580 logTName 581 // Boolean flags. Not handled atomically because the flag.Value interface 582 // does not let us avoid the =true, and that shorthand is necessary for 583 // compatibility. TODO: does this matter enough to fix? Seems unlikely. 584 toStderr bool // The -logtostderr flag. 585 alsoToStderr bool // The -alsologtostderr flag. 586 587 // Level flag. Handled atomically. 588 stderrThreshold severity // The -stderrthreshold flag. 589 590 // freeList is a list of byte buffers, maintained under freeListMu. 591 freeList *buffer 592 // freeListMu maintains the free list. It is separate from the main mutex 593 // so buffers can be grabbed and printed to without holding the main lock, 594 // for better parallelization. 595 freeListMu sync.Mutex 596 597 // mu protects the remaining elements of this structure and is 598 // used to synchronize logging. 599 mu sync.Mutex 600 // file holds writer for each of the log types. 601 file [numSeverity]flushSyncWriter 602 // pcs is used in V to avoid an allocation when computing the caller's PC. 603 pcs [1]uintptr 604 // vmap is a cache of the V Level for each V() call site, identified by PC. 605 // It is wiped whenever the vmodule flag changes state. 606 vmap map[uintptr]Level 607 // filterLength stores the length of the vmodule filter chain. If greater 608 // than zero, it means vmodule is enabled. It may be read safely 609 // using sync.LoadInt32, but is only modified under mu. 610 filterLength int32 611 // traceLocation is the state of the -log_backtrace_at flag. 612 traceLocation TraceLocation 613 // These flags are modified only under lock, although verbosity may be fetched 614 // safely using atomic.LoadInt32. 615 vmodule moduleSpec // The state of the -vmodule flag. 616 verbosity Level // V logging level, the value of the -v flag/ 617 618 // severityTraceThreshold determines the minimum severity at which 619 // file traces will be logged in the header. See severity const iota above. 620 // Only severities at or above this number will be logged with a trace, 621 // eg. at severityTraceThreshold = 2, then only severities errorLog and fatalLog 622 // will log with traces. 623 severityTraceThreshold severity 624 625 // verbosityTraceThreshold determines the minimum verbosity at which 626 // file traces will be logged in the header. 627 // Only levels at or above this number will be logged with a trace, 628 // eg. at verbosityTraceThreshold = 5, then only verbosities Debug, Detail, and Ridiculousness 629 // will log with traces. 630 verbosityTraceThreshold Level 631 } 632 633 // buffer holds a byte Buffer for reuse. The zero value is ready for use. 634 type buffer struct { 635 bytes.Buffer 636 tmp [64]byte // temporary byte array for creating headers. 637 next *buffer 638 } 639 640 var logging loggingT 641 var display loggingT 642 643 func init() { 644 //flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files") 645 //flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files") 646 //flag.Var(&logging.verbosity, "v", "log level for V logs") 647 //flag.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr") 648 //flag.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") 649 //flag.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") 650 651 logging.logTName = fileLog 652 // Default stderrThreshold is ERROR. 653 // This makes V(logger.Error) logs print ALSO to stderr. 654 logging.stderrThreshold = errorLog 655 656 // Establish defaults for trace thresholds. 657 logging.verbosityTraceThreshold.set(0) 658 logging.severityTraceThreshold.set(2) 659 660 // Default for verbosity. 661 logging.setVState(Level(DefaultVerbosity), nil, false) 662 go logging.flushDaemon() 663 664 display.logTName = displayLog 665 // Renders anything at or below (Warn...) level Info to stderr, which 666 // is set by default anyway. 667 display.stderrThreshold = infoLog 668 669 // toStderr makes it ONLY print to stderr, not to file 670 display.toStderr = true 671 672 // Should never reach... unless we get real fancy with D(levels) 673 display.verbosityTraceThreshold.set(5) 674 // Only includes traces for severity=fatal logs for display. 675 // This should never be reached; fatal logs should ALWAYS be logged to file, 676 // and they will also be written to stderr (anything Error and above is). 677 // Keep in mind severities are "upside-down" from verbosities; so here 3=error, 4=fatal, and 0=info 678 // and that here severity>=3 will meet the threshold. 679 display.severityTraceThreshold.set(2) 680 // Set display verbosity default Info. So it will render 681 // all Fatal, Error, Warn, and Info log levels. 682 // Please don't use Fatal for display; again, Fatal logs should only go through file logging 683 // (they will be printed to stderr anyway). 684 display.setVState(Level(DefaultDisplay), nil, false) 685 go display.flushDaemon() 686 } 687 688 // Flush flushes all pending log I/O. 689 func Flush() { 690 logging.lockAndFlushAll() 691 display.lockAndFlushAll() 692 } 693 694 // traceThreshold determines the arbitrary level for log lines to be printed 695 // with caller trace information in the header. 696 func (l *loggingT) traceThreshold(s severity) bool { 697 return s >= l.severityTraceThreshold || l.verbosity >= l.verbosityTraceThreshold 698 } 699 700 // GetVTraceThreshold gets the current verbosity trace threshold for logging. 701 func GetVTraceThreshold() *Level { 702 return &logging.verbosityTraceThreshold 703 } 704 705 // SetVTraceThreshold sets the current verbosity trace threshold for logging. 706 func SetVTraceThreshold(v int) { 707 logging.mu.Lock() 708 defer logging.mu.Unlock() 709 710 l := logging.verbosity.get() 711 logging.verbosity.set(0) 712 logging.verbosityTraceThreshold.set(Level(v)) 713 logging.verbosity.set(l) 714 } 715 716 // setVState sets a consistent state for V logging. 717 // l.mu is held. 718 func (l *loggingT) setVState(verbosity Level, filter []modulePat, setFilter bool) { 719 // Turn verbosity off so V will not fire while we are in transition. 720 l.verbosity.set(0) 721 // Ditto for filter length. 722 atomic.StoreInt32(&l.filterLength, 0) 723 724 // Set the new filters and wipe the pc->Level map if the filter has changed. 725 if setFilter { 726 l.vmodule.filter = filter 727 l.vmap = make(map[uintptr]Level) 728 } 729 730 // Things are consistent now, so enable filtering and verbosity. 731 // They are enabled in order opposite to that in V. 732 atomic.StoreInt32(&l.filterLength, int32(len(filter))) 733 l.verbosity.set(verbosity) 734 } 735 736 // getBuffer returns a new, ready-to-use buffer. 737 func (l *loggingT) getBuffer() *buffer { 738 l.freeListMu.Lock() 739 b := l.freeList 740 if b != nil { 741 l.freeList = b.next 742 } 743 l.freeListMu.Unlock() 744 if b == nil { 745 b = new(buffer) 746 } else { 747 b.next = nil 748 b.Reset() 749 } 750 return b 751 } 752 753 // putBuffer returns a buffer to the free list. 754 func (l *loggingT) putBuffer(b *buffer) { 755 if b.Len() >= 256 { 756 // Let big buffers die a natural death. 757 return 758 } 759 l.freeListMu.Lock() 760 b.next = l.freeList 761 l.freeList = b 762 l.freeListMu.Unlock() 763 } 764 765 var timeNow = time.Now // Stubbed out for testing. 766 767 /* 768 header formats a log header as defined by the C++ implementation. 769 It returns a buffer containing the formatted header and the user's file and line number. 770 The depth specifies how many stack frames above lives the source line to be identified in the log message. 771 772 Log lines have this form: 773 Lmmdd hh:mm:ss.uuuuuu threadid file:line] msg... 774 where the fields are defined as follows: 775 L A single character, representing the log level (eg 'I' for INFO) 776 mm The month (zero padded; ie May is '05') 777 dd The day (zero padded) 778 hh:mm:ss.uuuuuu Time in hours, minutes and fractional seconds 779 threadid The space-padded thread ID as returned by GetTID() 780 file The file name 781 line The line number 782 msg The user-supplied message 783 */ 784 func (l *loggingT) header(s severity, depth int) (*buffer, string, int) { 785 _, file, line, ok := runtime.Caller(3 + depth) 786 if !ok { 787 file = "???" 788 line = 1 789 } else { 790 file = trimToImportPath(file) 791 for _, p := range trimPrefixes { 792 if strings.HasPrefix(file, p) { 793 file = file[len(p):] 794 break 795 } 796 } 797 file = file[1:] // drop '/' 798 } 799 return l.formatHeader(s, file, line), file, line 800 } 801 802 // formatHeader formats a log header using the provided file name and line number. 803 func (l *loggingT) formatHeader(s severity, file string, line int) *buffer { 804 now := timeNow() 805 if line < 0 { 806 line = 0 // not a real line number, but acceptable to someDigits 807 } 808 if s > fatalLog { 809 s = infoLog // for safety. 810 } 811 buf := l.getBuffer() 812 813 // Avoid Fprintf, for speed. The format is so simple that we can do it quickly by hand. 814 // It's worth about 3X. Fprintf is hard. 815 year, month, day := now.Date() 816 hour, minute, second := now.Clock() 817 // Lmmdd hh:mm:ss.uuuuuu threadid file:line] 818 819 //buf.nDigits(8, 0, severityColor[s],'') 820 821 // If to-file (debuggable) logs. 822 if l.logTName == fileLog { 823 buf.tmp[0] = severityChar[s] 824 buf.Write(buf.tmp[:1]) 825 buf.twoDigits(0, int(month)) 826 buf.twoDigits(2, day) 827 buf.tmp[4] = ' ' 828 buf.twoDigits(5, hour) 829 buf.tmp[7] = ':' 830 buf.twoDigits(8, minute) 831 buf.tmp[10] = ':' 832 buf.twoDigits(11, second) 833 // Only keep nanoseconds for file logs 834 buf.tmp[13] = '.' 835 buf.nDigits(6, 14, now.Nanosecond()/1000, '0') 836 buf.Write(buf.tmp[:20]) 837 buf.WriteString(" ") 838 839 if l.traceThreshold(s) { 840 buf.WriteString(file) 841 buf.tmp[0] = ':' 842 n := buf.someDigits(1, line) 843 buf.tmp[n+1] = ']' 844 buf.tmp[n+2] = ' ' 845 buf.Write(buf.tmp[:n+3]) 846 } 847 } else { 848 // Write dim. 849 buf.WriteString(severityColor[infoLog]) 850 851 buf.nDigits(4, 0, year, '_') 852 buf.nDigits(4, 0, year, '_') 853 buf.tmp[4] = '-' 854 buf.twoDigits(5, int(month)) 855 buf.tmp[7] = '-' 856 buf.twoDigits(8, day) 857 buf.tmp[10] = ' ' 858 buf.twoDigits(11, hour) 859 buf.tmp[13] = ':' 860 buf.twoDigits(14, minute) 861 buf.tmp[16] = ':' 862 buf.twoDigits(17, second) 863 buf.Write(buf.tmp[:19]) 864 865 buf.WriteString(severityColorReset + " ") 866 if l.traceThreshold(s) { 867 buf.WriteString(severityColor[s]) 868 buf.Write([]byte{'['}) 869 buf.WriteString(severityName[s]) 870 buf.Write([]byte{']'}) 871 buf.WriteString(severityColorReset) 872 buf.Write([]byte{' '}) 873 } 874 } 875 876 return buf 877 } 878 879 // Some custom tiny helper functions to print the log header efficiently. 880 881 const digits = "0123456789" 882 883 // twoDigits formats a zero-prefixed two-digit integer at buf.tmp[i]. 884 func (buf *buffer) twoDigits(i, d int) { 885 buf.tmp[i+1] = digits[d%10] 886 d /= 10 887 buf.tmp[i] = digits[d%10] 888 } 889 890 // nDigits formats an n-digit integer at buf.tmp[i], 891 // padding with pad on the left. 892 // It assumes d >= 0. 893 func (buf *buffer) nDigits(n, i, d int, pad byte) { 894 j := n - 1 895 for ; j >= 0 && d > 0; j-- { 896 buf.tmp[i+j] = digits[d%10] 897 d /= 10 898 } 899 for ; j >= 0; j-- { 900 buf.tmp[i+j] = pad 901 } 902 } 903 904 // someDigits formats a zero-prefixed variable-width integer at buf.tmp[i]. 905 func (buf *buffer) someDigits(i, d int) int { 906 // Print into the top, then copy down. We know there's space for at least 907 // a 10-digit number. 908 j := len(buf.tmp) 909 for { 910 j-- 911 buf.tmp[j] = digits[d%10] 912 d /= 10 913 if d == 0 { 914 break 915 } 916 } 917 return copy(buf.tmp[i:], buf.tmp[j:]) 918 } 919 920 func (l *loggingT) println(s severity, args ...interface{}) { 921 buf, file, line := l.header(s, 0) 922 fmt.Fprintln(buf, args...) 923 l.output(s, buf, file, line, false) 924 } 925 926 func (l *loggingT) print(s severity, args ...interface{}) { 927 l.printDepth(s, 1, args...) 928 } 929 930 func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) { 931 buf, file, line := l.header(s, depth) 932 fmt.Fprint(buf, args...) 933 if buf.Bytes()[buf.Len()-1] != '\n' { 934 buf.WriteByte('\n') 935 } 936 l.output(s, buf, file, line, false) 937 } 938 939 func (l *loggingT) printfmt(s severity, format string, args ...interface{}) { 940 buf, file, line := l.header(s, 0) 941 fmt.Fprintf(buf, format, args...) 942 if buf.Bytes()[buf.Len()-1] != '\n' { 943 buf.WriteByte('\n') 944 } 945 l.output(s, buf, file, line, false) 946 } 947 948 // printWithFileLine behaves like print but uses the provided file and line number. If 949 // alsoLogToStderr is true, the log message always appears on standard error; it 950 // will also appear in the log file unless --logtostderr is set. 951 func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) { 952 buf := l.formatHeader(s, file, line) 953 fmt.Fprint(buf, args...) 954 if buf.Bytes()[buf.Len()-1] != '\n' { 955 buf.WriteByte('\n') 956 } 957 l.output(s, buf, file, line, alsoToStderr) 958 } 959 960 // output writes the data to the log files and releases the buffer. 961 func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) { 962 l.mu.Lock() 963 if l.traceLocation.isSet() { 964 if l.traceLocation.match(file, line) { 965 buf.Write(stacks(false)) 966 } 967 } 968 data := buf.Bytes() 969 if l.toStderr { 970 color.Error.Write(data) 971 } else { 972 if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { 973 color.Error.Write(data) 974 } 975 if l.file[s] == nil { 976 if err := l.createFiles(s); err != nil { 977 color.Error.Write(data) // Make sure the message appears somewhere. 978 l.exit(err) 979 } 980 } 981 switch s { 982 case fatalLog: 983 l.file[fatalLog].Write(data) 984 fallthrough 985 case errorLog: 986 l.file[errorLog].Write(data) 987 fallthrough 988 case warningLog: 989 l.file[warningLog].Write(data) 990 fallthrough 991 case infoLog: 992 l.file[infoLog].Write(data) 993 } 994 } 995 if s == fatalLog { 996 // If we got here via Exit rather than Fatal, print no stacks. 997 if atomic.LoadUint32(&fatalNoStacks) > 0 { 998 l.mu.Unlock() 999 timeoutFlush(10 * time.Second) 1000 os.Exit(1) 1001 } 1002 // Dump all goroutine stacks before exiting. 1003 // First, make sure we see the trace for the current goroutine on standard error. 1004 // If -logtostderr has been specified, the loop below will do that anyway 1005 // as the first stack in the full dump. 1006 if !l.toStderr { 1007 color.Error.Write(stacks(false)) 1008 } 1009 // Write the stack trace for all goroutines to the files. 1010 trace := stacks(true) 1011 logExitFunc = func(error) {} // If we get a write error, we'll still exit below. 1012 for log := fatalLog; log >= infoLog; log-- { 1013 if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. 1014 f.Write(trace) 1015 } 1016 } 1017 l.mu.Unlock() 1018 timeoutFlush(10 * time.Second) 1019 os.Exit(255) // C++ uses -1, which is silly because it's anded with 255 anyway. 1020 } 1021 l.putBuffer(buf) 1022 l.mu.Unlock() 1023 if stats := severityStats[s]; stats != nil { 1024 atomic.AddInt64(&stats.lines, 1) 1025 atomic.AddInt64(&stats.bytes, int64(len(data))) 1026 } 1027 } 1028 1029 // timeoutFlush calls Flush and returns when it completes or after timeout 1030 // elapses, whichever happens first. This is needed because the hooks invoked 1031 // by Flush may deadlock when glog.Fatal is called from a hook that holds 1032 // a lock. 1033 func timeoutFlush(timeout time.Duration) { 1034 done := make(chan bool, 1) 1035 go func() { 1036 Flush() // calls logging.lockAndFlushAll() 1037 done <- true 1038 }() 1039 select { 1040 case <-done: 1041 case <-time.After(timeout): 1042 fmt.Fprintln(color.Error, "glog: Flush took longer than", timeout) 1043 } 1044 } 1045 1046 // stacks is a wrapper for runtime.Stack that attempts to recover the data for all goroutines. 1047 func stacks(all bool) []byte { 1048 // We don't know how big the traces are, so grow a few times if they don't fit. Start large, though. 1049 n := 10000 1050 if all { 1051 n = 100000 1052 } 1053 var trace []byte 1054 for i := 0; i < 5; i++ { 1055 trace = make([]byte, n) 1056 nbytes := runtime.Stack(trace, all) 1057 if nbytes < len(trace) { 1058 return trace[:nbytes] 1059 } 1060 n *= 2 1061 } 1062 return trace 1063 } 1064 1065 // logExitFunc provides a simple mechanism to override the default behavior 1066 // of exiting on error. Used in testing and to guarantee we reach a required exit 1067 // for fatal logs. Instead, exit could be a function rather than a method but that 1068 // would make its use clumsier. 1069 var logExitFunc func(error) 1070 1071 // exit is called if there is trouble creating or writing log files. 1072 // It flushes the logs and exits the program; there's no point in hanging around. 1073 // l.mu is held. 1074 func (l *loggingT) exit(err error) { 1075 fmt.Fprintf(color.Error, "log: exiting because of error: %s\n", err) 1076 // If logExitFunc is set, we do that instead of exiting. 1077 if logExitFunc != nil { 1078 logExitFunc(err) 1079 return 1080 } 1081 l.flushAll() 1082 os.Exit(2) 1083 } 1084 1085 // syncBuffer joins a bufio.Writer to its underlying file, providing access to the 1086 // file's Sync method and providing a wrapper for the Write method that provides log 1087 // file rotation. There are conflicting methods, so the file cannot be embedded. 1088 // l.mu is held for all its methods. 1089 type syncBuffer struct { 1090 logger *loggingT 1091 *bufio.Writer 1092 file *os.File 1093 time time.Time 1094 sev severity 1095 nbytes uint64 // The number of bytes written to this file 1096 } 1097 1098 func (sb *syncBuffer) Sync() error { 1099 return sb.file.Sync() 1100 } 1101 1102 func (sb *syncBuffer) Write(p []byte) (n int, err error) { 1103 now := time.Now() 1104 if sb.shouldRotate(len(p), now) { 1105 if err := sb.rotateCurrent(now); err != nil { 1106 sb.logger.exit(err) 1107 } 1108 go sb.rotateOld(now) 1109 } 1110 n, err = sb.Writer.Write(p) 1111 sb.nbytes += uint64(n) 1112 if err != nil { 1113 sb.logger.exit(err) 1114 } 1115 return 1116 } 1117 1118 // shouldRotate checks if we need to rotate the current log file 1119 func (sb *syncBuffer) shouldRotate(len int, now time.Time) bool { 1120 newLen := sb.nbytes + uint64(len) 1121 if newLen <= MinSize { 1122 return false 1123 } else if MaxSize > 0 && newLen >= MaxSize { 1124 return true 1125 } 1126 1127 switch RotationInterval { 1128 case Never: 1129 return false 1130 case Hourly: 1131 return sb.time.Hour() != now.Hour() 1132 case Daily: 1133 return sb.time.Day() != now.Day() 1134 case Weekly: 1135 yearLog, weekLog := sb.time.ISOWeek() 1136 yearNow, weekNow := now.ISOWeek() 1137 return !(yearLog == yearNow && weekLog == weekNow) 1138 case Monthly: 1139 return sb.time.Month() != now.Month() 1140 } 1141 return false 1142 } 1143 1144 // rotateCurrent closes the syncBuffer's file and starts a new one. 1145 func (sb *syncBuffer) rotateCurrent(now time.Time) error { 1146 if sb.file != nil { 1147 sb.Flush() 1148 sb.file.Close() 1149 } 1150 var err error 1151 sb.file, _, err = create(severityName[sb.sev], now) 1152 sb.nbytes = 0 1153 sb.time = time.Now() 1154 if err != nil { 1155 return err 1156 } 1157 1158 sb.Writer = bufio.NewWriterSize(sb.file, bufferSize) 1159 1160 // Write header. 1161 var buf bytes.Buffer 1162 fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05")) 1163 fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH) 1164 fmt.Fprintf(&buf, "Context: %s\n", common.GetClientSessionIdentity().String()) 1165 fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n") 1166 n, err := sb.file.Write(buf.Bytes()) 1167 sb.nbytes += uint64(n) 1168 return err 1169 } 1170 1171 // converts plain log file to gzipped log file. New file is created 1172 func gzipFile(name string) error { 1173 gzipped, err := os.Create(name + ".gz") 1174 defer gzipped.Close() 1175 if err != nil { 1176 return err 1177 } 1178 writer := bufio.NewWriter(gzipped) 1179 gzipWriter := gzip.NewWriter(writer) 1180 1181 plain, err := os.Open(name) 1182 if err != nil { 1183 return err 1184 } 1185 reader := bufio.NewReader(plain) 1186 1187 // copy from plain text file to gzipped output 1188 _, err = io.Copy(gzipWriter, reader) 1189 _ = plain.Close() 1190 if err != nil { 1191 return err 1192 } 1193 if err = gzipWriter.Close(); err != nil { 1194 return err 1195 } 1196 if err = writer.Flush(); err != nil { 1197 return err 1198 } 1199 if err = gzipped.Sync(); err != nil { 1200 return err 1201 } 1202 if err = gzipped.Close(); err != nil { 1203 return err 1204 } 1205 1206 return os.Remove(name) 1207 } 1208 1209 var rotationTime int64 1210 1211 func (sb *syncBuffer) rotateOld(now time.Time) { 1212 nanos := now.UnixNano() 1213 if atomic.CompareAndSwapInt64(&rotationTime, 0, nanos) { 1214 logs, err := getLogFiles() 1215 if err != nil { 1216 Fatal(err) 1217 } 1218 1219 logs = sb.excludeActive(logs) 1220 1221 logs, err = removeOutdated(logs, now) 1222 if err != nil { 1223 Fatal(err) 1224 } 1225 1226 logs, err = compressOrphans(logs) 1227 if err != nil { 1228 Fatal(err) 1229 } 1230 1231 if MaxTotalSize > MaxSize { 1232 totalSize := getTotalSize(logs) 1233 for i := 0; i < len(logs) && totalSize > MaxTotalSize-MaxSize; i++ { 1234 err := os.Remove(filepath.Join(logs[i].dir, logs[i].name)) 1235 if err != nil { 1236 Fatal(err) 1237 } 1238 totalSize -= logs[i].size 1239 } 1240 } 1241 1242 if current := atomic.SwapInt64(&rotationTime, 0); current > nanos { 1243 go sb.rotateOld(time.Unix(0, current)) 1244 } 1245 } else { 1246 atomic.StoreInt64(&rotationTime, nanos) 1247 } 1248 } 1249 1250 type logFile struct { 1251 dir string 1252 name string 1253 size uint64 1254 timestamp string 1255 } 1256 1257 // getLogFiles returns log files, ordered from oldest to newest 1258 func getLogFiles() (logFiles []logFile, err error) { 1259 prefix := fmt.Sprintf("%s.%s.%s.log.", program, host, userName) 1260 for _, logDir := range logDirs { 1261 files, err := ioutil.ReadDir(logDir) 1262 if err == nil { 1263 files = filterLogFiles(files, prefix) 1264 for _, file := range files { 1265 logFiles = append(logFiles, logFile{ 1266 dir: logDir, 1267 name: file.Name(), 1268 size: uint64(file.Size()), 1269 timestamp: extractTimestamp(file.Name(), prefix), 1270 }) 1271 } 1272 sort.Slice(logFiles, func(i, j int) bool { 1273 return logFiles[i].timestamp < logFiles[j].timestamp 1274 }) 1275 return logFiles, nil 1276 } 1277 } 1278 return nil, errors.New("log: no log dirs") 1279 } 1280 1281 func (sb *syncBuffer) excludeActive(logs []logFile) []logFile { 1282 filtered := logs[:0] 1283 current := sb.getCurrentLogs() 1284 for _, log := range logs { 1285 active := false 1286 fullName := filepath.Join(log.dir, log.name) 1287 for _, latest := range current { 1288 if fullName == latest { 1289 active = true 1290 } 1291 } 1292 if !active { 1293 filtered = append(filtered, log) 1294 } 1295 } 1296 return filtered 1297 } 1298 1299 // getCurrentLogs returns list of log files currently in use by the syncBuffer 1300 func (sb *syncBuffer) getCurrentLogs() (logs []string) { 1301 if sb.logger == nil { 1302 return nil 1303 } 1304 for _, buffer := range sb.logger.file { 1305 if buffer != nil && buffer.(*syncBuffer).file != nil { 1306 path, err := filepath.Abs(buffer.(*syncBuffer).file.Name()) 1307 if err == nil { 1308 logs = append(logs, path) 1309 } 1310 } 1311 } 1312 return logs 1313 } 1314 1315 func extractTimestamp(logFile, prefix string) string { 1316 if len(logFile) <= len(prefix) { 1317 return "" 1318 } 1319 splits := strings.SplitN(logFile[len(prefix):], ".", 3) 1320 if len(splits) == 3 { 1321 return splits[1] 1322 } else { 1323 return "" 1324 } 1325 } 1326 1327 func filterLogFiles(files []os.FileInfo, prefix string) []os.FileInfo { 1328 filtered := files[:0] 1329 for _, file := range files { 1330 if !file.IsDir() && strings.HasPrefix(file.Name(), prefix) { 1331 filtered = append(filtered, file) 1332 } 1333 } 1334 return filtered 1335 } 1336 1337 func removeOutdated(logs []logFile, now time.Time) ([]logFile, error) { 1338 if MaxAge == 0 { 1339 return logs, nil 1340 } 1341 t := now.Add(-1 * MaxAge) 1342 timestamp := fmt.Sprintf("%04d%02d%02d-%02d%02d%02d", 1343 t.Year(), 1344 t.Month(), 1345 t.Day(), 1346 t.Hour(), 1347 t.Minute(), 1348 t.Second(), 1349 ) 1350 1351 remaining := logs[:0] 1352 for _, log := range logs { 1353 if log.timestamp <= timestamp { 1354 if err := os.Remove(filepath.Join(log.dir, log.name)); err != nil { 1355 return nil, err 1356 } 1357 } else { 1358 remaining = append(remaining, log) 1359 } 1360 } 1361 return remaining, nil 1362 } 1363 1364 // compress all uncompressed log files, except the currently used log file 1365 func compressOrphans(logs []logFile) ([]logFile, error) { 1366 for i, log := range logs { 1367 fullName := filepath.Join(log.dir, log.name) 1368 if !strings.HasSuffix(log.name, ".gz") { 1369 if err := gzipFile(fullName); err != nil { 1370 return nil, err 1371 } 1372 logs[i].name += ".gz" 1373 } 1374 } 1375 return logs, nil 1376 } 1377 1378 func getTotalSize(logs []logFile) (size uint64) { 1379 for _, log := range logs { 1380 size += log.size 1381 } 1382 return 1383 } 1384 1385 // bufferSize sizes the buffer associated with each log file. It's large 1386 // so that log records can accumulate without the logging thread blocking 1387 // on disk I/O. The flushDaemon will block instead. 1388 const bufferSize = 256 * 1024 1389 1390 // createFiles creates all the log files for severity from sev down to infoLog. 1391 // l.mu is held. 1392 func (l *loggingT) createFiles(sev severity) error { 1393 now := time.Now() 1394 // Files are created in decreasing severity order, so as soon as we find one 1395 // has already been created, we can stop. 1396 for s := sev; s >= infoLog && l.file[s] == nil; s-- { 1397 sb := &syncBuffer{ 1398 logger: l, 1399 sev: s, 1400 } 1401 if err := sb.rotateCurrent(now); err != nil { 1402 return err 1403 } 1404 l.file[s] = sb 1405 } 1406 return nil 1407 } 1408 1409 const flushInterval = 5 * time.Second 1410 1411 // flushDaemon periodically flushes the log file buffers. 1412 func (l *loggingT) flushDaemon() { 1413 for range time.NewTicker(flushInterval).C { 1414 l.lockAndFlushAll() 1415 } 1416 } 1417 1418 // lockAndFlushAll is like flushAll but locks l.mu first. 1419 func (l *loggingT) lockAndFlushAll() { 1420 l.mu.Lock() 1421 l.flushAll() 1422 l.mu.Unlock() 1423 } 1424 1425 // flushAll flushes all the logs and attempts to "sync" their data to disk. 1426 // l.mu is held. 1427 func (l *loggingT) flushAll() { 1428 // Flush from fatal down, in case there's trouble flushing. 1429 for s := fatalLog; s >= infoLog; s-- { 1430 file := l.file[s] 1431 if file != nil { 1432 // if e := file.Flush(); e != nil { 1433 // stdLog.Fatalln(e) 1434 // } 1435 // if e := file.Sync(); e != nil { 1436 // stdLog.Fatalln(e) 1437 // } 1438 file.Flush() // ignore error 1439 file.Sync() // ignore error 1440 } 1441 } 1442 } 1443 1444 // CopyStandardLogTo arranges for messages written to the Go "log" package's 1445 // default logs to also appear in the Google logs for the named and lower 1446 // severities. Subsequent changes to the standard log's default output location 1447 // or format may break this behavior. 1448 // 1449 // Valid names are "INFO", "WARNING", "ERROR", and "FATAL". If the name is not 1450 // recognized, CopyStandardLogTo panics. 1451 func CopyStandardLogTo(name string) { 1452 sev, ok := severityByName(name) 1453 if !ok { 1454 panic(fmt.Sprintf("log.CopyStandardLogTo(%q): unrecognized severity name", name)) 1455 } 1456 // Set a log format that captures the user's file and line: 1457 // d.go:23: message 1458 stdLog.SetFlags(stdLog.Lshortfile) 1459 stdLog.SetOutput(logBridge(sev)) 1460 } 1461 1462 // logBridge provides the Write method that enables CopyStandardLogTo to connect 1463 // Go's standard logs to the logs provided by this package. 1464 type logBridge severity 1465 1466 // Write parses the standard logging line and passes its components to the 1467 // logger for severity(lb). 1468 func (lb logBridge) Write(b []byte) (n int, err error) { 1469 var ( 1470 file = "???" 1471 line = 1 1472 text string 1473 ) 1474 // Split "d.go:23: message" into "d.go", "23", and "message". 1475 if parts := bytes.SplitN(b, []byte{':'}, 3); len(parts) != 3 || len(parts[0]) < 1 || len(parts[2]) < 1 { 1476 text = fmt.Sprintf("bad log format: %s", b) 1477 } else { 1478 file = string(parts[0]) 1479 text = string(parts[2][1:]) // skip leading space 1480 line, err = strconv.Atoi(string(parts[1])) 1481 if err != nil { 1482 text = fmt.Sprintf("bad line number: %s", b) 1483 line = 1 1484 } 1485 } 1486 // printWithFileLine with alsoToStderr=true, so standard log messages 1487 // always appear on standard error. 1488 1489 logging.printWithFileLine(severity(lb), file, line, true, text) 1490 return len(b), nil 1491 } 1492 1493 // setV computes and remembers the V level for a given PC 1494 // when vmodule is enabled. 1495 // File pattern matching takes the basename of the file, stripped 1496 // of its .go suffix, and uses filepath.Match, which is a little more 1497 // general than the *? matching used in C++. 1498 // l.mu is held. 1499 func (l *loggingT) setV(pc uintptr) Level { 1500 fn := runtime.FuncForPC(pc) 1501 file, _ := fn.FileLine(pc) 1502 file = trimToImportPath(file) 1503 for _, filter := range l.vmodule.filter { 1504 if filter.pattern.MatchString(file) { 1505 l.vmap[pc] = filter.level 1506 return filter.level 1507 } 1508 } 1509 l.vmap[pc] = 0 1510 return 0 1511 } 1512 1513 // Verbose is a boolean type that implements Infof (like Printf) etc. 1514 // See the documentation of V for more information. 1515 type Verbose bool 1516 type Displayable bool 1517 1518 // V reports whether verbosity at the call site is at least the requested level. 1519 // The returned value is a boolean of type Verbose, which implements Info, Infoln 1520 // and Infof. These methods will write to the Info log if called. 1521 // Thus, one may write either 1522 // if glog.V(2) { glog.Info("log this") } 1523 // or 1524 // glog.V(2).Info("log this") 1525 // The second form is shorter but the first is cheaper if logging is off because it does 1526 // not evaluate its arguments. 1527 // 1528 // Whether an individual call to V generates a log record depends on the setting of 1529 // the -v and --vmodule flags; both are off by default. If the level in the call to 1530 // V is at least the value of -v, or of -vmodule for the source file containing the 1531 // call, the V call will log. 1532 func V(level Level) Verbose { 1533 // This function tries hard to be cheap unless there's work to do. 1534 // The fast path is two atomic loads and compares. 1535 1536 // Here is a cheap but safe test to see if V logging is enabled globally. 1537 if logging.verbosity.get() >= level { 1538 return Verbose(true) 1539 } 1540 // It's off globally but it vmodule may still be set. 1541 // Here is another cheap but safe test to see if vmodule is enabled. 1542 if atomic.LoadInt32(&logging.filterLength) > 0 { 1543 // Now we need a proper lock to use the logging structure. The pcs field 1544 // is shared so we must lock before accessing it. This is fairly expensive, 1545 // but if V logging is enabled we're slow anyway. 1546 logging.mu.Lock() 1547 defer logging.mu.Unlock() 1548 if runtime.Callers(2, logging.pcs[:]) == 0 { 1549 return Verbose(false) 1550 } 1551 v, ok := logging.vmap[logging.pcs[0]] 1552 if !ok { 1553 v = logging.setV(logging.pcs[0]) 1554 } 1555 return Verbose(v >= level) 1556 } 1557 return Verbose(false) 1558 } 1559 1560 func D(level Level) Displayable { 1561 // This function tries hard to be cheap unless there's work to do. 1562 // The fast path is two atomic loads and compares. 1563 1564 // Here is a cheap but safe test to see if V logging is enabled globally. 1565 if display.verbosity.get() >= level { 1566 return Displayable(true) 1567 } 1568 // It's off globally but it vmodule may still be set. 1569 // Here is another cheap but safe test to see if vmodule is enabled. 1570 if atomic.LoadInt32(&display.filterLength) > 0 { 1571 // Now we need a proper lock to use the logging structure. The pcs field 1572 // is shared so we must lock before accessing it. This is fairly expensive, 1573 // but if V logging is enabled we're slow anyway. 1574 display.mu.Lock() 1575 defer display.mu.Unlock() 1576 if runtime.Callers(2, display.pcs[:]) == 0 { 1577 return Displayable(false) 1578 } 1579 v, ok := display.vmap[logging.pcs[0]] 1580 if !ok { 1581 v = display.setV(logging.pcs[0]) 1582 } 1583 return Displayable(v >= level) 1584 } 1585 return Displayable(false) 1586 } 1587 1588 func (d Displayable) Infoln(args ...interface{}) { 1589 if d { 1590 display.println(infoLog, args...) 1591 } 1592 } 1593 1594 func (d Displayable) Infof(format string, args ...interface{}) { 1595 if d { 1596 display.printfmt(infoLog, format, args...) 1597 } 1598 } 1599 1600 func (d Displayable) Warnln(args ...interface{}) { 1601 if d { 1602 display.println(warningLog, args...) 1603 } 1604 } 1605 1606 func (d Displayable) Warnf(format string, args ...interface{}) { 1607 if d { 1608 display.printfmt(warningLog, format, args...) 1609 } 1610 } 1611 1612 func (d Displayable) Errorln(args ...interface{}) { 1613 if d { 1614 display.println(errorLog, args...) 1615 } 1616 } 1617 1618 func (d Displayable) Errorf(format string, args ...interface{}) { 1619 if d { 1620 display.printfmt(errorLog, format, args...) 1621 } 1622 } 1623 1624 // INFO 1625 // Info is equivalent to the global Info function, guarded by the value of v. 1626 // See the documentation of V for usage. 1627 func (v Verbose) Info(args ...interface{}) { 1628 if v { 1629 logging.print(infoLog, args...) 1630 } 1631 } 1632 1633 // Infoln is equivalent to the global Infoln function, guarded by the value of v. 1634 // See the documentation of V for usage. 1635 func (v Verbose) Infoln(args ...interface{}) { 1636 if v { 1637 logging.println(infoLog, args...) 1638 } 1639 } 1640 1641 // Infof is equivalent to the global Infof function, guarded by the value of v. 1642 // See the documentation of V for usage. 1643 func (v Verbose) Infof(format string, args ...interface{}) { 1644 if v { 1645 logging.printfmt(infoLog, format, args...) 1646 } 1647 } 1648 1649 // WARN 1650 // Warn is equivalent to the global Warn function, guarded by the value of v. 1651 // See the documentation of V for usage. 1652 func (v Verbose) Warn(args ...interface{}) { 1653 if v { 1654 logging.print(warningLog, args...) 1655 } 1656 } 1657 1658 // Warnln is equivalent to the global Warnln function, guarded by the value of v. 1659 // See the documentation of V for usage. 1660 func (v Verbose) Warnln(args ...interface{}) { 1661 if v { 1662 logging.println(warningLog, args...) 1663 } 1664 } 1665 1666 // Warnf is equivalent to the global Warnf function, guarded by the value of v. 1667 // See the documentation of V for usage. 1668 func (v Verbose) Warnf(format string, args ...interface{}) { 1669 if v { 1670 logging.printfmt(warningLog, format, args...) 1671 } 1672 } 1673 1674 // ERROR 1675 // Error is equivalent to the global Error function, guarded by the value of v. 1676 // See the documentation of V for usage. 1677 func (v Verbose) Error(args ...interface{}) { 1678 if v { 1679 logging.print(errorLog, args...) 1680 } 1681 } 1682 1683 // Errorln is equivalent to the global Errorln function, guarded by the value of v. 1684 // See the documentation of V for usage. 1685 func (v Verbose) Errorln(args ...interface{}) { 1686 if v { 1687 logging.println(errorLog, args...) 1688 } 1689 } 1690 1691 // Errorf is equivalent to the global Errorf function, guarded by the value of v. 1692 // See the documentation of V for usage. 1693 func (v Verbose) Errorf(format string, args ...interface{}) { 1694 if v { 1695 logging.printfmt(errorLog, format, args...) 1696 } 1697 } 1698 1699 // Separator creates a line, ie --------------------------------- 1700 func Separator(iterable string) string { 1701 return strings.Repeat(iterable, 110) 1702 } 1703 1704 // Info logs to the INFO log. 1705 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1706 func Info(args ...interface{}) { 1707 logging.print(infoLog, args...) 1708 } 1709 1710 // InfoDepth acts as Info but uses depth to determine which call frame to log. 1711 // InfoDepth(0, "msg") is the same as Info("msg"). 1712 func InfoDepth(depth int, args ...interface{}) { 1713 logging.printDepth(infoLog, depth, args...) 1714 } 1715 1716 // Infoln logs to the INFO log. 1717 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1718 func Infoln(args ...interface{}) { 1719 logging.print(infoLog, args...) 1720 } 1721 1722 // Infof logs to the INFO log. 1723 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1724 func Infof(format string, args ...interface{}) { 1725 logging.printfmt(infoLog, format, args...) 1726 } 1727 1728 // Warning logs to the WARNING and INFO logs. 1729 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1730 func Warning(args ...interface{}) { 1731 logging.print(warningLog, args...) 1732 } 1733 1734 // WarningDepth acts as Warning but uses depth to determine which call frame to log. 1735 // WarningDepth(0, "msg") is the same as Warning("msg"). 1736 func WarningDepth(depth int, args ...interface{}) { 1737 logging.printDepth(warningLog, depth, args...) 1738 } 1739 1740 // Warningln logs to the WARNING and INFO logs. 1741 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1742 func Warningln(args ...interface{}) { 1743 logging.println(warningLog, args...) 1744 } 1745 1746 // Warningf logs to the WARNING and INFO logs. 1747 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1748 func Warningf(format string, args ...interface{}) { 1749 logging.printfmt(warningLog, format, args...) 1750 } 1751 1752 // Error logs to the ERROR, WARNING, and INFO logs. 1753 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1754 func Error(args ...interface{}) { 1755 logging.print(errorLog, args...) 1756 } 1757 1758 // ErrorDepth acts as Error but uses depth to determine which call frame to log. 1759 // ErrorDepth(0, "msg") is the same as Error("msg"). 1760 func ErrorDepth(depth int, args ...interface{}) { 1761 logging.printDepth(errorLog, depth, args...) 1762 } 1763 1764 // Errorln logs to the ERROR, WARNING, and INFO logs. 1765 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1766 func Errorln(args ...interface{}) { 1767 logging.println(errorLog, args...) 1768 } 1769 1770 // Errorf logs to the ERROR, WARNING, and INFO logs. 1771 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1772 func Errorf(format string, args ...interface{}) { 1773 logging.printfmt(errorLog, format, args...) 1774 } 1775 1776 // Fatal logs to the FATAL, ERROR, WARNING, and INFO logs, 1777 // including a stack trace of all running goroutines, then calls os.Exit(255). 1778 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1779 func Fatal(args ...interface{}) { 1780 logging.print(fatalLog, args...) 1781 } 1782 1783 // FatalDepth acts as Fatal but uses depth to determine which call frame to log. 1784 // FatalDepth(0, "msg") is the same as Fatal("msg"). 1785 func FatalDepth(depth int, args ...interface{}) { 1786 logging.printDepth(fatalLog, depth, args...) 1787 } 1788 1789 // Fatalln logs to the FATAL, ERROR, WARNING, and INFO logs, 1790 // including a stack trace of all running goroutines, then calls os.Exit(255). 1791 // Arguments are handled in the manner of fmt.Println; a newline is appended if missing. 1792 func Fatalln(args ...interface{}) { 1793 logging.println(fatalLog, args...) 1794 } 1795 1796 // Fatalf logs to the FATAL, ERROR, WARNING, and INFO logs, 1797 // including a stack trace of all running goroutines, then calls os.Exit(255). 1798 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1799 func Fatalf(format string, args ...interface{}) { 1800 logging.printfmt(fatalLog, format, args...) 1801 } 1802 1803 // fatalNoStacks is non-zero if we are to exit without dumping goroutine stacks. 1804 // It allows Exit and relatives to use the Fatal logs. 1805 var fatalNoStacks uint32 1806 1807 // Exit logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). 1808 // Arguments are handled in the manner of fmt.Print; a newline is appended if missing. 1809 func Exit(args ...interface{}) { 1810 atomic.StoreUint32(&fatalNoStacks, 1) 1811 logging.print(fatalLog, args...) 1812 } 1813 1814 // ExitDepth acts as Exit but uses depth to determine which call frame to log. 1815 // ExitDepth(0, "msg") is the same as Exit("msg"). 1816 func ExitDepth(depth int, args ...interface{}) { 1817 atomic.StoreUint32(&fatalNoStacks, 1) 1818 logging.printDepth(fatalLog, depth, args...) 1819 } 1820 1821 // Exitln logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). 1822 func Exitln(args ...interface{}) { 1823 atomic.StoreUint32(&fatalNoStacks, 1) 1824 logging.println(fatalLog, args...) 1825 } 1826 1827 // Exitf logs to the FATAL, ERROR, WARNING, and INFO logs, then calls os.Exit(1). 1828 // Arguments are handled in the manner of fmt.Printf; a newline is appended if missing. 1829 func Exitf(format string, args ...interface{}) { 1830 atomic.StoreUint32(&fatalNoStacks, 1) 1831 logging.printfmt(fatalLog, format, args...) 1832 }