package logger import ( "context" "fmt" "io" "os" "runtime" "sync" "time" ) // Level 日志级别 type Level int const ( DEBUG Level = iota INFO WARN ERROR FATAL ) func (l Level) String() string { switch l { case DEBUG: return "DEBUG" case INFO: return "INFO" case WARN: return "WARN" case ERROR: return "ERROR" case FATAL: return "FATAL" default: return "UNKNOWN" } } // Fields 日志字段的类型别名 type Fields map[string]interface{} // Logger 结构化日志器 type Logger struct { mu sync.Mutex level Level output io.Writer prefix string fields Fields hooks []Hook } // Hook 日志钩子接口 type Hook interface { Fire(entry *Entry) error Levels() []Level } // Entry 日志条目 type Entry struct { Logger *Logger Time time.Time Level Level Message string Fields Fields Caller string Context context.Context } // New 创建新的日志器 func New() *Logger { return &Logger{ level: INFO, output: os.Stdout, fields: make(Fields), } } // SetLevel 设置日志级别 func (l *Logger) SetLevel(level Level) { l.mu.Lock() defer l.mu.Unlock() l.level = level } // GetLevel 获取日志级别 func (l *Logger) GetLevel() Level { l.mu.Lock() defer l.mu.Unlock() return l.level } // SetOutput 设置输出目标 func (l *Logger) SetOutput(w io.Writer) { l.mu.Lock() defer l.mu.Unlock() l.output = w } // WithPrefix 设置前缀 func (l *Logger) WithPrefix(prefix string) *Logger { return &Logger{ level: l.level, output: l.output, prefix: prefix, fields: make(Fields), } } // WithField 添加单个字段 func (l *Logger) WithField(key string, value interface{}) *Logger { l.mu.Lock() defer l.mu.Unlock() newFields := make(Fields, len(l.fields)+1) for k, v := range l.fields { newFields[k] = v } newFields[key] = value return &Logger{ level: l.level, output: l.output, prefix: l.prefix, fields: newFields, hooks: l.hooks, // 复制钩子 } } // WithFields 添加多个字段 func (l *Logger) WithFields(fields Fields) *Logger { l.mu.Lock() defer l.mu.Unlock() newFields := make(Fields, len(l.fields)+len(fields)) for k, v := range l.fields { newFields[k] = v } for k, v := range fields { newFields[k] = v } return &Logger{ level: l.level, output: l.output, prefix: l.prefix, fields: newFields, hooks: l.hooks, // 复制钩子 } } // WithContext 添加上下文 func (l *Logger) WithContext(ctx context.Context) *Logger { return &Logger{ level: l.level, output: l.output, prefix: l.prefix, fields: l.fields, } } // AddHook 添加钩子 func (l *Logger) AddHook(hook Hook) { l.mu.Lock() defer l.mu.Unlock() l.hooks = append(l.hooks, hook) } // newEntry 创建新的日志条目 func (l *Logger) newEntry(level Level, msg string) *Entry { l.mu.Lock() defer l.mu.Unlock() entry := &Entry{ Logger: l, Time: time.Now(), Level: level, Message: msg, Fields: make(Fields, len(l.fields)), } // 复制字段 for k, v := range l.fields { entry.Fields[k] = v } // 添加调用者信息 if _, file, line, ok := runtime.Caller(2); ok { entry.Caller = fmt.Sprintf("%s:%d", file, line) } return entry } // Debug 记录 DEBUG 级别日志 func (l *Logger) Debug(msg string) { if l.level <= DEBUG { l.newEntry(DEBUG, msg).Log() } } // Info 记录 INFO 级别日志 func (l *Logger) Info(msg string) { if l.level <= INFO { l.newEntry(INFO, msg).Log() } } // Warn 记录 WARN 级别日志 func (l *Logger) Warn(msg string) { if l.level <= WARN { l.newEntry(WARN, msg).Log() } } // Error 记录 ERROR 级别日志 func (l *Logger) Error(msg string) { if l.level <= ERROR { l.newEntry(ERROR, msg).Log() } } // Fatal 记录 FATAL 级别日志 func (l *Logger) Fatal(msg string) { if l.level <= FATAL { l.newEntry(FATAL, msg).Log() os.Exit(1) } } // Debugf 记录带格式化的 DEBUG 级别日志 func (l *Logger) Debugf(format string, args ...interface{}) { l.Debug(fmt.Sprintf(format, args...)) } // Infof 记录带格式化的 INFO 级别日志 func (l *Logger) Infof(format string, args ...interface{}) { l.Info(fmt.Sprintf(format, args...)) } // Warnf 记录带格式化的 WARN 级别日志 func (l *Logger) Warnf(format string, args ...interface{}) { l.Warn(fmt.Sprintf(format, args...)) } // Errorf 记录带格式化的 ERROR 级别日志 func (l *Logger) Errorf(format string, args ...interface{}) { l.Error(fmt.Sprintf(format, args...)) } // Fatalf 记录带格式化的 FATAL 级别日志 func (l *Logger) Fatalf(format string, args ...interface{}) { l.Fatal(fmt.Sprintf(format, args...)) } // Log 记录日志条目 func (e *Entry) Log() { formatted := e.format() e.Logger.mu.Lock() _, _ = e.Logger.output.Write([]byte(formatted)) e.Logger.mu.Unlock() // 触发钩子 for _, hook := range e.Logger.hooks { for _, level := range hook.Levels() { if e.Level == level { _ = hook.Fire(e) } } } } // format 格式化日志条目 func (e *Entry) format() string { timestamp := e.Time.Format("2006-01-02 15:04:05.000") var callerStr string if e.Caller != "" { callerStr = fmt.Sprintf("[%s] ", e.Caller) } var prefixStr string if e.Logger.prefix != "" { prefixStr = fmt.Sprintf("[%s] ", e.Logger.prefix) } // 格式化字段 fieldsStr := "" for k, v := range e.Fields { fieldsStr += fmt.Sprintf("%s=%v ", k, v) } return fmt.Sprintf("%s %s%s%s%s%s\n", timestamp, e.Level.String(), callerStr, prefixStr, e.Message, fieldsStr, ) } // 性能追踪相关 // TimingEntry 性能计时条目 type TimingEntry struct { logger *Logger start time.Time operation string fields Fields } // BeginTiming 开始性能追踪 func (l *Logger) BeginTiming(operation string) *TimingEntry { return &TimingEntry{ logger: l.WithField("operation", operation), start: time.Now(), operation: operation, fields: make(Fields), } } // WithField 添加追踪字段 func (t *TimingEntry) WithField(key string, value interface{}) *TimingEntry { t.fields[key] = value return t } // End 结束性能追踪并记录 func (t *TimingEntry) End(msg string) { duration := time.Since(t.start) t.logger.WithFields(t.fields).WithField("duration_ms", float64(duration.Nanoseconds())/1e6).Info(msg) } // 全局默认日志器 var defaultLogger = New() // Default 获取默认日志器 func Default() *Logger { return defaultLogger } // SetDefault 设置默认日志器 func SetDefault(logger *Logger) { defaultLogger = logger } // 便捷函数 func Debug(msg string) { defaultLogger.Debug(msg) } func Info(msg string) { defaultLogger.Info(msg) } func Warn(msg string) { defaultLogger.Warn(msg) } func Error(msg string) { defaultLogger.Error(msg) } func Fatal(msg string) { defaultLogger.Fatal(msg) } func Debugf(format string, args ...interface{}) { defaultLogger.Debugf(format, args...) } func Infof(format string, args ...interface{}) { defaultLogger.Infof(format, args...) } func Warnf(format string, args ...interface{}) { defaultLogger.Warnf(format, args...) } func Errorf(format string, args ...interface{}) { defaultLogger.Errorf(format, args...) } func Fatalf(format string, args ...interface{}) { defaultLogger.Fatalf(format, args...) } func WithField(key string, value interface{}) *Logger { return defaultLogger.WithField(key, value) } func WithFields(fields Fields) *Logger { return defaultLogger.WithFields(fields) }