package logging import ( "fmt" "os" "time" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) type Level zapcore.Level const ( Info Level = 0 Warning Level = 1 Error Level = 2 Debug Level = -1 ) type Logger struct { log *zap.Logger debug *zap.Logger debugging bool } func NewLogger(file string, cfg *Config) (*Logger, error) { if cfg == nil { cfg = DefaultConfig() } if file == "" { file = "NewLogger.log" } encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.TimeKey = "timestamp" encoderConfig.EncodeTime = func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString(t.Format("2006-01-02T15:04:05.000")) } encoder := zapcore.NewJSONEncoder(encoderConfig) fileSyncer := zapcore.AddSync(&lumberjack.Logger{ Filename: file, MaxSize: 1, // megabytes MaxBackups: 3, MaxAge: 28, // days }) // Create core list var cores []zapcore.Core // File core (always added) cores = append(cores, zapcore.NewCore(encoder, fileSyncer, zapcore.InfoLevel)) // Optional stdout core if cfg.TerminalOut { stdoutSyncer := zapcore.AddSync(zapcore.Lock(os.Stdout)) cores = append(cores, zapcore.NewCore(encoder, stdoutSyncer, zapcore.InfoLevel)) } combinedCore := zapcore.NewTee(cores...) // If debugging, add a separate debug core (to both file and stdout if requested) var debugCores []zapcore.Core debugCores = append(debugCores, zapcore.NewCore(encoder, fileSyncer, zapcore.DebugLevel)) if cfg.TerminalOut { stdoutSyncer := zapcore.AddSync(zapcore.Lock(os.Stdout)) debugCores = append(debugCores, zapcore.NewCore(encoder, stdoutSyncer, zapcore.DebugLevel)) } debugCore := zapcore.NewTee(debugCores...) // Build the logger return &Logger{ log: zap.New(combinedCore), debug: zap.New(debugCore), debugging: cfg.Debug, }, nil } func (l *Logger) Info(caller, msg string) { l.log.Info(msg, zap.String("caller", caller)) } func (l *Logger) Warning(caller, msg string) { l.log.Warn(msg, zap.String("caller", caller)) } func (l *Logger) Error(caller string, msg any) { l.log.Error(fmt.Sprint(msg), zap.String("caller", caller)) } func (l *Logger) Debug(caller, msg string) { if !l.debugging { return } l.debug.Debug(msg, zap.String("caller", caller)) }