update
This commit is contained in:
@@ -1,240 +0,0 @@
|
||||
// common/logger/logger.go
|
||||
package logger
|
||||
|
||||
import (
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"go.uber.org/zap"
|
||||
"go.uber.org/zap/zapcore"
|
||||
"gopkg.in/natefinch/lumberjack.v2"
|
||||
)
|
||||
|
||||
// 全局单例日志实例
|
||||
var (
|
||||
_logger *zap.Logger
|
||||
once sync.Once
|
||||
)
|
||||
|
||||
// LoggerOptions 日志配置项
|
||||
type LoggerOptions struct {
|
||||
Level string // 日志级别:debug/info/warn/error/panic/fatal
|
||||
Format string // 输出格式:console(控制台)/json(JSON)
|
||||
OutputPath string // 文件输出路径(如./logs/app.log)
|
||||
MaxSize int // 单个日志文件最大大小(MB)
|
||||
MaxBackups int // 最大保留日志文件数
|
||||
MaxAge int // 最大保留天数
|
||||
Compress bool // 是否压缩日志文件
|
||||
ShowLine bool // 是否显示代码行号
|
||||
ConsoleColor bool // 控制台是否显示彩色(开发环境用)
|
||||
ServiceName string // 服务名(多业务时区分日志归属,如user/order)
|
||||
StacktraceKey string // 堆栈信息键名
|
||||
CallerSkip int // 调用栈跳过数(适配封装层,正确显示业务代码行号)
|
||||
FlushInterval time.Duration // 日志刷盘间隔
|
||||
}
|
||||
|
||||
// LoggerOption 选项模式函数类型
|
||||
type LoggerOption func(*LoggerOptions)
|
||||
|
||||
// defaultLoggerOptions 初始化默认配置
|
||||
// 开发环境默认:控制台彩色日志、info级别、显示行号
|
||||
func defaultLoggerOptions() *LoggerOptions {
|
||||
return &LoggerOptions{
|
||||
Level: "info",
|
||||
Format: "console",
|
||||
OutputPath: "./logs/app.log",
|
||||
MaxSize: 100, // 单个文件100MB
|
||||
MaxBackups: 10, // 保留10个备份
|
||||
MaxAge: 7, // 保留7天
|
||||
Compress: true, // 压缩备份文件
|
||||
ShowLine: true, // 显示行号
|
||||
ConsoleColor: true, // 控制台彩色
|
||||
ServiceName: "trading_assistant", // 默认服务名
|
||||
StacktraceKey: "stacktrace",
|
||||
CallerSkip: 1, // 跳过当前封装层,正确显示业务代码行号
|
||||
FlushInterval: 3 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// 以下为配置项设置函数,支持链式调用
|
||||
func WithLevel(level string) LoggerOption {
|
||||
return func(o *LoggerOptions) { o.Level = level }
|
||||
}
|
||||
|
||||
func WithFormat(format string) LoggerOption {
|
||||
return func(o *LoggerOptions) { o.Format = format }
|
||||
}
|
||||
|
||||
func WithOutputPath(path string) LoggerOption {
|
||||
return func(o *LoggerOptions) { o.OutputPath = path }
|
||||
}
|
||||
|
||||
func WithServiceName(name string) LoggerOption {
|
||||
return func(o *LoggerOptions) { o.ServiceName = name }
|
||||
}
|
||||
|
||||
func WithShowLine(show bool) LoggerOption {
|
||||
return func(o *LoggerOptions) { o.ShowLine = show }
|
||||
}
|
||||
|
||||
func WithConsoleColor(color bool) LoggerOption {
|
||||
return func(o *LoggerOptions) { o.ConsoleColor = color }
|
||||
}
|
||||
|
||||
// getZapLevel 转换日志级别为zapcore.Level
|
||||
func getZapLevel(level string) zapcore.Level {
|
||||
switch level {
|
||||
case "debug":
|
||||
return zapcore.DebugLevel
|
||||
case "warn":
|
||||
return zapcore.WarnLevel
|
||||
case "error":
|
||||
return zapcore.ErrorLevel
|
||||
case "panic":
|
||||
return zapcore.PanicLevel
|
||||
case "fatal":
|
||||
return zapcore.FatalLevel
|
||||
default:
|
||||
return zapcore.InfoLevel // 默认info级别
|
||||
}
|
||||
}
|
||||
|
||||
// getEncoder 获取日志编码器(console/json)
|
||||
func getEncoder(opts *LoggerOptions) zapcore.Encoder {
|
||||
// 日志基础配置:时间格式、服务名、调用栈等
|
||||
encoderConfig := zapcore.EncoderConfig{
|
||||
TimeKey: "time",
|
||||
LevelKey: "level",
|
||||
NameKey: "service",
|
||||
CallerKey: "caller",
|
||||
MessageKey: "msg",
|
||||
StacktraceKey: opts.StacktraceKey,
|
||||
LineEnding: zapcore.DefaultLineEnding,
|
||||
EncodeLevel: zapcore.CapitalLevelEncoder, // 级别大写(INFO/ERROR)
|
||||
EncodeTime: zapcore.RFC3339TimeEncoder, // 时间格式RFC3339
|
||||
EncodeDuration: zapcore.SecondsDurationEncoder,
|
||||
EncodeCaller: zapcore.ShortCallerEncoder, // 调用者格式:文件:行号
|
||||
}
|
||||
|
||||
// 开发环境:控制台彩色编码器
|
||||
if opts.Format == "console" && opts.ConsoleColor {
|
||||
return zapcore.NewConsoleEncoder(encoderConfig)
|
||||
}
|
||||
|
||||
// 生产环境:JSON编码器(便于日志收集分析,如ELK)
|
||||
return zapcore.NewJSONEncoder(encoderConfig)
|
||||
}
|
||||
|
||||
// getWriteSyncer 获取日志写入器(文件+控制台)
|
||||
// 同时输出到文件和控制台,文件自动切割
|
||||
func getWriteSyncer(opts *LoggerOptions) zapcore.WriteSyncer {
|
||||
// 日志文件切割配置(基于lumberjack)
|
||||
lumberjackLogger := &lumberjack.Logger{
|
||||
Filename: opts.OutputPath,
|
||||
MaxSize: opts.MaxSize,
|
||||
MaxBackups: opts.MaxBackups,
|
||||
MaxAge: opts.MaxAge,
|
||||
Compress: opts.Compress,
|
||||
}
|
||||
|
||||
// 同时输出到文件和控制台
|
||||
return zapcore.NewMultiWriteSyncer(
|
||||
zapcore.AddSync(os.Stdout),
|
||||
zapcore.AddSync(lumberjackLogger),
|
||||
)
|
||||
}
|
||||
|
||||
// InitLogger 初始化全局单例日志实例
|
||||
func InitLogger(opts ...LoggerOption) *zap.Logger {
|
||||
once.Do(func() {
|
||||
// 加载默认配置 + 覆盖用户自定义配置
|
||||
options := defaultLoggerOptions()
|
||||
for _, opt := range opts {
|
||||
opt(options)
|
||||
}
|
||||
|
||||
// 1. 设置日志级别
|
||||
level := getZapLevel(options.Level)
|
||||
core := zapcore.NewCore(
|
||||
getEncoder(options), // 编码器
|
||||
getWriteSyncer(options), // 写入器
|
||||
level, // 日志级别
|
||||
)
|
||||
|
||||
// 2. 构建日志实例配置:是否显示调用者、堆栈信息
|
||||
zapOpts := []zap.Option{zap.AddCallerSkip(options.CallerSkip)}
|
||||
if options.ShowLine {
|
||||
zapOpts = append(zapOpts, zap.AddCaller()) // 显示调用者(文件:行号)
|
||||
}
|
||||
// 错误级别及以上显示堆栈信息
|
||||
zapOpts = append(zapOpts, zap.AddStacktrace(zapcore.ErrorLevel))
|
||||
// 设置服务名
|
||||
zapOpts = append(zapOpts, zap.Fields(zap.String("service", options.ServiceName)))
|
||||
|
||||
// 3. 创建日志实例
|
||||
_logger = zap.New(core, zapOpts...)
|
||||
|
||||
// 4. 定时刷盘(避免日志驻留内存)
|
||||
go func() {
|
||||
ticker := time.NewTicker(options.FlushInterval)
|
||||
defer ticker.Stop()
|
||||
for range ticker.C {
|
||||
_ = _logger.Sync()
|
||||
}
|
||||
}()
|
||||
|
||||
// 5. 应用退出时刷盘
|
||||
os.Setenv("ZAP_FLUSH_ON_EXIT", "true")
|
||||
})
|
||||
|
||||
return _logger
|
||||
}
|
||||
|
||||
// GetLogger 获取全局单例日志实例
|
||||
func GetLogger() *zap.Logger {
|
||||
if _logger == nil {
|
||||
// 未初始化时,返回默认控制台日志(兜底)
|
||||
return InitLogger()
|
||||
}
|
||||
return _logger
|
||||
}
|
||||
|
||||
// --------------- 轻量封装日志方法 ---------------
|
||||
// 简化业务层调用,无需每次获取logger实例
|
||||
// 复杂日志(如带字段)可直接使用GetLogger()获取原生实例
|
||||
|
||||
// Debug 调试日志
|
||||
func Debug(msg string, fields ...zap.Field) {
|
||||
GetLogger().Debug(msg, fields...)
|
||||
}
|
||||
|
||||
// Info 信息日志
|
||||
func Info(msg string, fields ...zap.Field) {
|
||||
GetLogger().Info(msg, fields...)
|
||||
}
|
||||
|
||||
// Warn 警告日志
|
||||
func Warn(msg string, fields ...zap.Field) {
|
||||
GetLogger().Warn(msg, fields...)
|
||||
}
|
||||
|
||||
// Error 错误日志(带堆栈)
|
||||
func Error(msg string, fields ...zap.Field) {
|
||||
GetLogger().Error(msg, fields...)
|
||||
}
|
||||
|
||||
// Panic 恐慌日志(打印后触发panic)
|
||||
func Panic(msg string, fields ...zap.Field) {
|
||||
GetLogger().Panic(msg, fields...)
|
||||
}
|
||||
|
||||
// Fatal 致命日志(打印后退出程序)
|
||||
func Fatal(msg string, fields ...zap.Field) {
|
||||
GetLogger().Fatal(msg, fields...)
|
||||
}
|
||||
|
||||
// Sync 手动刷盘(如重要操作后)
|
||||
func Sync() error {
|
||||
return GetLogger().Sync()
|
||||
}
|
||||
Reference in New Issue
Block a user