add JRZQ09J8、FLXGDEA8、FLXGDEA9、JRZQ1D09

add external_services log
This commit is contained in:
2025-08-25 15:44:06 +08:00
parent 365a2a8886
commit 267ff92998
80 changed files with 5555 additions and 1254 deletions

View File

@@ -2,8 +2,6 @@ package logger
import (
"context"
"fmt"
"os"
"path/filepath"
"time"
@@ -12,303 +10,219 @@ import (
"gopkg.in/natefinch/lumberjack.v2"
)
// LevelLoggerConfig 按级别分文件日志配置
// LevelLogger 级别分文件日志器 - 基于 Zap 官方推荐
type LevelLogger struct {
logger *zap.Logger
levelLoggers map[zapcore.Level]*zap.Logger
config LevelLoggerConfig
}
// LevelLoggerConfig 级别分文件日志器配置
type LevelLoggerConfig struct {
BaseConfig Config
// 是否启用按级别分文件
BaseConfig Config
EnableLevelSeparation bool
// 各级别日志文件配置
LevelConfigs map[zapcore.Level]LevelFileConfig
LevelConfigs map[zapcore.Level]LevelFileConfig
}
// LevelFileConfig 单个级别文件配置
type LevelFileConfig struct {
MaxSize int // 单个文件最大大小(MB)
MaxBackups int // 最大备份文件数
MaxAge int // 最大保留天数
Compress bool // 是否压缩
MaxSize int `mapstructure:"max_size"`
MaxBackups int `mapstructure:"max_backups"`
MaxAge int `mapstructure:"max_age"`
Compress bool `mapstructure:"compress"`
}
// LevelLogger 级别分文件日志器
type LevelLogger struct {
loggers map[zapcore.Level]*zap.Logger
config LevelLoggerConfig
}
// NewLevelLogger 创建级别分文件日志器
func NewLevelLogger(config LevelLoggerConfig) (Logger, error) {
// 根据环境创建基础日志器
var baseLogger *zap.Logger
var err error
// NewLevelLogger 创建按级别分文件的日志器
func NewLevelLogger(config LevelLoggerConfig) (*LevelLogger, error) {
if !config.EnableLevelSeparation {
// 如果不启用按级别分文件,使用普通日志器
normalLogger, err := NewLogger(config.BaseConfig)
if err != nil {
return nil, err
}
// 转换为LevelLogger格式
zapLogger := normalLogger.(*ZapLogger).GetZapLogger()
return &LevelLogger{
loggers: map[zapcore.Level]*zap.Logger{
zapcore.DebugLevel: zapLogger,
zapcore.InfoLevel: zapLogger,
zapcore.WarnLevel: zapLogger,
zapcore.ErrorLevel: zapLogger,
zapcore.FatalLevel: zapLogger,
zapcore.PanicLevel: zapLogger,
},
config: config,
}, nil
}
// 设置默认级别配置
if config.LevelConfigs == nil {
config.LevelConfigs = getDefaultLevelConfigs()
}
// 确保日志目录存在
if err := os.MkdirAll(config.BaseConfig.LogDir, 0755); err != nil {
return nil, fmt.Errorf("创建日志目录失败: %w", err)
}
// 为每个级别创建独立的日志器
loggers := make(map[zapcore.Level]*zap.Logger)
for level := range config.LevelConfigs {
logger, err := createLevelLogger(level, config)
if err != nil {
return nil, fmt.Errorf("创建级别日志器失败 [%s]: %w", level.String(), err)
}
loggers[level] = logger
}
return &LevelLogger{
loggers: loggers,
config: config,
}, nil
}
// getDefaultLevelConfigs 获取默认级别配置
func getDefaultLevelConfigs() map[zapcore.Level]LevelFileConfig {
return map[zapcore.Level]LevelFileConfig{
zapcore.DebugLevel: {
MaxSize: 50, // 50MB
MaxBackups: 3,
MaxAge: 7, // 7天
Compress: true,
},
zapcore.InfoLevel: {
MaxSize: 100, // 100MB
MaxBackups: 5,
MaxAge: 30, // 30天
Compress: true,
},
zapcore.WarnLevel: {
MaxSize: 100, // 100MB
MaxBackups: 5,
MaxAge: 30, // 30天
Compress: true,
},
zapcore.ErrorLevel: {
MaxSize: 200, // 200MB
MaxBackups: 10,
MaxAge: 90, // 90天
Compress: true,
},
zapcore.FatalLevel: {
MaxSize: 100, // 100MB
MaxBackups: 10,
MaxAge: 365, // 1年
Compress: true,
},
zapcore.PanicLevel: {
MaxSize: 100, // 100MB
MaxBackups: 10,
MaxAge: 365, // 1年
Compress: true,
},
}
}
// createLevelLogger 为单个级别创建日志器
func createLevelLogger(level zapcore.Level, config LevelLoggerConfig) (*zap.Logger, error) {
levelConfig := config.LevelConfigs[level]
// 创建编码器
encoderConfig := getEncoderConfig()
var encoder zapcore.Encoder
if config.BaseConfig.Format == "json" {
encoder = zapcore.NewJSONEncoder(encoderConfig)
if config.BaseConfig.Development {
baseLogger, err = zap.NewDevelopment(
zap.AddCaller(),
zap.AddCallerSkip(1),
zap.AddStacktrace(zapcore.ErrorLevel),
)
} else {
encoder = zapcore.NewConsoleEncoder(encoderConfig)
baseLogger, err = zap.NewProduction(
zap.AddCaller(),
zap.AddCallerSkip(1),
zap.AddStacktrace(zapcore.ErrorLevel),
)
}
// 创建文件输出
writeSyncer, err := createLevelFileWriteSyncer(level, config.BaseConfig, levelConfig)
if err != nil {
return nil, err
}
// 创建核心
core := zapcore.NewCore(encoder, writeSyncer, level)
// 创建级别分文件的日志器
levelLogger := &LevelLogger{
logger: baseLogger,
levelLoggers: make(map[zapcore.Level]*zap.Logger),
config: config,
}
// 创建日志器
logger := zap.New(core, zap.AddCaller(), zap.AddStacktrace(zapcore.ErrorLevel))
// 为每个级别创建专门的日志器
if config.EnableLevelSeparation {
levelLogger.createLevelLoggers()
}
return logger, nil
return levelLogger, nil
}
// createLevelFileWriteSyncer 创建级别文件输出同步
func createLevelFileWriteSyncer(level zapcore.Level, baseConfig Config, levelConfig LevelFileConfig) (zapcore.WriteSyncer, error) {
// 构建日志文件路径
// createLevelLoggers 创建级别的日志
func (l *LevelLogger) createLevelLoggers() {
levels := []zapcore.Level{
zapcore.DebugLevel,
zapcore.InfoLevel,
zapcore.WarnLevel,
zapcore.ErrorLevel,
zapcore.FatalLevel,
zapcore.PanicLevel,
}
for _, level := range levels {
// 获取该级别的配置
levelConfig, exists := l.config.LevelConfigs[level]
if !exists {
// 如果没有配置,使用默认配置
levelConfig = LevelFileConfig{
MaxSize: 100,
MaxBackups: 5,
MaxAge: 30,
Compress: true,
}
}
// 创建该级别的文件输出
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),
)
l.levelLoggers[level] = levelLogger
}
}
// createLevelWriteSyncer 创建级别特定的文件输出同步器
func (l *LevelLogger) createLevelWriteSyncer(level zapcore.Level, config LevelFileConfig) zapcore.WriteSyncer {
// 构建文件路径
var logFilePath string
if baseConfig.UseDaily {
// 按日分包logs/2024-01-01/error.log
today := time.Now().Format("2006-01-02")
dailyDir := filepath.Join(baseConfig.LogDir, today)
if err := os.MkdirAll(dailyDir, 0755); err != nil {
return nil, fmt.Errorf("创建日期目录失败: %w", err)
}
logFilePath = filepath.Join(dailyDir, fmt.Sprintf("%s.log", level.String()))
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")
} else {
// 传统方式logs/error.log
logFilePath = filepath.Join(baseConfig.LogDir, fmt.Sprintf("%s.log", level.String()))
// 传统方式logs/debug.log
levelName := level.String()
logFilePath = filepath.Join(l.config.BaseConfig.LogDir, levelName+".log")
}
// 创建lumberjack日志轮转器
lumberJackLogger := &lumberjack.Logger{
// 创建 lumberjack 日志轮转器
rotator := &lumberjack.Logger{
Filename: logFilePath,
MaxSize: levelConfig.MaxSize,
MaxBackups: levelConfig.MaxBackups,
MaxAge: levelConfig.MaxAge,
Compress: levelConfig.Compress,
MaxSize: config.MaxSize,
MaxBackups: config.MaxBackups,
MaxAge: config.MaxAge,
Compress: config.Compress,
}
return zapcore.AddSync(lumberJackLogger), nil
}
// Debug 调试日志
func (l *LevelLogger) Debug(msg string, fields ...zapcore.Field) {
if logger, exists := l.loggers[zapcore.DebugLevel]; exists {
logger.Debug(msg, fields...)
}
}
// Info 信息日志
func (l *LevelLogger) Info(msg string, fields ...zapcore.Field) {
if logger, exists := l.loggers[zapcore.InfoLevel]; exists {
logger.Info(msg, fields...)
}
}
// Warn 警告日志
func (l *LevelLogger) Warn(msg string, fields ...zapcore.Field) {
if logger, exists := l.loggers[zapcore.WarnLevel]; exists {
logger.Warn(msg, fields...)
}
}
// Error 错误日志
func (l *LevelLogger) Error(msg string, fields ...zapcore.Field) {
if logger, exists := l.loggers[zapcore.ErrorLevel]; exists {
logger.Error(msg, fields...)
}
}
// Fatal 致命错误日志
func (l *LevelLogger) Fatal(msg string, fields ...zapcore.Field) {
if logger, exists := l.loggers[zapcore.FatalLevel]; exists {
logger.Fatal(msg, fields...)
}
}
// Panic 恐慌日志
func (l *LevelLogger) Panic(msg string, fields ...zapcore.Field) {
if logger, exists := l.loggers[zapcore.PanicLevel]; exists {
logger.Panic(msg, fields...)
}
}
// With 添加字段
func (l *LevelLogger) With(fields ...zapcore.Field) Logger {
// 为每个级别创建带字段的日志器
newLoggers := make(map[zapcore.Level]*zap.Logger)
for level, logger := range l.loggers {
newLoggers[level] = logger.With(fields...)
}
return &LevelLogger{
loggers: newLoggers,
config: l.config,
}
}
// WithContext 从上下文添加字段
func (l *LevelLogger) WithContext(ctx context.Context) Logger {
// 从上下文中提取常用字段
fields := []zapcore.Field{}
if traceID := getTraceIDFromContextLevel(ctx); traceID != "" {
fields = append(fields, zap.String("trace_id", traceID))
}
if userID := getUserIDFromContextLevel(ctx); userID != "" {
fields = append(fields, zap.String("user_id", userID))
}
if requestID := getRequestIDFromContextLevel(ctx); requestID != "" {
fields = append(fields, zap.String("request_id", requestID))
}
return l.With(fields...)
}
// Sync 同步日志
func (l *LevelLogger) Sync() error {
var lastErr error
for _, logger := range l.loggers {
if err := logger.Sync(); err != nil {
lastErr = err
}
}
return lastErr
return zapcore.AddSync(rotator)
}
// GetLevelLogger 获取指定级别的日志器
func (l *LevelLogger) GetLevelLogger(level zapcore.Level) *zap.Logger {
if logger, exists := l.loggers[level]; exists {
if logger, exists := l.levelLoggers[level]; exists {
return logger
}
return nil
return l.logger
}
// GetLoggers 获取所有级别的日志器
func (l *LevelLogger) GetLoggers() map[zapcore.Level]*zap.Logger {
return l.loggers
// 实现 Logger 接口
func (l *LevelLogger) Debug(msg string, fields ...zapcore.Field) {
if logger := l.GetLevelLogger(zapcore.DebugLevel); logger != nil {
logger.Debug(msg, fields...)
}
}
// 辅助函数从logger.go复制
func getTraceIDFromContextLevel(ctx context.Context) string {
if traceID := ctx.Value("trace_id"); traceID != nil {
if id, ok := traceID.(string); ok {
return id
func (l *LevelLogger) Info(msg string, fields ...zapcore.Field) {
if logger := l.GetLevelLogger(zapcore.InfoLevel); logger != nil {
logger.Info(msg, fields...)
}
}
func (l *LevelLogger) Warn(msg string, fields ...zapcore.Field) {
if logger := l.GetLevelLogger(zapcore.WarnLevel); logger != nil {
logger.Warn(msg, fields...)
}
}
func (l *LevelLogger) Error(msg string, fields ...zapcore.Field) {
if logger := l.GetLevelLogger(zapcore.ErrorLevel); logger != nil {
logger.Error(msg, fields...)
}
}
func (l *LevelLogger) Fatal(msg string, fields ...zapcore.Field) {
if logger := l.GetLevelLogger(zapcore.FatalLevel); logger != nil {
logger.Fatal(msg, fields...)
}
}
func (l *LevelLogger) Panic(msg string, fields ...zapcore.Field) {
if logger := l.GetLevelLogger(zapcore.PanicLevel); logger != nil {
logger.Panic(msg, fields...)
}
}
func (l *LevelLogger) With(fields ...zapcore.Field) Logger {
// 为所有级别添加字段
for level, logger := range l.levelLoggers {
l.levelLoggers[level] = logger.With(fields...)
}
return l
}
func (l *LevelLogger) WithContext(ctx context.Context) Logger {
// 从上下文提取字段
fields := extractFieldsFromContext(ctx)
return l.With(fields...)
}
func (l *LevelLogger) Named(name string) Logger {
// 为所有级别添加名称
for level, logger := range l.levelLoggers {
l.levelLoggers[level] = logger.Named(name)
}
return l
}
func (l *LevelLogger) Sync() error {
// 同步所有级别的日志器
for _, logger := range l.levelLoggers {
if err := logger.Sync(); err != nil {
return err
}
}
return ""
return l.logger.Sync()
}
func getUserIDFromContextLevel(ctx context.Context) string {
if userID := ctx.Value("user_id"); userID != nil {
if id, ok := userID.(string); ok {
return id
}
}
return ""
func (l *LevelLogger) Core() zapcore.Core {
return l.logger.Core()
}
func getRequestIDFromContextLevel(ctx context.Context) string {
if requestID := ctx.Value("request_id"); requestID != nil {
if id, ok := requestID.(string); ok {
return id
}
}
return ""
}
func (l *LevelLogger) GetZapLogger() *zap.Logger {
return l.logger
}