package initializeimport ( "encoding/json" "github.com/tidwall/gjson" "github.com/tidwall/sjson" "go.uber.org/zap" "go.uber.org/zap/zapcore" "golang.org/x/net/context" "gopkg.in/natefinch/lumberjack.v2" "notification_service/global" "os" "time")func InitLogger() { development := os.Getenv("DEVELOPMENT") if development == "1" { // 如果是开发环境 initDevelopmentLogger() } else { initProductionLogger() }}func initDevelopmentLogger() { config := zap.NewDevelopmentConfig() logger, err := config.Build(zap.AddCaller()) if err != nil { panic(err) } zap.ReplaceGlobals(logger)}func initProductionLogger() { encoderConfig := zap.NewProductionEncoderConfig() // 获取编码器 encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 使用 ISO-8601 时间格式 encoderConfig.TimeKey = "time" encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 日志级别记为大写 encoder := zapcore.NewJSONEncoder(encoderConfig) // NewJSONEncoder:json 格式输出。如果是 NewConsoleEncoder,则以字符串格式输出 infoLogLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { // 该日志等级函数记录 INFO 及以上级别的日志 return lvl >= zap.InfoLevel }) errorLogLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { // 该日志等级函数记录 ERROR 及以上级别的日志 return lvl >= zap.ErrorLevel }) infoFileSyncer := zapcore.AddSync(&lumberjack.Logger{ Filename: "./log/info.log", // 日志文件存放目录,如果目录不存在会自动创建 MaxSize: 50, // 文件大小限制,单位:MB MaxBackups: 200, // 最大保留日志文件数量 MaxAge: 180, // 日志文件保留天数 Compress: false, // 是否压缩处理 }) errorFileSyncer := zapcore.AddSync(&lumberjack.Logger{ Filename: "./log/error.log", MaxSize: 50, MaxBackups: 200, MaxAge: 180, Compress: false, }) redisSyncer := zapcore.AddSync(&RedisLogger{}) // 日志存入 Redis infoCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileSyncer, redisSyncer), infoLogLevel) errorCore := zapcore.NewCore(encoder, errorFileSyncer, errorLogLevel) logger := zap.New(zapcore.NewTee(infoCore, errorCore), zap.AddCaller()) // zap.AddCaller():显示文件名和行号 zap.ReplaceGlobals(logger) // 替换全局 logger}type RedisLogger struct{} // 需要实现 io.Writer 接口func (*RedisLogger) Write(p []byte) (n int, err error) { // 实现 io.Writer 接口即实现 Write 方法 log := string(p) if gjson.Get(log, "trace_id").String() == "" { // 如果日志中不包含 trace_id return } var redisLog string if gjson.Get(log, "log_type").String() == "access_log" { type AccessLog struct { TraceID string `json:"trace_id,omitempty"` Time string `json:"time,omitempty"` Timestamp int64 `json:"timestamp,omitempty"` LogType string `json:"log_type,omitempty"` ClientID string `json:"client_id,omitempty"` RequestURI string `json:"request_uri,omitempty"` RequestMethod string `json:"request_method,omitempty"` RequestHeaders string `json:"request_headers,omitempty"` RequestBody string `json:"request_body,omitempty"` ResponseBody string `json:"response_body,omitempty"` NotificationType string `json:"notification_type,omitempty"` Receivers []string `json:"receivers,omitempty"` } accessLog := AccessLog{} _ = json.Unmarshal(p, &accessLog) t, _ := time.ParseInLocation("2006-01-02T15:04:05+0800", accessLog.Time, time.Local) accessLog.Time = "" accessLog.Timestamp = t.UnixMilli() redisLogBytes, _ := json.Marshal(accessLog) redisLog = string(redisLogBytes) } else { redisLog, _ = sjson.Set(redisLog, "trace_id", gjson.Get(log, "trace_id").String()) t, _ := time.ParseInLocation("2006-01-02T15:04:05+0800", gjson.Get(log, "time").String(), time.Local) redisLog, _ = sjson.Set(redisLog, "timestamp", t.UnixMilli()) redisLog, _ = sjson.Set(redisLog, "log_type", "exec_log") log, _ = sjson.Delete(log, "level") log, _ = sjson.Delete(log, "time") log, _ = sjson.Delete(log, "caller") log, _ = sjson.Delete(log, "msg") log, _ = sjson.Delete(log, "trace_id") redisLog, _ = sjson.Set(redisLog, "log_content", log) } global.Redis.RPush(context.Background(), "notification_service_log", redisLog) return}