Fix file logging; support for unbuffered logging
@@ -20,6 +20,7 @@ import (
"io"
"os"
"runtime/debug"
+ "strings"
"time"
"github.com/inconshreveable/log15"
@@ -67,6 +68,15 @@ func SetupFromFlags(name string) error {
return err
}
+// SetupLogFile initializes a file for logging. The path is logDir/name.log if
+// name doesn't already contain the .log extension, or logDir/name otherwise.
+// logLevel can be one of debug, info, warn, error, and crit and states the
+// minimum level of logging events that get written to the file. logSize is the
+// maximum size, in MiB, until the log rotates. logAge is the maximum number of
+// days to retain old log files. If logFlush > 0, logging output is buffered,
+// and flushed every logFlush seconds. If logFlush < 0: logging output is
+// buffered, but must be manually flushed by calling Flush(). If logFlush = 0
+// logging output is unbuffered and Flush() is a no-op.
func SetupLogFile(name string, logDir string, logLevel string, logSize int, logAge int,
logFlush int) error {
@@ -74,15 +84,34 @@ func SetupLogFile(name string, logDir string, logLevel string, logSize int, logA
if err != nil {
return common.NewBasicError("Unable to parse log.level flag:", err)
}
- logBuf = newSyncBuf(mkLogfile(name))
+
+ // Strip .log extension s.t. config files can contain the exact filename
+ // while not breaking existing behavior for apps that don't contain the
+ // extension.
+ name = strings.TrimSuffix(name, ".log")
+ var fileLogger io.WriteCloser
+ fileLogger = &lumberjack.Logger{
+ Filename: fmt.Sprintf("%s/%s.log", logDir, name),
+ MaxSize: logSize, // MiB
+ MaxAge: logAge, // days
+ }
+
+ if logFlush != 0 {
+ logBuf = newSyncBuf(fileLogger)
+ fileLogger = logBuf
+ }
+
logFileHandler = log15.LvlFilterHandler(logLvl,
- log15.StreamHandler(logBuf, fmt15.Fmt15Format(nil)))
+ log15.StreamHandler(fileLogger, fmt15.Fmt15Format(nil)))
setHandlers()
+
+ if logFlush > 0 {
go func() {
for range time.Tick(time.Duration(logFlush) * time.Second) {
Flush()
}
}()
+ }
return nil
}
@@ -124,14 +153,6 @@ func AddLogFileFlags() {
flag.IntVar(&logFlush, "log.flush", 5, "How frequently to flush to the log file, in seconds")
}
-func mkLogfile(name string) io.WriteCloser {
- return &lumberjack.Logger{
- Filename: fmt.Sprintf("%s/%s.log", logDir, name),
- MaxSize: logSize, // MiB
- MaxAge: logAge, // days
- }
-}
-
func LogPanicAndExit() {
if msg := recover(); msg != nil {
log15.Crit("Panic", "msg", msg, "stack", string(debug.Stack()))
@@ -141,8 +162,10 @@ func LogPanicAndExit() {
}
func Flush() {
+ if logBuf != nil {
logBuf.Flush()
}
+}
func New(ctx ...interface{}) Logger {
return log15.New(ctx...)
