|
@@ -93,27 +93,29 @@ import (
|
|
|
// should be modified only through the flag.Value interface. The values match
|
|
|
// the corresponding constants in C++.
|
|
|
type severity int32 // sync/atomic int32
|
|
|
+var outputSeverity severity
|
|
|
|
|
|
// These constants identify the log levels in order of increasing severity.
|
|
|
// A message written to a high-severity log file is also written to each
|
|
|
// lower-severity log file.
|
|
|
const (
|
|
|
- infoLog severity = iota
|
|
|
- warningLog
|
|
|
+ debugLog severity = iota
|
|
|
+ infoLog
|
|
|
errorLog
|
|
|
fatalLog
|
|
|
- numSeverity = 4
|
|
|
+ numSeverity = 5
|
|
|
)
|
|
|
|
|
|
-const severityChar = "IWEF"
|
|
|
+const severityChar = "DIEF"
|
|
|
|
|
|
var severityName = []string{
|
|
|
- infoLog: "INFO",
|
|
|
- warningLog: "WARNING",
|
|
|
- errorLog: "ERROR",
|
|
|
- fatalLog: "FATAL",
|
|
|
+ debugLog: "DEBUG",
|
|
|
+ infoLog: "INFO",
|
|
|
+ errorLog: "ERROR",
|
|
|
+ fatalLog: "FATAL",
|
|
|
}
|
|
|
|
|
|
+//测试tag
|
|
|
// get returns the value of the severity.
|
|
|
func (s *severity) get() severity {
|
|
|
return severity(atomic.LoadInt32((*int32)(s)))
|
|
@@ -161,6 +163,14 @@ func severityByName(s string) (severity, bool) {
|
|
|
return 0, false
|
|
|
}
|
|
|
|
|
|
+func SetLevelString(outputLevel string) {
|
|
|
+ severity, ok := severityByName(outputLevel)
|
|
|
+ if !ok {
|
|
|
+ panic(fmt.Errorf("cannot find severity name %s", outputLevel))
|
|
|
+ }
|
|
|
+ outputSeverity = severity
|
|
|
+}
|
|
|
+
|
|
|
// OutputStats tracks the number of output lines and bytes written.
|
|
|
type OutputStats struct {
|
|
|
lines int64
|
|
@@ -180,13 +190,13 @@ func (s *OutputStats) Bytes() int64 {
|
|
|
// Stats tracks the number of lines of output and number of bytes
|
|
|
// per severity level. Values must be read with atomic.LoadInt64.
|
|
|
var Stats struct {
|
|
|
- Info, Warning, Error OutputStats
|
|
|
+ Debug, Info, Error OutputStats
|
|
|
}
|
|
|
|
|
|
var severityStats = [numSeverity]*OutputStats{
|
|
|
- infoLog: &Stats.Info,
|
|
|
- warningLog: &Stats.Warning,
|
|
|
- errorLog: &Stats.Error,
|
|
|
+ debugLog: &Stats.Debug,
|
|
|
+ infoLog: &Stats.Info,
|
|
|
+ errorLog: &Stats.Error,
|
|
|
}
|
|
|
|
|
|
// Level is exported because it appears in the arguments to V and is
|
|
@@ -397,6 +407,7 @@ type flushSyncWriter interface {
|
|
|
|
|
|
func init() {
|
|
|
flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files")
|
|
|
+ flag.BoolVar(&logging.dailyRolling, "dailyRolling", false, " weather to handle log files daily")
|
|
|
flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files")
|
|
|
flag.Var(&logging.verbosity, "v", "log level for V logs")
|
|
|
flag.Var(&logging.stderrThreshold, "stderrthreshold", "logs at or above this threshold go to stderr")
|
|
@@ -406,6 +417,9 @@ func init() {
|
|
|
// Default stderrThreshold is ERROR.
|
|
|
logging.stderrThreshold = errorLog
|
|
|
|
|
|
+ //Default outputSeverity is INFO.
|
|
|
+ outputSeverity = infoLog
|
|
|
+
|
|
|
logging.setVState(0, nil, false)
|
|
|
go logging.flushDaemon()
|
|
|
}
|
|
@@ -423,6 +437,8 @@ type loggingT struct {
|
|
|
toStderr bool // The -logtostderr flag.
|
|
|
alsoToStderr bool // The -alsologtostderr flag.
|
|
|
|
|
|
+ dailyRolling bool
|
|
|
+
|
|
|
// Level flag. Handled atomically.
|
|
|
stderrThreshold severity // The -stderrthreshold flag.
|
|
|
|
|
@@ -628,6 +644,9 @@ func (buf *buffer) someDigits(i, d int) int {
|
|
|
}
|
|
|
|
|
|
func (l *loggingT) println(s severity, args ...interface{}) {
|
|
|
+ if s < outputSeverity {
|
|
|
+ return
|
|
|
+ }
|
|
|
buf, file, line := l.header(s, 0)
|
|
|
fmt.Fprintln(buf, args...)
|
|
|
l.output(s, buf, file, line, false)
|
|
@@ -638,6 +657,9 @@ func (l *loggingT) print(s severity, args ...interface{}) {
|
|
|
}
|
|
|
|
|
|
func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) {
|
|
|
+ if s < outputSeverity {
|
|
|
+ return
|
|
|
+ }
|
|
|
buf, file, line := l.header(s, depth)
|
|
|
fmt.Fprint(buf, args...)
|
|
|
if buf.Bytes()[buf.Len()-1] != '\n' {
|
|
@@ -647,6 +669,9 @@ func (l *loggingT) printDepth(s severity, depth int, args ...interface{}) {
|
|
|
}
|
|
|
|
|
|
func (l *loggingT) printf(s severity, format string, args ...interface{}) {
|
|
|
+ if s < outputSeverity {
|
|
|
+ return
|
|
|
+ }
|
|
|
buf, file, line := l.header(s, 0)
|
|
|
fmt.Fprintf(buf, format, args...)
|
|
|
if buf.Bytes()[buf.Len()-1] != '\n' {
|
|
@@ -659,6 +684,9 @@ func (l *loggingT) printf(s severity, format string, args ...interface{}) {
|
|
|
// alsoLogToStderr is true, the log message always appears on standard error; it
|
|
|
// will also appear in the log file unless --logtostderr is set.
|
|
|
func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStderr bool, args ...interface{}) {
|
|
|
+ if s < outputSeverity {
|
|
|
+ return
|
|
|
+ }
|
|
|
buf := l.formatHeader(s, file, line)
|
|
|
fmt.Fprint(buf, args...)
|
|
|
if buf.Bytes()[buf.Len()-1] != '\n' {
|
|
@@ -698,11 +726,11 @@ func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoTo
|
|
|
case errorLog:
|
|
|
l.file[errorLog].Write(data)
|
|
|
fallthrough
|
|
|
- case warningLog:
|
|
|
- l.file[warningLog].Write(data)
|
|
|
- fallthrough
|
|
|
case infoLog:
|
|
|
l.file[infoLog].Write(data)
|
|
|
+ fallthrough
|
|
|
+ case debugLog:
|
|
|
+ l.file[debugLog].Write(data)
|
|
|
}
|
|
|
}
|
|
|
if s == fatalLog {
|
|
@@ -722,7 +750,7 @@ func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoTo
|
|
|
// Write the stack trace for all goroutines to the files.
|
|
|
trace := stacks(true)
|
|
|
logExitFunc = func(error) {} // If we get a write error, we'll still exit below.
|
|
|
- for log := fatalLog; log >= infoLog; log-- {
|
|
|
+ for log := fatalLog; log >= debugLog; log-- {
|
|
|
if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set.
|
|
|
f.Write(trace)
|
|
|
}
|
|
@@ -802,9 +830,10 @@ func (l *loggingT) exit(err error) {
|
|
|
type syncBuffer struct {
|
|
|
logger *loggingT
|
|
|
*bufio.Writer
|
|
|
- file *os.File
|
|
|
- sev severity
|
|
|
- nbytes uint64 // The number of bytes written to this file
|
|
|
+ file *os.File
|
|
|
+ sev severity
|
|
|
+ nbytes uint64 // The number of bytes written to this file
|
|
|
+ createdDate string
|
|
|
}
|
|
|
|
|
|
func (sb *syncBuffer) Sync() error {
|
|
@@ -812,6 +841,14 @@ func (sb *syncBuffer) Sync() error {
|
|
|
}
|
|
|
|
|
|
func (sb *syncBuffer) Write(p []byte) (n int, err error) {
|
|
|
+ if logging.dailyRolling {
|
|
|
+ if sb.createdDate != string(p[1:5]) {
|
|
|
+ if err := sb.rotateFile(time.Now()); err != nil {
|
|
|
+ sb.logger.exit(err)
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if sb.nbytes+uint64(len(p)) >= MaxSize {
|
|
|
if err := sb.rotateFile(time.Now()); err != nil {
|
|
|
sb.logger.exit(err)
|
|
@@ -839,13 +876,15 @@ func (sb *syncBuffer) rotateFile(now time.Time) error {
|
|
|
}
|
|
|
|
|
|
sb.Writer = bufio.NewWriterSize(sb.file, bufferSize)
|
|
|
+ _, month, day := now.Date()
|
|
|
+ sb.createdDate = fmt.Sprintf("%02d%02d", month, day)
|
|
|
|
|
|
// Write header.
|
|
|
var buf bytes.Buffer
|
|
|
fmt.Fprintf(&buf, "Log file created at: %s\n", now.Format("2006/01/02 15:04:05"))
|
|
|
fmt.Fprintf(&buf, "Running on machine: %s\n", host)
|
|
|
fmt.Fprintf(&buf, "Binary: Built with %s %s for %s/%s\n", runtime.Compiler, runtime.Version(), runtime.GOOS, runtime.GOARCH)
|
|
|
- fmt.Fprintf(&buf, "Log line format: [IWEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
|
|
|
+ fmt.Fprintf(&buf, "Log line format: [DIEF]mmdd hh:mm:ss.uuuuuu threadid file:line] msg\n")
|
|
|
n, err := sb.file.Write(buf.Bytes())
|
|
|
sb.nbytes += uint64(n)
|
|
|
return err
|
|
@@ -862,7 +901,7 @@ func (l *loggingT) createFiles(sev severity) error {
|
|
|
now := time.Now()
|
|
|
// Files are created in decreasing severity order, so as soon as we find one
|
|
|
// has already been created, we can stop.
|
|
|
- for s := sev; s >= infoLog && l.file[s] == nil; s-- {
|
|
|
+ for s := sev; s >= debugLog && l.file[s] == nil; s-- {
|
|
|
sb := &syncBuffer{
|
|
|
logger: l,
|
|
|
sev: s,
|
|
@@ -875,7 +914,7 @@ func (l *loggingT) createFiles(sev severity) error {
|
|
|
return nil
|
|
|
}
|
|
|
|
|
|
-const flushInterval = 30 * time.Second
|
|
|
+var flushInterval time.Duration = 5 * time.Second
|
|
|
|
|
|
// flushDaemon periodically flushes the log file buffers.
|
|
|
func (l *loggingT) flushDaemon() {
|
|
@@ -895,7 +934,7 @@ func (l *loggingT) lockAndFlushAll() {
|
|
|
// l.mu is held.
|
|
|
func (l *loggingT) flushAll() {
|
|
|
// Flush from fatal down, in case there's trouble flushing.
|
|
|
- for s := fatalLog; s >= infoLog; s-- {
|
|
|
+ for s := fatalLog; s >= debugLog; s-- {
|
|
|
file := l.file[s]
|
|
|
if file != nil {
|
|
|
file.Flush() // ignore error
|
|
@@ -1049,6 +1088,22 @@ func (v Verbose) Infof(format string, args ...interface{}) {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+func Debug(args ...interface{}) {
|
|
|
+ logging.print(debugLog, args...)
|
|
|
+}
|
|
|
+
|
|
|
+func DebugDepth(depth int, args ...interface{}) {
|
|
|
+ logging.printDepth(debugLog, depth, args...)
|
|
|
+}
|
|
|
+
|
|
|
+func Debugln(args ...interface{}) {
|
|
|
+ logging.println(debugLog, args...)
|
|
|
+}
|
|
|
+
|
|
|
+func Debugf(format string, args ...interface{}) {
|
|
|
+ logging.printf(debugLog, format, args...)
|
|
|
+}
|
|
|
+
|
|
|
// Info logs to the INFO log.
|
|
|
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
|
|
|
func Info(args ...interface{}) {
|
|
@@ -1073,30 +1128,6 @@ func Infof(format string, args ...interface{}) {
|
|
|
logging.printf(infoLog, format, args...)
|
|
|
}
|
|
|
|
|
|
-// Warning logs to the WARNING and INFO logs.
|
|
|
-// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
|
|
|
-func Warning(args ...interface{}) {
|
|
|
- logging.print(warningLog, args...)
|
|
|
-}
|
|
|
-
|
|
|
-// WarningDepth acts as Warning but uses depth to determine which call frame to log.
|
|
|
-// WarningDepth(0, "msg") is the same as Warning("msg").
|
|
|
-func WarningDepth(depth int, args ...interface{}) {
|
|
|
- logging.printDepth(warningLog, depth, args...)
|
|
|
-}
|
|
|
-
|
|
|
-// Warningln logs to the WARNING and INFO logs.
|
|
|
-// Arguments are handled in the manner of fmt.Println; a newline is appended if missing.
|
|
|
-func Warningln(args ...interface{}) {
|
|
|
- logging.println(warningLog, args...)
|
|
|
-}
|
|
|
-
|
|
|
-// Warningf logs to the WARNING and INFO logs.
|
|
|
-// Arguments are handled in the manner of fmt.Printf; a newline is appended if missing.
|
|
|
-func Warningf(format string, args ...interface{}) {
|
|
|
- logging.printf(warningLog, format, args...)
|
|
|
-}
|
|
|
-
|
|
|
// Error logs to the ERROR, WARNING, and INFO logs.
|
|
|
// Arguments are handled in the manner of fmt.Print; a newline is appended if missing.
|
|
|
func Error(args ...interface{}) {
|