diff options
Diffstat (limited to 'weed/util/log/log.go')
| -rw-r--r-- | weed/util/log/log.go | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/weed/util/log/log.go b/weed/util/log/log.go new file mode 100644 index 000000000..0a6af15c9 --- /dev/null +++ b/weed/util/log/log.go @@ -0,0 +1,239 @@ +package log + +import ( + "os" + "sync" + + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" +) + +// Level is an alias for zapcore.Level +type Level = zapcore.Level + +// LogConfig holds the configuration for logging +type LogConfig struct { + // LogFile is the path to the log file. If empty, logs will be written to stdout + LogFile string + // MaxSize is the maximum size in megabytes of the log file before it gets rotated + MaxSize int + // MaxBackups is the maximum number of old log files to retain + MaxBackups int + // MaxAge is the maximum number of days to retain old log files + MaxAge int + // Compress determines if the rotated log files should be compressed + Compress bool +} + +var ( + // Logger is the global logger instance + Logger *zap.Logger + // Sugar is the global sugared logger instance + Sugar *zap.SugaredLogger + // atom is the atomic level for dynamic log level changes + atom zap.AtomicLevel + // once ensures initialization happens only once + once sync.Once + // defaultLevel is the default logging level if not specified + defaultLevel = zapcore.InfoLevel +) + +// VerboseLogger wraps a sugared logger with verbosity level +type VerboseLogger struct { + level Level +} + +// Verbose returns a VerboseLogger for the given verbosity level +func Verbose(level Level) *VerboseLogger { + return &VerboseLogger{level: level} +} + +// Infof logs a formatted message at info level if the verbosity level is enabled +func (v *VerboseLogger) Infof(format string, args ...interface{}) { + if atom.Enabled(v.level) { + Sugar.Infof(format, args...) + } +} + +// Info logs a message at info level if the verbosity level is enabled +func (v *VerboseLogger) Info(args ...interface{}) { + if atom.Enabled(v.level) { + Sugar.Info(args...) + } +} + +// Infoln logs a message at info level with a newline if the verbosity level is enabled +func (v *VerboseLogger) Infoln(args ...interface{}) { + if atom.Enabled(v.level) { + Sugar.Infoln(args...) + } +} + +// Warning logs a message at warn level if the verbosity level is enabled +func (v *VerboseLogger) Warning(args ...interface{}) { + if atom.Enabled(v.level) { + Sugar.Warn(args...) + } +} + +// Warningf logs a formatted message at warn level if the verbosity level is enabled +func (v *VerboseLogger) Warningf(format string, args ...interface{}) { + if atom.Enabled(v.level) { + Sugar.Warnf(format, args...) + } +} + +// Init initializes the logger with the given level and configuration +func Init(level Level, config *LogConfig) { + once.Do(func() { + // Initialize with default level if not specified + if level == 0 { + level = defaultLevel + } + + atom = zap.NewAtomicLevel() + atom.SetLevel(level) + + encoderConfig := zap.NewProductionEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + + var writeSyncer zapcore.WriteSyncer + if config != nil && config.LogFile != "" { + // Create a lumberjack logger for log rotation + rotator := &lumberjack.Logger{ + Filename: config.LogFile, + MaxSize: config.MaxSize, // megabytes + MaxBackups: config.MaxBackups, + MaxAge: config.MaxAge, // days + Compress: config.Compress, + } + writeSyncer = zapcore.AddSync(rotator) + } else { + writeSyncer = zapcore.AddSync(os.Stdout) + } + + core := zapcore.NewCore( + zapcore.NewJSONEncoder(encoderConfig), + writeSyncer, + atom, + ) + + Logger = zap.New(core) + Sugar = Logger.Sugar() + }) +} + +// SetLevel changes the logging level dynamically +func SetLevel(level Level) { + if atom == (zap.AtomicLevel{}) { + Init(level, nil) + return + } + atom.SetLevel(level) +} + +// V returns a VerboseLogger for the given verbosity level +func V(level Level) *VerboseLogger { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + return Verbose(level) +} + +// Info logs a message at info level +func Info(args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Info(args...) +} + +// Infof logs a formatted message at info level +func Infof(format string, args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Infof(format, args...) +} + +// Warning logs a message at warn level +func Warning(args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Warn(args...) +} + +// Warningf logs a formatted message at warn level +func Warningf(format string, args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Warnf(format, args...) +} + +// Error logs a message at error level +func Error(args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Error(args...) +} + +// Errorf logs a formatted message at error level +func Errorf(format string, args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Errorf(format, args...) +} + +// Fatal logs a message at fatal level and then calls os.Exit(1) +func Fatal(args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Fatal(args...) +} + +// Fatalf logs a formatted message at fatal level and then calls os.Exit(1) +func Fatalf(format string, args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Fatalf(format, args...) +} + +// Exitf logs a formatted message at fatal level and then calls os.Exit(1) +func Exitf(format string, args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Fatalf(format, args...) + os.Exit(1) +} + +// With returns a logger with the given fields +func With(fields ...zap.Field) *zap.Logger { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + return Logger.With(fields...) +} + +// WithSugar returns a sugared logger with the given fields +func WithSugar(args ...interface{}) *zap.SugaredLogger { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + return Sugar.With(args...) +} + +// Printf logs a formatted message at info level +func Printf(format string, args ...interface{}) { + if atom == (zap.AtomicLevel{}) { + Init(defaultLevel, nil) + } + Sugar.Infof(format, args...) +} |
