2025-07-28 15:21:37 +08:00
|
|
|
|
package logger
|
|
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
|
"context"
|
|
|
|
|
|
"path/filepath"
|
|
|
|
|
|
"time"
|
|
|
|
|
|
|
|
|
|
|
|
"go.uber.org/zap"
|
|
|
|
|
|
"go.uber.org/zap/zapcore"
|
|
|
|
|
|
"gopkg.in/natefinch/lumberjack.v2"
|
|
|
|
|
|
)
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// LevelLogger 级别分文件日志器 - 基于 Zap 官方推荐
|
|
|
|
|
|
type LevelLogger struct {
|
|
|
|
|
|
logger *zap.Logger
|
|
|
|
|
|
levelLoggers map[zapcore.Level]*zap.Logger
|
|
|
|
|
|
config LevelLoggerConfig
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// LevelLoggerConfig 级别分文件日志器配置
|
2025-07-28 15:21:37 +08:00
|
|
|
|
type LevelLoggerConfig struct {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
BaseConfig Config
|
2025-07-28 15:21:37 +08:00
|
|
|
|
EnableLevelSeparation bool
|
2025-08-25 15:44:06 +08:00
|
|
|
|
LevelConfigs map[zapcore.Level]LevelFileConfig
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// LevelFileConfig 单个级别文件配置
|
|
|
|
|
|
type LevelFileConfig struct {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
MaxSize int `mapstructure:"max_size"`
|
|
|
|
|
|
MaxBackups int `mapstructure:"max_backups"`
|
|
|
|
|
|
MaxAge int `mapstructure:"max_age"`
|
|
|
|
|
|
Compress bool `mapstructure:"compress"`
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// NewLevelLogger 创建级别分文件日志器
|
|
|
|
|
|
func NewLevelLogger(config LevelLoggerConfig) (Logger, error) {
|
|
|
|
|
|
// 根据环境创建基础日志器
|
|
|
|
|
|
var baseLogger *zap.Logger
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
|
|
|
|
if config.BaseConfig.Development {
|
|
|
|
|
|
baseLogger, err = zap.NewDevelopment(
|
|
|
|
|
|
zap.AddCaller(),
|
|
|
|
|
|
zap.AddCallerSkip(1),
|
|
|
|
|
|
zap.AddStacktrace(zapcore.ErrorLevel),
|
|
|
|
|
|
)
|
|
|
|
|
|
} else {
|
|
|
|
|
|
baseLogger, err = zap.NewProduction(
|
|
|
|
|
|
zap.AddCaller(),
|
|
|
|
|
|
zap.AddCallerSkip(1),
|
|
|
|
|
|
zap.AddStacktrace(zapcore.ErrorLevel),
|
|
|
|
|
|
)
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if err != nil {
|
|
|
|
|
|
return nil, err
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 创建级别分文件的日志器
|
|
|
|
|
|
levelLogger := &LevelLogger{
|
|
|
|
|
|
logger: baseLogger,
|
|
|
|
|
|
levelLoggers: make(map[zapcore.Level]*zap.Logger),
|
|
|
|
|
|
config: config,
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 为每个级别创建专门的日志器
|
|
|
|
|
|
if config.EnableLevelSeparation {
|
|
|
|
|
|
levelLogger.createLevelLoggers()
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
return levelLogger, nil
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// createLevelLoggers 创建各级别的日志器
|
|
|
|
|
|
func (l *LevelLogger) createLevelLoggers() {
|
|
|
|
|
|
levels := []zapcore.Level{
|
|
|
|
|
|
zapcore.DebugLevel,
|
|
|
|
|
|
zapcore.InfoLevel,
|
|
|
|
|
|
zapcore.WarnLevel,
|
|
|
|
|
|
zapcore.ErrorLevel,
|
|
|
|
|
|
zapcore.FatalLevel,
|
|
|
|
|
|
zapcore.PanicLevel,
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
for _, level := range levels {
|
|
|
|
|
|
// 获取该级别的配置
|
|
|
|
|
|
levelConfig, exists := l.config.LevelConfigs[level]
|
|
|
|
|
|
if !exists {
|
|
|
|
|
|
// 如果没有配置,使用默认配置
|
|
|
|
|
|
levelConfig = LevelFileConfig{
|
|
|
|
|
|
MaxSize: 100,
|
|
|
|
|
|
MaxBackups: 5,
|
|
|
|
|
|
MaxAge: 30,
|
|
|
|
|
|
Compress: true,
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-07-28 15:21:37 +08:00
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 创建该级别的文件输出
|
|
|
|
|
|
writeSyncer := l.createLevelWriteSyncer(level, levelConfig)
|
|
|
|
|
|
|
|
|
|
|
|
// 创建编码器
|
|
|
|
|
|
encoder := getEncoder(l.config.BaseConfig.Format, l.config.BaseConfig)
|
|
|
|
|
|
|
|
|
|
|
|
// 创建 Core
|
|
|
|
|
|
core := zapcore.NewCore(encoder, writeSyncer, level)
|
|
|
|
|
|
|
|
|
|
|
|
// 创建该级别的日志器
|
|
|
|
|
|
levelLogger := zap.New(core,
|
|
|
|
|
|
zap.AddCaller(),
|
|
|
|
|
|
zap.AddCallerSkip(1),
|
|
|
|
|
|
zap.AddStacktrace(zapcore.ErrorLevel),
|
|
|
|
|
|
)
|
2025-07-28 15:21:37 +08:00
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
l.levelLoggers[level] = levelLogger
|
|
|
|
|
|
}
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// createLevelWriteSyncer 创建级别特定的文件输出同步器
|
|
|
|
|
|
func (l *LevelLogger) createLevelWriteSyncer(level zapcore.Level, config LevelFileConfig) zapcore.WriteSyncer {
|
|
|
|
|
|
// 构建文件路径
|
2025-07-28 15:21:37 +08:00
|
|
|
|
var logFilePath string
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if l.config.BaseConfig.UseDaily {
|
|
|
|
|
|
// 按日期分包:logs/2024-01-01/debug.log
|
|
|
|
|
|
date := time.Now().Format("2006-01-02")
|
|
|
|
|
|
levelName := level.String()
|
|
|
|
|
|
logFilePath = filepath.Join(l.config.BaseConfig.LogDir, date, levelName+".log")
|
2025-07-28 15:21:37 +08:00
|
|
|
|
} else {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 传统方式:logs/debug.log
|
|
|
|
|
|
levelName := level.String()
|
|
|
|
|
|
logFilePath = filepath.Join(l.config.BaseConfig.LogDir, levelName+".log")
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 创建 lumberjack 日志轮转器
|
|
|
|
|
|
rotator := &lumberjack.Logger{
|
2025-07-28 15:21:37 +08:00
|
|
|
|
Filename: logFilePath,
|
2025-08-25 15:44:06 +08:00
|
|
|
|
MaxSize: config.MaxSize,
|
|
|
|
|
|
MaxBackups: config.MaxBackups,
|
|
|
|
|
|
MaxAge: config.MaxAge,
|
|
|
|
|
|
Compress: config.Compress,
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
return zapcore.AddSync(rotator)
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// GetLevelLogger 获取指定级别的日志器
|
|
|
|
|
|
func (l *LevelLogger) GetLevelLogger(level zapcore.Level) *zap.Logger {
|
|
|
|
|
|
if logger, exists := l.levelLoggers[level]; exists {
|
|
|
|
|
|
return logger
|
|
|
|
|
|
}
|
|
|
|
|
|
return l.logger
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 实现 Logger 接口
|
2025-07-28 15:21:37 +08:00
|
|
|
|
func (l *LevelLogger) Debug(msg string, fields ...zapcore.Field) {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if logger := l.GetLevelLogger(zapcore.DebugLevel); logger != nil {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
logger.Debug(msg, fields...)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) Info(msg string, fields ...zapcore.Field) {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if logger := l.GetLevelLogger(zapcore.InfoLevel); logger != nil {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
logger.Info(msg, fields...)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) Warn(msg string, fields ...zapcore.Field) {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if logger := l.GetLevelLogger(zapcore.WarnLevel); logger != nil {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
logger.Warn(msg, fields...)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) Error(msg string, fields ...zapcore.Field) {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if logger := l.GetLevelLogger(zapcore.ErrorLevel); logger != nil {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
logger.Error(msg, fields...)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) Fatal(msg string, fields ...zapcore.Field) {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if logger := l.GetLevelLogger(zapcore.FatalLevel); logger != nil {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
logger.Fatal(msg, fields...)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) Panic(msg string, fields ...zapcore.Field) {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
if logger := l.GetLevelLogger(zapcore.PanicLevel); logger != nil {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
logger.Panic(msg, fields...)
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) With(fields ...zapcore.Field) Logger {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 为所有级别添加字段
|
|
|
|
|
|
for level, logger := range l.levelLoggers {
|
|
|
|
|
|
l.levelLoggers[level] = logger.With(fields...)
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
2025-08-25 15:44:06 +08:00
|
|
|
|
return l
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) WithContext(ctx context.Context) Logger {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 从上下文提取字段
|
|
|
|
|
|
fields := extractFieldsFromContext(ctx)
|
|
|
|
|
|
return l.With(fields...)
|
|
|
|
|
|
}
|
2025-07-28 15:21:37 +08:00
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
func (l *LevelLogger) Named(name string) Logger {
|
|
|
|
|
|
// 为所有级别添加名称
|
|
|
|
|
|
for level, logger := range l.levelLoggers {
|
|
|
|
|
|
l.levelLoggers[level] = logger.Named(name)
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
2025-08-25 15:44:06 +08:00
|
|
|
|
return l
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
func (l *LevelLogger) Sync() error {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
// 同步所有级别的日志器
|
|
|
|
|
|
for _, logger := range l.levelLoggers {
|
2025-07-28 15:21:37 +08:00
|
|
|
|
if err := logger.Sync(); err != nil {
|
2025-08-25 15:44:06 +08:00
|
|
|
|
return err
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
2025-08-25 15:44:06 +08:00
|
|
|
|
return l.logger.Sync()
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
func (l *LevelLogger) Core() zapcore.Core {
|
|
|
|
|
|
return l.logger.Core()
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2025-08-25 15:44:06 +08:00
|
|
|
|
func (l *LevelLogger) GetZapLogger() *zap.Logger {
|
|
|
|
|
|
return l.logger
|
2025-07-28 15:21:37 +08:00
|
|
|
|
}
|