Commit 6a024821 authored by ZhangGuangxu's avatar ZhangGuangxu Committed by Andrei Mihu
Browse files

Log file rotation. (#258)

parent 85467ff8
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -646,6 +646,14 @@
  revision = "c87af80f3cc5036b55b83d77171e156791085e2e"
  version = "v1.7.1"

[[projects]]
  digest = "1:11c58e19ff7ce22740423bb933f1ddca3bf575def40d5ac3437ec12871b1648b"
  name = "gopkg.in/natefinch/lumberjack.v2"
  packages = ["."]
  pruneopts = ""
  revision = "a96e63847dc3c67d17befa69c303767e2f84e54f"
  version = "v2.1"

[solve-meta]
  analyzer-name = "dep"
  analyzer-version = 1
@@ -697,6 +705,7 @@
    "google.golang.org/grpc/metadata",
    "google.golang.org/grpc/peer",
    "google.golang.org/grpc/status",
    "gopkg.in/natefinch/lumberjack.v2",
  ]
  solver-name = "gps-cdcl"
  solver-version = 1
+4 −0
Original line number Diff line number Diff line
@@ -73,3 +73,7 @@
[[constraint]]
  name = "github.com/blevesearch/bleve"
  revision = "89a815df0798b34feb44e4d3ade3c3a9d338aa63"

[[constraint]]
  name = "gopkg.in/natefinch/lumberjack.v2"
  version = "2.1.0"
+19 −6
Original line number Diff line number Diff line
@@ -307,6 +307,13 @@ type LoggerConfig struct {
	Level      string `yaml:"level" json:"level" usage:"Log level to set. Valid values are 'debug', 'info', 'warn', 'error'."`
	Stdout     bool   `yaml:"stdout" json:"stdout" usage:"Log to standard console output (as well as to a file if set)."`
	File       string `yaml:"file" json:"file" usage:"Log output to a file (as well as stdout if set). Make sure that the directory and the file is writable."`
	Rotating   bool   `yaml:"rotating" json:"rotating" usage:"Rotate log files. Default is false."`
	// reference: https://godoc.org/gopkg.in/natefinch/lumberjack.v2
	MaxSize    int    `yaml:"maxsize" json:"maxsize" usage:"The maximum size in megabytes of the log file before it gets rotated. It defaults to 100 megabytes."`
	MaxAge     int    ` yaml:"maxage" json:"maxage" usage:"The maximum number of days to retain old log files based on the timestamp encoded in their filename. The default is not to remove old log files based on age."`
	MaxBackups int    `yaml:"maxbackups" json:"maxbackups" usage:"The maximum number of old log files to retain. The default is to retain all old log files (though MaxAge may still cause them to get deleted.)"`
	LocalTime  bool   `yaml:"localtime" json:"localtime" usage:"This determines if the time used for formatting the timestamps in backup files is the computer's local time.  The default is to use UTC time."`
	Compress   bool   `yaml:"compress" json:"compress" usage:"This determines if the rotated log files should be compressed using gzip."`
}

// NewLoggerConfig creates a new LoggerConfig struct.
@@ -315,6 +322,12 @@ func NewLoggerConfig() *LoggerConfig {
		Level:      "info",
		Stdout:     true,
		File:       "",
		Rotating:   false,
		MaxSize:    0,
		MaxAge:     0,
		MaxBackups: 0,
		LocalTime:  false,
		Compress:   false,
	}
}

+46 −3
Original line number Diff line number Diff line
@@ -19,6 +19,7 @@ import (

	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
	"gopkg.in/natefinch/lumberjack.v2"
	"strings"
)

@@ -38,7 +39,12 @@ func SetupLogging(tmpLogger *zap.Logger, config Config) (*zap.Logger, *zap.Logge
	}

	consoleLogger := NewJSONLogger(os.Stdout, zapLevel)
	fileLogger := NewJSONFileLogger(consoleLogger, config.GetLogger().File, zapLevel)
	var fileLogger *zap.Logger
	if config.GetLogger().Rotating {
		fileLogger = NewRotatingJSONFileLogger(consoleLogger, config, zapLevel)
	} else {
		fileLogger = NewJSONFileLogger(consoleLogger, config.GetLogger().File, zapLevel)
	}

	if fileLogger != nil {
		multiLogger := NewMultiLogger(consoleLogger, fileLogger)
@@ -82,7 +88,15 @@ func NewMultiLogger(loggers ...*zap.Logger) *zap.Logger {
}

func NewJSONLogger(output *os.File, level zapcore.Level) *zap.Logger {
	jsonEncoder := zapcore.NewJSONEncoder(zapcore.EncoderConfig{
	jsonEncoder := newJSONEncoder()

	core := zapcore.NewCore(jsonEncoder, zapcore.Lock(output), level)
	options := []zap.Option{zap.AddStacktrace(zap.ErrorLevel)}
	return zap.New(core, options...)
}

func newJSONEncoder() zapcore.Encoder {
	return zapcore.NewJSONEncoder(zapcore.EncoderConfig{
		TimeKey:        "ts",
		LevelKey:       "level",
		NameKey:        "logger",
@@ -94,8 +108,37 @@ func NewJSONLogger(output *os.File, level zapcore.Level) *zap.Logger {
		EncodeDuration: zapcore.StringDurationEncoder,
		EncodeCaller:   zapcore.ShortCallerEncoder,
	})
}

	core := zapcore.NewCore(jsonEncoder, zapcore.Lock(output), level)
func NewRotatingJSONFileLogger(consoleLogger *zap.Logger, config Config, level zapcore.Level) *zap.Logger {
	fpath := config.GetLogger().File
	if len(fpath) == 0 {
		consoleLogger.Fatal("Rotating log file is enabled. But log file name is empty.")
		return nil
	}

	output, err := os.OpenFile(fpath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0666)
	if err != nil {
		consoleLogger.Fatal("Could not create log file", zap.Error(err))
		return nil
	}
	output.Close()

	jsonEncoder := newJSONEncoder()
	// lumberjack.Logger is already safe for concurrent use, so we don't need to lock it.
	w := zapcore.AddSync(&lumberjack.Logger{
		Filename:   fpath,
		MaxSize:    config.GetLogger().MaxSize,
		MaxAge:     config.GetLogger().MaxAge,
		MaxBackups: config.GetLogger().MaxBackups,
		LocalTime:  config.GetLogger().LocalTime,
		Compress:   config.GetLogger().Compress,
	})
	core := zapcore.NewCore(
		jsonEncoder,
		w,
		level,
	)
	options := []zap.Option{zap.AddStacktrace(zap.ErrorLevel)}
	return zap.New(core, options...)
}
+23 −0
Original line number Diff line number Diff line
# Compiled Object files, Static and Dynamic libs (Shared Objects)
*.o
*.a
*.so

# Folders
_obj
_test

# Architecture specific extensions/prefixes
*.[568vq]
[568vq].out

*.cgo1.go
*.cgo2.c
_cgo_defun.c
_cgo_gotypes.go
_cgo_export.*

_testmain.go

*.exe
*.test
Loading