1. package initialize
    2. import (
    3. "encoding/json"
    4. "github.com/tidwall/gjson"
    5. "github.com/tidwall/sjson"
    6. "go.uber.org/zap"
    7. "go.uber.org/zap/zapcore"
    8. "golang.org/x/net/context"
    9. "gopkg.in/natefinch/lumberjack.v2"
    10. "notification_service/global"
    11. "os"
    12. "time"
    13. )
    14. func InitLogger() {
    15. development := os.Getenv("DEVELOPMENT")
    16. if development == "1" { // 如果是开发环境
    17. initDevelopmentLogger()
    18. } else {
    19. initProductionLogger()
    20. }
    21. }
    22. func initDevelopmentLogger() {
    23. config := zap.NewDevelopmentConfig()
    24. logger, err := config.Build(zap.AddCaller())
    25. if err != nil {
    26. panic(err)
    27. }
    28. zap.ReplaceGlobals(logger)
    29. }
    30. func initProductionLogger() {
    31. encoderConfig := zap.NewProductionEncoderConfig() // 获取编码器
    32. encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 使用 ISO-8601 时间格式
    33. encoderConfig.TimeKey = "time"
    34. encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder // 日志级别记为大写
    35. encoder := zapcore.NewJSONEncoder(encoderConfig) // NewJSONEncoder:json 格式输出。如果是 NewConsoleEncoder,则以字符串格式输出
    36. infoLogLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { // 该日志等级函数记录 INFO 及以上级别的日志
    37. return lvl >= zap.InfoLevel
    38. })
    39. errorLogLevel := zap.LevelEnablerFunc(func(lvl zapcore.Level) bool { // 该日志等级函数记录 ERROR 及以上级别的日志
    40. return lvl >= zap.ErrorLevel
    41. })
    42. infoFileSyncer := zapcore.AddSync(&lumberjack.Logger{
    43. Filename: "./log/info.log", // 日志文件存放目录,如果目录不存在会自动创建
    44. MaxSize: 50, // 文件大小限制,单位:MB
    45. MaxBackups: 200, // 最大保留日志文件数量
    46. MaxAge: 180, // 日志文件保留天数
    47. Compress: false, // 是否压缩处理
    48. })
    49. errorFileSyncer := zapcore.AddSync(&lumberjack.Logger{
    50. Filename: "./log/error.log",
    51. MaxSize: 50,
    52. MaxBackups: 200,
    53. MaxAge: 180,
    54. Compress: false,
    55. })
    56. redisSyncer := zapcore.AddSync(&RedisLogger{}) // 日志存入 Redis
    57. infoCore := zapcore.NewCore(encoder, zapcore.NewMultiWriteSyncer(infoFileSyncer, redisSyncer), infoLogLevel)
    58. errorCore := zapcore.NewCore(encoder, errorFileSyncer, errorLogLevel)
    59. logger := zap.New(zapcore.NewTee(infoCore, errorCore), zap.AddCaller()) // zap.AddCaller():显示文件名和行号
    60. zap.ReplaceGlobals(logger) // 替换全局 logger
    61. }
    62. type RedisLogger struct{} // 需要实现 io.Writer 接口
    63. func (*RedisLogger) Write(p []byte) (n int, err error) { // 实现 io.Writer 接口即实现 Write 方法
    64. log := string(p)
    65. if gjson.Get(log, "trace_id").String() == "" { // 如果日志中不包含 trace_id
    66. return
    67. }
    68. var redisLog string
    69. if gjson.Get(log, "log_type").String() == "access_log" {
    70. type AccessLog struct {
    71. TraceID string `json:"trace_id,omitempty"`
    72. Time string `json:"time,omitempty"`
    73. Timestamp int64 `json:"timestamp,omitempty"`
    74. LogType string `json:"log_type,omitempty"`
    75. ClientID string `json:"client_id,omitempty"`
    76. RequestURI string `json:"request_uri,omitempty"`
    77. RequestMethod string `json:"request_method,omitempty"`
    78. RequestHeaders string `json:"request_headers,omitempty"`
    79. RequestBody string `json:"request_body,omitempty"`
    80. ResponseBody string `json:"response_body,omitempty"`
    81. NotificationType string `json:"notification_type,omitempty"`
    82. Receivers []string `json:"receivers,omitempty"`
    83. }
    84. accessLog := AccessLog{}
    85. _ = json.Unmarshal(p, &accessLog)
    86. t, _ := time.ParseInLocation("2006-01-02T15:04:05+0800", accessLog.Time, time.Local)
    87. accessLog.Time = ""
    88. accessLog.Timestamp = t.UnixMilli()
    89. redisLogBytes, _ := json.Marshal(accessLog)
    90. redisLog = string(redisLogBytes)
    91. } else {
    92. redisLog, _ = sjson.Set(redisLog, "trace_id", gjson.Get(log, "trace_id").String())
    93. t, _ := time.ParseInLocation("2006-01-02T15:04:05+0800", gjson.Get(log, "time").String(), time.Local)
    94. redisLog, _ = sjson.Set(redisLog, "timestamp", t.UnixMilli())
    95. redisLog, _ = sjson.Set(redisLog, "log_type", "exec_log")
    96. log, _ = sjson.Delete(log, "level")
    97. log, _ = sjson.Delete(log, "time")
    98. log, _ = sjson.Delete(log, "caller")
    99. log, _ = sjson.Delete(log, "msg")
    100. log, _ = sjson.Delete(log, "trace_id")
    101. redisLog, _ = sjson.Set(redisLog, "log_content", log)
    102. }
    103. global.Redis.RPush(context.Background(), "notification_service_log", redisLog)
    104. return
    105. }