From bcf99c2ee909a18085e40602f10ed2ae48cd40c3 Mon Sep 17 00:00:00 2001 From: Firescar96 Date: Fri, 3 Jun 2016 03:07:13 -0400 Subject: [PATCH] Update to reinstate logfile flag Fix log to stdout instead of stderr update files to use new stdout function Add a flag to toggle logging to temp files instead of stdout --- cmd/bootnode/main.go | 2 +- cmd/ethtest/main.go | 2 +- cmd/evm/main.go | 2 +- cmd/gethrpctest/main.go | 2 +- eth/protocol_test.go | 2 +- internal/debug/flags.go | 19 +++++++++- logger/glog/glog.go | 79 +++++++++++++++++++++++----------------- logger/glog/glog_test.go | 2 +- logger/loggers.go | 29 +++++++++++++++ p2p/server_test.go | 2 +- 10 files changed, 98 insertions(+), 43 deletions(-) diff --git a/cmd/bootnode/main.go b/cmd/bootnode/main.go index 7d3f9fdb3f..411ddadecc 100644 --- a/cmd/bootnode/main.go +++ b/cmd/bootnode/main.go @@ -42,7 +42,7 @@ func main() { ) flag.Var(glog.GetVerbosity(), "verbosity", "log verbosity (0-9)") flag.Var(glog.GetVModule(), "vmodule", "log verbosity pattern") - glog.SetToStderr(true) + glog.SetToStdout(true) flag.Parse() if *genKey != "" { diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go index d8f9696360..dc5f1a035a 100644 --- a/cmd/ethtest/main.go +++ b/cmd/ethtest/main.go @@ -201,7 +201,7 @@ func setupApp(c *cli.Context) { } func main() { - glog.SetToStderr(true) + glog.SetToStdout(true) app := cli.NewApp() app.Name = "ethtest" diff --git a/cmd/evm/main.go b/cmd/evm/main.go index 7d9b3a6c33..a1094cdbc6 100644 --- a/cmd/evm/main.go +++ b/cmd/evm/main.go @@ -105,7 +105,7 @@ func init() { } func run(ctx *cli.Context) { - glog.SetToStderr(true) + glog.SetToStdout(true) glog.SetV(ctx.GlobalInt(VerbosityFlag.Name)) db, _ := ethdb.NewMemDatabase() diff --git a/cmd/gethrpctest/main.go b/cmd/gethrpctest/main.go index 2e07e94260..c9cf981e54 100644 --- a/cmd/gethrpctest/main.go +++ b/cmd/gethrpctest/main.go @@ -50,7 +50,7 @@ func main() { // Enable logging errors, we really do want to see those glog.SetV(2) - glog.SetToStderr(true) + glog.SetToStdout(true) // Load the test suite to run the RPC against tests, err := tests.LoadBlockTests(*testFile) diff --git a/eth/protocol_test.go b/eth/protocol_test.go index 0a82e2e795..5e2261f0e8 100644 --- a/eth/protocol_test.go +++ b/eth/protocol_test.go @@ -30,7 +30,7 @@ import ( ) func init() { - // glog.SetToStderr(true) + // glog.SetToStdout(true) // glog.SetV(6) } diff --git a/internal/debug/flags.go b/internal/debug/flags.go index 5b1a9b23c4..1f07486559 100644 --- a/internal/debug/flags.go +++ b/internal/debug/flags.go @@ -38,6 +38,15 @@ var ( Usage: "Per-module verbosity: comma-separated list of = (e.g. eth/*=6,p2p=5)", Value: glog.GetVModule(), } + logFileFlag = cli.StringFlag{ + Name: "logfile", + Usage: "Log output to this file (default = no log file generated)", + Value: "", + } + templogFileFlag = cli.BoolFlag{ + Name: "templog", + Usage: "Disables console output and sends output to timestamped files in the OS temp directory on an interval", + } backtraceAtFlag = cli.GenericFlag{ Name: "backtrace", Usage: "Request a stack trace at a specific logging statement (e.g. \"block.go:271\")", @@ -73,7 +82,7 @@ var ( // Flags holds all command-line flags required for debugging. var Flags = []cli.Flag{ - verbosityFlag, vmoduleFlag, backtraceAtFlag, + verbosityFlag, vmoduleFlag, logFileFlag, templogFileFlag, backtraceAtFlag, pprofFlag, pprofPortFlag, memprofilerateFlag, blockprofilerateFlag, cpuprofileFlag, traceFlag, } @@ -83,7 +92,7 @@ var Flags = []cli.Flag{ func Setup(ctx *cli.Context) error { // logging glog.CopyStandardLogTo("INFO") - glog.SetToStderr(true) + glog.SetToStdout(!ctx.GlobalIsSet(templogFileFlag.Name)) // profiling, tracing runtime.MemProfileRate = ctx.GlobalInt(memprofilerateFlag.Name) @@ -107,6 +116,12 @@ func Setup(ctx *cli.Context) error { glog.Errorln(http.ListenAndServe(address, nil)) }() } + + //glog.SetV(ctx.GlobalInt(verbosityFlag.Name)) + if ctx.GlobalIsSet(logFileFlag.Name) { + logger.New("", ctx.GlobalString(logFileFlag.Name), ctx.GlobalInt(verbosityFlag.Name)) + } + return nil } diff --git a/logger/glog/glog.go b/logger/glog/glog.go index edaa21f075..9daf7318a1 100644 --- a/logger/glog/glog.go +++ b/logger/glog/glog.go @@ -39,11 +39,11 @@ // This package provides several flags that modify this behavior. // As a result, flag.Parse must be called before any logging is done. // -// -logtostderr=false +// -logtostdout=false // Logs are written to standard error instead of to files. -// -alsologtostderr=false +// -alsologtostdout=false // Logs are written to standard error as well as to files. -// -stderrthreshold=ERROR +// -stdoutthreshold=ERROR // Log events at or above this severity are logged to standard // error as well as to files. // -log_dir="" @@ -91,10 +91,12 @@ import ( "sync" "sync/atomic" "time" + + "github.com/ethereum/go-ethereum/logger" ) // severity identifies the sort of log: info, warning etc. It also implements -// the flag.Value interface. The -stderrthreshold flag is of type severity and +// the flag.Value interface. The -stdoutthreshold flag is of type severity and // should be modified only through the flag.Value interface. The values match // the corresponding constants in C++. type severity int32 // sync/atomic int32 @@ -138,10 +140,10 @@ func SetV(v int) { logging.verbosity.set(Level(v)) } -// SetToStderr sets the global output style -func SetToStderr(toStderr bool) { +// SetToStdout sets the global output style +func SetToStdout(toStdout bool) { logging.mu.Lock() - logging.toStderr = toStderr + logging.toStdout = toStdout logging.mu.Unlock() } @@ -193,7 +195,7 @@ func (s *severity) Set(value string) error { } threshold = severity(v) } - logging.stderrThreshold.set(threshold) + logging.stdoutThreshold.set(threshold) return nil } @@ -365,7 +367,7 @@ func compileModulePattern(pat string) (*regexp.Regexp, error) { return regexp.Compile(re + "$") } -// traceLocation represents the setting of the -log_backtrace_at flag. +// TraceLocation represents the setting of the -log_backtrace_at flag. type TraceLocation struct { file string line int @@ -405,7 +407,7 @@ func (t *TraceLocation) Get() interface{} { var errTraceSyntax = errors.New("syntax error: expect file.go:234") -// Syntax: -log_backtrace_at=gopherflakes.go:234 +// Set syntax: -log_backtrace_at=gopherflakes.go:234 // Note that unlike vmodule the file extension is included here. func (t *TraceLocation) Set(value string) error { if value == "" { @@ -447,15 +449,15 @@ type flushSyncWriter interface { } func init() { - //flag.BoolVar(&logging.toStderr, "logtostderr", false, "log to standard error instead of files") - //flag.BoolVar(&logging.alsoToStderr, "alsologtostderr", false, "log to standard error as well as files") + //flag.BoolVar(&logging.toStdout, "logtostdout", false, "log to standard error instead of files") + //flag.BoolVar(&logging.alsoToStdout, "alsologtostdout", 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") + //flag.Var(&logging.stdoutThreshold, "stdoutthreshold", "logs at or above this threshold go to stdout") //flag.Var(&logging.vmodule, "vmodule", "comma-separated list of pattern=N settings for file-filtered logging") //flag.Var(&logging.traceLocation, "log_backtrace_at", "when logging hits line file:N, emit a stack trace") - // Default stderrThreshold is ERROR. - logging.stderrThreshold = errorLog + // Default stdoutThreshold is ERROR. + logging.stdoutThreshold = errorLog logging.setVState(3, nil, false) go logging.flushDaemon() } @@ -470,11 +472,11 @@ type loggingT struct { // Boolean flags. Not handled atomically because the flag.Value interface // does not let us avoid the =true, and that shorthand is necessary for // compatibility. TODO: does this matter enough to fix? Seems unlikely. - toStderr bool // The -logtostderr flag. - alsoToStderr bool // The -alsologtostderr flag. + toStdout bool // The -logtostdout flag. + alsoToStdout bool // The -alsologtostdout flag. // Level flag. Handled atomically. - stderrThreshold severity // The -stderrthreshold flag. + stdoutThreshold severity // The -stdoutthreshold flag. // freeList is a list of byte buffers, maintained under freeListMu. freeList *buffer @@ -486,8 +488,10 @@ type loggingT struct { // mu protects the remaining elements of this structure and is // used to synchronize logging. mu sync.Mutex - // file holds writer for each of the log types. + // file holds the temp directory writer for each of the log types. file [numSeverity]flushSyncWriter + // generalLogger holds the logging listeners for each of the log types + generalLogger [numSeverity]*logger.Logger // pcs is used in V to avoid an allocation when computing the caller's PC. pcs [1]uintptr // vmap is a cache of the V Level for each V() call site, identified by PC. @@ -709,30 +713,37 @@ func (l *loggingT) printfmt(s severity, format string, args ...interface{}) { // printWithFileLine behaves like print but uses the provided file and line number. If // 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{}) { +// will also appear in the log file unless --logtostdout is set. +func (l *loggingT) printWithFileLine(s severity, file string, line int, alsoToStdout bool, args ...interface{}) { buf := l.formatHeader(s, file, line) fmt.Fprint(buf, args...) if buf.Bytes()[buf.Len()-1] != '\n' { buf.WriteByte('\n') } - l.output(s, buf, file, line, alsoToStderr) + l.output(s, buf, file, line, alsoToStdout) } // output writes the data to the log files and releases the buffer. -func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStderr bool) { +func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoToStdout bool) { l.mu.Lock() if l.traceLocation.isSet() { if l.traceLocation.match(file, line) { buf.Write(stacks(false)) } } + data := buf.Bytes() - if l.toStderr { - os.Stderr.Write(data) + + if l.generalLogger[s] == nil { + l.generalLogger[s] = logger.NewLogger(severityName[s]) + } + l.generalLogger[s].Info(string(data)) + + if l.toStdout { + os.Stdout.Write(data) } else { - if alsoToStderr || l.alsoToStderr || s >= l.stderrThreshold.get() { - os.Stderr.Write(data) + if alsoToStdout || l.alsoToStdout || s >= l.stdoutThreshold.get() { + os.Stdout.Write(data) } if l.file[s] == nil { if err := l.createFiles(s); err != nil { @@ -740,6 +751,7 @@ func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoTo l.exit(err) } } + switch s { case fatalLog: l.file[fatalLog].Write(data) @@ -763,16 +775,13 @@ func (l *loggingT) output(s severity, buf *buffer, file string, line int, alsoTo } // Dump all goroutine stacks before exiting. // First, make sure we see the trace for the current goroutine on standard error. - // If -logtostderr has been specified, the loop below will do that anyway - // as the first stack in the full dump. - if !l.toStderr { - os.Stderr.Write(stacks(false)) - } + + os.Stderr.Write(stacks(false)) // 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-- { - if f := l.file[log]; f != nil { // Can be nil if -logtostderr is set. + if f := l.file[log]; f != nil { // Can be nil if -logtostdout is set. f.Write(trace) } } @@ -835,6 +844,8 @@ var logExitFunc func(error) // l.mu is held. func (l *loggingT) exit(err error) { fmt.Fprintf(os.Stderr, "log: exiting because of error: %s\n", err) + logger := logger.NewLogger("Exit") + logger.Errorf("log: exiting because of error: %s\n", err) // If logExitFunc is set, we do that instead of exiting. if logExitFunc != nil { logExitFunc(err) @@ -995,7 +1006,7 @@ func (lb logBridge) Write(b []byte) (n int, err error) { line = 1 } } - // printWithFileLine with alsoToStderr=true, so standard log messages + // printWithFileLine with alsoToStdout=true, so standard log messages // always appear on standard error. logging.printWithFileLine(severity(lb), file, line, true, text) return len(b), nil diff --git a/logger/glog/glog_test.go b/logger/glog/glog_test.go index b58f3d6426..2ef63a51ee 100644 --- a/logger/glog/glog_test.go +++ b/logger/glog/glog_test.go @@ -82,7 +82,7 @@ func contains(s severity, str string, t *testing.T) bool { // setFlags configures the logging flags how the test expects them. func setFlags() { - logging.toStderr = false + logging.toStdout = false } // Test that Info works as advertised. diff --git a/logger/loggers.go b/logger/loggers.go index e63355d0bf..df298d9057 100644 --- a/logger/loggers.go +++ b/logger/loggers.go @@ -57,6 +57,10 @@ func NewLogger(tag string) *Logger { return &Logger{"[" + tag + "] "} } +func (logger *Logger) Send(level LogLevel, v ...interface{}) { + logMessageC <- stdMsg{level, logger.tag + fmt.Sprint(v...)} +} + func (logger *Logger) Sendln(level LogLevel, v ...interface{}) { logMessageC <- stdMsg{level, logger.tag + fmt.Sprintln(v...)} } @@ -65,6 +69,31 @@ func (logger *Logger) Sendf(level LogLevel, format string, v ...interface{}) { logMessageC <- stdMsg{level, logger.tag + fmt.Sprintf(format, v...)} } +// Error writes a message with ErrorLevel. +func (logger *Logger) Error(v ...interface{}) { + logger.Send(ErrorLevel, v...) +} + +// Warn writes a message with WarnLevel. +func (logger *Logger) Warn(v ...interface{}) { + logger.Send(WarnLevel, v...) +} + +// Info writes a message with InfoLevel. +func (logger *Logger) Info(v ...interface{}) { + logger.Send(InfoLevel, v...) +} + +// Debug writes a message with DebugLevel. +func (logger *Logger) Debug(v ...interface{}) { + logger.Send(DebugLevel, v...) +} + +// DebugDetail writes a message with DebugDetailLevel. +func (logger *Logger) DebugDetail(v ...interface{}) { + logger.Send(DebugDetailLevel, v...) +} + // Errorln writes a message with ErrorLevel. func (logger *Logger) Errorln(v ...interface{}) { logger.Sendln(ErrorLevel, v...) diff --git a/p2p/server_test.go b/p2p/server_test.go index deb34f5bb1..d59222bdab 100644 --- a/p2p/server_test.go +++ b/p2p/server_test.go @@ -32,7 +32,7 @@ import ( func init() { // glog.SetV(6) - // glog.SetToStderr(true) + // glog.SetToStdout(true) } type testTransport struct {