package log import ( "fmt" "os" "time" "go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" ) var sugar *zap.SugaredLogger type Config struct { Path string InfoFile string ErrorFile string FatalFile string MaxSize int MaxBackups int MaxAge int } func Init(c Config) error { l, err := New(c) if err != nil { return err } sugar = l return nil } func Info(args ...any) { sugar.Info(args...) } func Infof(template string, args ...any) { sugar.Infof(template, args...) } func Warn(args ...any) { sugar.Warn(args...) } func Warnf(template string, args ...any) { sugar.Warnf(template, args...) } func Error(args ...any) { sugar.Error(args...) } func Errorf(template string, args ...any) { sugar.Errorf(template, args...) } func Fatal(args ...any) { sugar.Fatal(args...) } func Fatalf(template string, args ...any) { sugar.Fatalf(template, args...) } func New(c Config) (*zap.SugaredLogger, error) { if c.Path == "" { c.Path = "logs" } if c.InfoFile == "" { c.InfoFile = "info.log" } if c.ErrorFile == "" { c.ErrorFile = "error.log" } if c.FatalFile == "" { c.FatalFile = "fatal.log" } if c.MaxSize == 0 { c.MaxSize = 100 } if c.MaxBackups == 0 { c.MaxBackups = 10 } if c.MaxAge == 0 { c.MaxAge = 30 } if err := os.MkdirAll(c.Path, 0o755); err != nil { return nil, fmt.Errorf("log mkdir: %w", err) } consoleEncoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{ MessageKey: "msg", LevelKey: "level", EncodeLevel: zapcore.LowercaseColorLevelEncoder, TimeKey: "ts", EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString(t.Format("2006-01-02 15:04:05")) }, CallerKey: "file", EncodeCaller: zapcore.ShortCallerEncoder, EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { enc.AppendInt64(int64(d) / 1e6) }, }) fileEncoder := zapcore.NewConsoleEncoder(zapcore.EncoderConfig{ MessageKey: "msg", LevelKey: "level", EncodeLevel: zapcore.LowercaseLevelEncoder, TimeKey: "ts", EncodeTime: func(t time.Time, enc zapcore.PrimitiveArrayEncoder) { enc.AppendString(t.Format("2006-01-02 15:04:05")) }, CallerKey: "file", EncodeCaller: zapcore.ShortCallerEncoder, EncodeDuration: func(d time.Duration, enc zapcore.PrimitiveArrayEncoder) { enc.AppendInt64(int64(d) / 1e6) }, }) infoLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl == zapcore.InfoLevel }) errorLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl == zapcore.ErrorLevel }) fatalLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl == zapcore.FatalLevel }) today := time.Now().Format("2006-01-02") infoWriter := getWriter(c.Path+"/"+today+"-"+c.InfoFile, c) errorWriter := getWriter(c.Path+"/"+today+"-"+c.ErrorFile, c) fatalWriter := getWriter(c.Path+"/"+today+"-"+c.FatalFile, c) core := zapcore.NewTee( zapcore.NewCore(consoleEncoder, zapcore.AddSync(os.Stdout), zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { return lvl >= zapcore.InfoLevel })), zapcore.NewCore(fileEncoder, infoWriter, infoLevel), zapcore.NewCore(fileEncoder, errorWriter, errorLevel), zapcore.NewCore(fileEncoder, fatalWriter, fatalLevel), ) // AddCallerSkip(1):经包级 Info/Errorf 转发时显示真实调用方 return zap.New(core, zap.AddCaller(), zap.AddCallerSkip(1)).Sugar(), nil } func getWriter(filename string, c Config) zapcore.WriteSyncer { return zapcore.AddSync(&lumberjack.Logger{ Filename: filename, MaxSize: c.MaxSize, MaxBackups: c.MaxBackups, MaxAge: c.MaxAge, Compress: false, LocalTime: true, }) }