// Package logger 日志模块,基于 logrus 封装统一的日志接口 package logger import ( "context" "io" "os" "path/filepath" "resume-platform/pkg/constant" "github.com/sirupsen/logrus" ) var ( defaultLogger *logrus.Logger // 默认日志实例 ) // Config 日志配置 type Config struct { Level string // 日志级别 Output string // 输出文件路径 } // Init 初始化日志系统 // @param cfg 日志配置 // @return error 初始化错误 // @author sunct func Init(cfg Config) error { l := logrus.New() level, err := logrus.ParseLevel(cfg.Level) if err != nil { level = logrus.InfoLevel } l.SetLevel(level) l.SetFormatter(&logrus.TextFormatter{ FullTimestamp: true, TimestampFormat: "2006-01-02 15:04:05", }) if cfg.Output != "" { logDir := filepath.Dir(cfg.Output) if logDir != "." && logDir != "" { if err := os.MkdirAll(logDir, 0755); err != nil { return err } } file, err := os.OpenFile(cfg.Output, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644) if err != nil { return err } mw := io.MultiWriter(os.Stdout, file) l.SetOutput(mw) } else { l.SetOutput(os.Stdout) } defaultLogger = l return nil } // Get 获取默认日志实例 // @return *logrus.Logger 日志实例 // @author sunct func Get() *logrus.Logger { if defaultLogger == nil { defaultLogger = logrus.New() defaultLogger.SetFormatter(&logrus.TextFormatter{ FullTimestamp: true, TimestampFormat: "2006-01-02 15:04:05", }) } return defaultLogger } // Debug 输出 Debug 级别日志 // @param args 日志内容 func Debug(args ...interface{}) { Get().Debug(args...) } // Debugf 格式化输出 Debug 级别日志 // @param format 格式字符串 // @param args 格式化参数 func Debugf(format string, args ...interface{}) { Get().Debugf(format, args...) } // Info 输出 Info 级别日志 // @param args 日志内容 func Info(args ...interface{}) { Get().Info(args...) } // Infof 格式化输出 Info 级别日志 // @param format 格式字符串 // @param args 格式化参数 func Infof(format string, args ...interface{}) { Get().Infof(format, args...) } // Warn 输出 Warn 级别日志 // @param args 日志内容 func Warn(args ...interface{}) { Get().Warn(args...) } // Warnf 格式化输出 Warn 级别日志 // @param format 格式字符串 // @param args 格式化参数 func Warnf(format string, args ...interface{}) { Get().Warnf(format, args...) } // Error 输出 Error 级别日志 // @param args 日志内容 func Error(args ...interface{}) { Get().Error(args...) } // Errorf 格式化输出 Error 级别日志 // @param format 格式字符串 // @param args 格式化参数 func Errorf(format string, args ...interface{}) { Get().Errorf(format, args...) } // Fatal 输出 Fatal 级别日志并退出 // @param args 日志内容 func Fatal(args ...interface{}) { Get().Fatal(args...) } // Fatalf 格式化输出 Fatal 级别日志并退出 // @param format 格式字符串 // @param args 格式化参数 func Fatalf(format string, args ...interface{}) { Get().Fatalf(format, args...) } // WithField 添加单字段上下文 // @param key 字段名 // @param value 字段值 // @return *logrus.Entry 带字段的日志条目 // @author sunct func WithField(key string, value interface{}) *logrus.Entry { return Get().WithField(key, value) } // WithFields 添加多字段上下文 // @param fields 字段映射 // @return *logrus.Entry 带字段的日志条目 // @author sunct func WithFields(fields logrus.Fields) *logrus.Entry { return Get().WithFields(fields) } func FromContext(ctx context.Context) *logrus.Entry { entry := Get().WithField("app", "resume-platform") if reqId := ctx.Value(constant.RequestIdKey); reqId != nil { entry = entry.WithField("request-id", reqId) } if route := ctx.Value(constant.RequestRouteKey); route != nil { entry = entry.WithField("route", route) } if clientIP := ctx.Value(constant.ClientIP); clientIP != nil { entry = entry.WithField("client-ip", clientIP) } return entry } func CtxDebug(ctx context.Context, args ...interface{}) { FromContext(ctx).Debug(args...) } func CtxDebugf(ctx context.Context, format string, args ...interface{}) { FromContext(ctx).Debugf(format, args...) } func CtxInfo(ctx context.Context, args ...interface{}) { FromContext(ctx).Info(args...) } func CtxInfof(ctx context.Context, format string, args ...interface{}) { FromContext(ctx).Infof(format, args...) } func CtxWarn(ctx context.Context, args ...interface{}) { FromContext(ctx).Warn(args...) } func CtxWarnf(ctx context.Context, format string, args ...interface{}) { FromContext(ctx).Warnf(format, args...) } func CtxError(ctx context.Context, args ...interface{}) { FromContext(ctx).Error(args...) } func CtxErrorf(ctx context.Context, format string, args ...interface{}) { FromContext(ctx).Errorf(format, args...) } func CtxFatal(ctx context.Context, args ...interface{}) { FromContext(ctx).Fatal(args...) } func CtxFatalf(ctx context.Context, format string, args ...interface{}) { FromContext(ctx).Fatalf(format, args...) }