package logger import ( "context" "sync" "github.com/go-logr/logr" ) // Logger 定义项目的日志接口,基于logr但提供更清晰的抽象. // 支持结构化日志和上下文感知的日志记录. type Logger interface { // Context-aware structured logging methods (推荐使用) DebugContext(ctx context.Context, msg string, args ...any) InfoContext(ctx context.Context, msg string, args ...any) WarnContext(ctx context.Context, msg string, args ...any) ErrorContext(ctx context.Context, msg string, args ...any) // Non-context structured logging methods (用于适配器和内部组件) Debug(msg string, args ...any) Info(msg string, args ...any) Warn(msg string, args ...any) Error(msg string, args ...any) } // NewLogger 创建一个基于logr的Logger实现. func NewLogger(logger logr.Logger) Logger { return &logrAdapter{ logger: logger, } } // NewDefaultLogger 创建一个默认的Logger实现. // 注意:logr需要显式提供一个LogSink实现,这里返回一个discard logger. func NewDefaultLogger() Logger { return &logrAdapter{ logger: logr.Discard(), } } // NopLogger 空操作日志器实现,所有日志方法都不执行任何操作. // 适用于不需要日志输出的场景,如测试或性能敏感的场景. type NopLogger struct{} // NewNopLogger 创建新的空操作日志器. func NewNopLogger() *NopLogger { return &NopLogger{} } func (n *NopLogger) DebugContext(_ context.Context, _ string, _ ...any) {} func (n *NopLogger) InfoContext(_ context.Context, _ string, _ ...any) {} func (n *NopLogger) WarnContext(_ context.Context, _ string, _ ...any) {} func (n *NopLogger) ErrorContext(_ context.Context, _ string, _ ...any) {} func (n *NopLogger) Debug(_ string, _ ...any) {} func (n *NopLogger) Info(_ string, _ ...any) {} func (n *NopLogger) Warn(_ string, _ ...any) {} func (n *NopLogger) Error(_ string, _ ...any) {} // 全局日志器相关变量. // //nolint:gochecknoglobals // 全局日志器是必要的,用于提供便捷的日志访问接口 var ( globalLogger Logger = NewNopLogger() // 默认使用 NopLogger globalLoggerLock sync.RWMutex ) // SetGlobalLogger 设置全局日志器. // 线程安全,可以在程序启动时调用以设置全局日志器. func SetGlobalLogger(logger Logger) { if logger == nil { logger = NewNopLogger() } globalLoggerLock.Lock() defer globalLoggerLock.Unlock() globalLogger = logger } // GetGlobalLogger 获取全局日志器. // 线程安全,返回当前设置的全局日志器,如果未设置则返回 NopLogger. func GetGlobalLogger() Logger { globalLoggerLock.RLock() defer globalLoggerLock.RUnlock() return globalLogger } // logrAdapter 是Logger接口的logr实现. type logrAdapter struct { logger logr.Logger } // convertArgs 将args转换为logr的key-value对格式. // logr要求key-value成对出现,如果args是奇数个,最后一个会作为单独的value. func convertArgs(args ...any) []any { // 如果args已经是成对的key-value格式,直接返回 if len(args)%2 == 0 { return args } // 如果不是成对的,可能需要特殊处理 // 这里我们假设调用者传入的是key-value对 return args } func (l *logrAdapter) DebugContext(ctx context.Context, msg string, args ...any) { _ = ctx // 保持接口兼容性,logr目前不支持context l.logger.V(1).Info(msg, convertArgs(args...)...) } func (l *logrAdapter) InfoContext(ctx context.Context, msg string, args ...any) { _ = ctx // 保持接口兼容性,logr目前不支持context l.logger.Info(msg, convertArgs(args...)...) } func (l *logrAdapter) WarnContext(ctx context.Context, msg string, args ...any) { _ = ctx // 保持接口兼容性,logr目前不支持context // logr没有Warn级别,使用Info但标记为warning kv := convertArgs(args...) kv = append(kv, "level", "warning") l.logger.Info(msg, kv...) } func (l *logrAdapter) ErrorContext(ctx context.Context, msg string, args ...any) { _ = ctx // 保持接口兼容性,logr目前不支持context // 尝试从args中提取error var err error kvArgs := make([]any, 0, len(args)) for i := 0; i < len(args); i++ { if i+1 < len(args) && args[i] == "error" { if e, ok := args[i+1].(error); ok { err = e i++ // 跳过error值 continue } } kvArgs = append(kvArgs, args[i]) } if err != nil { l.logger.Error(err, msg, convertArgs(kvArgs...)...) } else { // 如果没有error,使用Info但标记为error级别 kvArgs = append(kvArgs, "level", "error") l.logger.Info(msg, convertArgs(kvArgs...)...) } } func (l *logrAdapter) Debug(msg string, args ...any) { l.logger.V(1).Info(msg, convertArgs(args...)...) } func (l *logrAdapter) Info(msg string, args ...any) { l.logger.Info(msg, convertArgs(args...)...) } func (l *logrAdapter) Warn(msg string, args ...any) { // logr没有Warn级别,使用Info但标记为warning kv := convertArgs(args...) kv = append(kv, "level", "warning") l.logger.Info(msg, kv...) } func (l *logrAdapter) Error(msg string, args ...any) { // 尝试从args中提取error var err error kvArgs := make([]any, 0, len(args)) for i := 0; i < len(args); i++ { if i+1 < len(args) && args[i] == "error" { if e, ok := args[i+1].(error); ok { err = e i++ // 跳过error值 continue } } kvArgs = append(kvArgs, args[i]) } if err != nil { l.logger.Error(err, msg, convertArgs(kvArgs...)...) } else { // 如果没有error,使用Info但标记为error级别 kvArgs = append(kvArgs, "level", "error") l.logger.Info(msg, convertArgs(kvArgs...)...) } }