147 lines
3.5 KiB
Go
147 lines
3.5 KiB
Go
package logger
|
||
|
||
import (
|
||
"go.uber.org/zap"
|
||
"go.uber.org/zap/zapcore"
|
||
"gopkg.in/natefinch/lumberjack.v2"
|
||
)
|
||
|
||
var (
|
||
// appLogger 应用日志记录器
|
||
appLogger *zap.Logger
|
||
// accessLogger 访问日志记录器
|
||
accessLogger *zap.Logger
|
||
)
|
||
|
||
// InitLoggers 初始化应用和访问日志记录器
|
||
func InitLoggers(
|
||
level string,
|
||
development bool,
|
||
appLogConfig LogRotationConfig,
|
||
accessLogConfig LogRotationConfig,
|
||
) error {
|
||
// 解析日志级别
|
||
zapLevel := parseLevel(level)
|
||
|
||
// 创建编码器配置
|
||
encoderConfig := zapcore.EncoderConfig{
|
||
TimeKey: "timestamp",
|
||
LevelKey: "level",
|
||
NameKey: "logger",
|
||
CallerKey: "caller",
|
||
MessageKey: "message",
|
||
StacktraceKey: "stacktrace",
|
||
LineEnding: zapcore.DefaultLineEnding,
|
||
EncodeLevel: zapcore.LowercaseLevelEncoder,
|
||
EncodeTime: zapcore.ISO8601TimeEncoder, // RFC3339 格式
|
||
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||
EncodeCaller: zapcore.ShortCallerEncoder,
|
||
}
|
||
|
||
// 选择编码器(开发模式使用控制台,生产使用 JSON)
|
||
var encoder zapcore.Encoder
|
||
if development {
|
||
encoder = zapcore.NewConsoleEncoder(encoderConfig)
|
||
} else {
|
||
encoder = zapcore.NewJSONEncoder(encoderConfig)
|
||
}
|
||
|
||
// 创建应用日志核心
|
||
appCore := zapcore.NewCore(
|
||
encoder,
|
||
zapcore.AddSync(newLumberjackLogger(appLogConfig)),
|
||
zapLevel,
|
||
)
|
||
|
||
// 创建访问日志核心(始终使用 JSON)
|
||
accessCore := zapcore.NewCore(
|
||
zapcore.NewJSONEncoder(encoderConfig),
|
||
zapcore.AddSync(newLumberjackLogger(accessLogConfig)),
|
||
zapcore.InfoLevel, // 访问日志始终使用 info 级别
|
||
)
|
||
|
||
// 构建日志记录器
|
||
if development {
|
||
// 开发模式:添加调用者信息和堆栈跟踪
|
||
appLogger = zap.New(appCore, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel), zap.Development())
|
||
} else {
|
||
// 生产模式:添加调用者信息,仅在 error 时添加堆栈跟踪
|
||
appLogger = zap.New(appCore, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
|
||
}
|
||
|
||
// 访问日志不需要调用者信息
|
||
accessLogger = zap.New(accessCore)
|
||
|
||
return nil
|
||
}
|
||
|
||
// GetAppLogger 返回应用日志记录器
|
||
func GetAppLogger() *zap.Logger {
|
||
if appLogger == nil {
|
||
// 如果未初始化,返回 nop logger
|
||
return zap.NewNop()
|
||
}
|
||
return appLogger
|
||
}
|
||
|
||
// GetAccessLogger 返回访问日志记录器
|
||
func GetAccessLogger() *zap.Logger {
|
||
if accessLogger == nil {
|
||
// 如果未初始化,返回 nop logger
|
||
return zap.NewNop()
|
||
}
|
||
return accessLogger
|
||
}
|
||
|
||
// Sync 刷新所有日志缓冲区
|
||
func Sync() error {
|
||
if appLogger != nil {
|
||
if err := appLogger.Sync(); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
if accessLogger != nil {
|
||
if err := accessLogger.Sync(); err != nil {
|
||
return err
|
||
}
|
||
}
|
||
return nil
|
||
}
|
||
|
||
// parseLevel 解析日志级别字符串
|
||
func parseLevel(level string) zapcore.Level {
|
||
switch level {
|
||
case "debug":
|
||
return zapcore.DebugLevel
|
||
case "info":
|
||
return zapcore.InfoLevel
|
||
case "warn":
|
||
return zapcore.WarnLevel
|
||
case "error":
|
||
return zapcore.ErrorLevel
|
||
default:
|
||
return zapcore.InfoLevel
|
||
}
|
||
}
|
||
|
||
// newLumberjackLogger 创建 Lumberjack 日志轮转器
|
||
func newLumberjackLogger(config LogRotationConfig) *lumberjack.Logger {
|
||
return &lumberjack.Logger{
|
||
Filename: config.Filename,
|
||
MaxSize: config.MaxSize,
|
||
MaxBackups: config.MaxBackups,
|
||
MaxAge: config.MaxAge,
|
||
Compress: config.Compress,
|
||
LocalTime: true, // 使用本地时间
|
||
}
|
||
}
|
||
|
||
// LogRotationConfig 日志轮转配置(从 config 包复制以避免循环依赖)
|
||
type LogRotationConfig struct {
|
||
Filename string
|
||
MaxSize int
|
||
MaxBackups int
|
||
MaxAge int
|
||
Compress bool
|
||
}
|