diff options
author | Valery Piashchynski <[email protected]> | 2021-06-09 13:32:34 +0300 |
---|---|---|
committer | Valery Piashchynski <[email protected]> | 2021-06-09 13:32:34 +0300 |
commit | 3ec3306730455b6c5c423d130ebc322757661487 (patch) | |
tree | 1acfe544effb563a06e133a13be1faac6b3fddbb /plugins/logger | |
parent | a723cedba199a1c50dca05630b53139ee456ace8 (diff) |
- Add support for the file logger with log rotation and compression
Signed-off-by: Valery Piashchynski <[email protected]>
Diffstat (limited to 'plugins/logger')
-rw-r--r-- | plugins/logger/config.go | 92 | ||||
-rw-r--r-- | plugins/logger/enums.go | 12 | ||||
-rw-r--r-- | plugins/logger/zap_adapter.go | 2 |
3 files changed, 98 insertions, 8 deletions
diff --git a/plugins/logger/config.go b/plugins/logger/config.go index d2236cac..6ef56661 100644 --- a/plugins/logger/config.go +++ b/plugins/logger/config.go @@ -1,10 +1,12 @@ package logger import ( + "os" "strings" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" ) // ChannelConfig configures loggers per channel. @@ -13,9 +15,57 @@ type ChannelConfig struct { Channels map[string]Config `mapstructure:"channels"` } +// FileLoggerConfig structure represents configuration for the file logger +type FileLoggerConfig struct { + // Filename is the file to write logs to. Backup log files will be retained + // in the same directory. It uses <processname>-lumberjack.log in + // os.TempDir() if empty. + LogOutput string `mapstructure:"log_output"` + + // MaxSize is the maximum size in megabytes of the log file before it gets + // rotated. It defaults to 100 megabytes. + MaxSize int `mapstructure:"max_size"` + + // MaxAge is the maximum number of days to retain old log files based on the + // timestamp encoded in their filename. Note that a day is defined as 24 + // hours and may not exactly correspond to calendar days due to daylight + // savings, leap seconds, etc. The default is not to remove old log files + // based on age. + MaxAge int `mapstructure:"max_age"` + + // MaxBackups is 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.) + MaxBackups int `mapstructure:"max_backups"` + + // Compress determines if the rotated log files should be compressed + // using gzip. The default is not to perform compression. + Compress bool `mapstructure:"compress"` +} + +func (fl *FileLoggerConfig) InitDefaults() *FileLoggerConfig { + if fl.LogOutput == "" { + fl.LogOutput = os.TempDir() + } + + if fl.MaxSize == 0 { + fl.MaxSize = 100 + } + + if fl.MaxAge == 0 { + fl.MaxAge = 24 + } + + if fl.MaxBackups == 0 { + fl.MaxBackups = 10 + } + + return fl +} + type Config struct { // Mode configures logger based on some default template (development, production, off). - Mode string `mapstructure:"mode"` + Mode Mode `mapstructure:"mode"` // Level is the minimum enabled logging level. Note that this is a dynamic // level, so calling ChannelConfig.Level.SetLevel will atomically change the log @@ -38,17 +88,20 @@ type Config struct { // sends error-level logs to a different location from info- and debug-level // logs, see the package-level AdvancedConfiguration example. ErrorOutput []string `mapstructure:"errorOutput"` + + // File logger options + FileLogger *FileLoggerConfig `mapstructure:"file_logger_options"` } // BuildLogger converts config into Zap configuration. func (cfg *Config) BuildLogger() (*zap.Logger, error) { var zCfg zap.Config - switch strings.ToLower(cfg.Mode) { - case "off", "none": + switch Mode(strings.ToLower(string(cfg.Mode))) { + case off, none: return zap.NewNop(), nil - case "production": + case production: zCfg = zap.NewProductionConfig() - case "development": + case development: zCfg = zap.Config{ Level: zap.NewAtomicLevelAt(zap.DebugLevel), Development: true, @@ -72,7 +125,7 @@ func (cfg *Config) BuildLogger() (*zap.Logger, error) { OutputPaths: []string{"stderr"}, ErrorOutputPaths: []string{"stderr"}, } - case "raw": + case raw: zCfg = zap.Config{ Level: zap.NewAtomicLevelAt(zap.InfoLevel), Encoding: "console", @@ -120,13 +173,38 @@ func (cfg *Config) BuildLogger() (*zap.Logger, error) { zCfg.ErrorOutputPaths = cfg.ErrorOutput } + // if we also have a file logger specified in the config + // init it + // otherwise - return standard config + if cfg.FileLogger != nil { + // init absent options + cfg.FileLogger.InitDefaults() + + w := zapcore.AddSync( + &lumberjack.Logger{ + Filename: cfg.FileLogger.LogOutput, + MaxSize: cfg.FileLogger.MaxSize, + MaxAge: cfg.FileLogger.MaxAge, + MaxBackups: cfg.FileLogger.MaxBackups, + Compress: cfg.FileLogger.Compress, + }, + ) + + core := zapcore.NewCore( + zapcore.NewJSONEncoder(zCfg.EncoderConfig), + w, + zCfg.Level, + ) + return zap.New(core), nil + } + return zCfg.Build() } // InitDefault Initialize default logger func (cfg *Config) InitDefault() { if cfg.Mode == "" { - cfg.Mode = "development" + cfg.Mode = development } if cfg.Level == "" { cfg.Level = "debug" diff --git a/plugins/logger/enums.go b/plugins/logger/enums.go new file mode 100644 index 00000000..803eace0 --- /dev/null +++ b/plugins/logger/enums.go @@ -0,0 +1,12 @@ +package logger + +// Mode represents available logger modes +type Mode string + +const ( + none Mode = "none" + off Mode = "off" + production Mode = "production" + development Mode = "development" + raw Mode = "raw" +) diff --git a/plugins/logger/zap_adapter.go b/plugins/logger/zap_adapter.go index 6d865519..fab59844 100644 --- a/plugins/logger/zap_adapter.go +++ b/plugins/logger/zap_adapter.go @@ -10,7 +10,7 @@ type ZapAdapter struct { zl *zap.Logger } -// Create NewZapAdapter which uses general log interface +// NewZapAdapter ... which uses general log interface func NewZapAdapter(zapLogger *zap.Logger) *ZapAdapter { return &ZapAdapter{ zl: zapLogger.WithOptions(zap.AddCallerSkip(1)), |