Golang Zap日誌
阿新 • • 發佈:2022-04-21
Zap日誌解析
Config.yaml
zap: level: 'info' #日誌級別 format: 'console' #輸出的級別,有console和json prefix: '[catering]' #輸出的字首,[catering]xxxxxxxxxxx director: 'log' #存放的資料夾 show-line: true #是否顯示行號 encode-level: 'LowercaseColorLevelEncoder' #編碼級別,目前支援四種LowercaseLevelEncoder,LowercaseColorLevelEncoder,CapitalLevelEncoder,CapitalColorLevelEncoder stacktrace-key: 'stacktrace' #棧名 log-in-console: true #輸出控制檯
配置檔案
package config type Zap struct { Level string `mapstructure:"level" json:"level" yaml:"level"` // 級別 Format string `mapstructure:"format" json:"format" yaml:"format"` // 輸出 Prefix string `mapstructure:"prefix" json:"prefix" yaml:"prefix"` // 日誌字首 Director string `mapstructure:"director" json:"director" yaml:"director"` // 日誌資料夾 ShowLine bool `mapstructure:"show-line" json:"showLine" yaml:"showLine"` // 顯示行 EncodeLevel string `mapstructure:"encode-level" json:"encodeLevel" yaml:"encode-level"` // 編碼級 StacktraceKey string `mapstructure:"stacktrace-key" json:"stacktraceKey" yaml:"stacktrace-key"` // 棧名 LogInConsole bool `mapstructure:"log-in-console" json:"logInConsole" yaml:"log-in-console"` // 輸出控制檯 }
初始化
func InitZap() { cfg := global.Config.Zap //獲取上述的配置檔案 // 判斷是否有Director資料夾 if ok, _ := pkg.PathExists(cfg.Director); !ok { fmt.Printf("create %v directory\n", cfg.Director) _ = os.Mkdir(cfg.Director, os.ModePerm) } // zap.LevelEnablerFunc(func(lev zapcore.Level) bool 用來劃分不同級別的輸出 // 根據不同的級別輸出到不同的日誌檔案 // 除錯級別 debugPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev == zap.DebugLevel }) // 日誌級別 infoPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev == zap.InfoLevel }) // 警告級別 warnPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev == zap.WarnLevel }) // 錯誤級別 errorPriority := zap.LevelEnablerFunc(func(lev zapcore.Level) bool { return lev >= zap.ErrorLevel }) cores := [...]zapcore.Core{ getEncoderCore(fmt.Sprintf("./%s/server_debug.log", cfg.Director), debugPriority), getEncoderCore(fmt.Sprintf("./%s/server_info.log", cfg.Director), infoPriority), getEncoderCore(fmt.Sprintf("./%s/server_warn.log", cfg.Director), warnPriority), getEncoderCore(fmt.Sprintf("./%s/server_error.log", cfg.Director), errorPriority), } //zapcore.NewTee(cores ...zapcore.Core) zapcore.Core //NewTee建立一個Core,將日誌條目複製到兩個或更多的底層Core中 logger := zap.New(zapcore.NewTee(cores[:]...)) //用檔名、行號和zap呼叫者的函式名註釋每條訊息 if cfg.ShowLine { logger = logger.WithOptions(zap.AddCaller()) } //把初始化好的logger賦值到全域性日誌變數中 global.Log = logger }
getEncoderCode函式
// getEncoderCore 獲取Encoder的zapcore.Core
func getEncoderCore(fileName string, level zapcore.LevelEnabler) (core zapcore.Core) {
writer := pkg.GetWriteSyncer(fileName) // 使用file-rotatelogs進行日誌分割
return zapcore.NewCore(getEncoder(), writer, level)
}
getEncoder函式
// getEncoder 獲取zapcore.Encoder
func getEncoder() zapcore.Encoder {
//獲取配置檔案的輸出格式,json or console
cfg := global.Config.Zap
if cfg.Format == "json" {
return zapcore.NewJSONEncoder(getEncoderConfig())
}
return zapcore.NewConsoleEncoder(getEncoderConfig())
}
getEncoderConfig函式
獲取自定義的編碼器的配置
// getEncoderConfig 獲取zapcore.EncoderConfig
func getEncoderConfig() (config zapcore.EncoderConfig) {
cfg := global.Config.Zap
config = zapcore.EncoderConfig{
MessageKey: "message",
LevelKey: "level",
TimeKey: "time",
NameKey: "logger",
CallerKey: "caller",
StacktraceKey: cfg.StacktraceKey, //棧名
LineEnding: zapcore.DefaultLineEnding, //預設的結尾\n
EncodeLevel: zapcore.LowercaseLevelEncoder, //小寫字母輸出
EncodeTime: CustomTimeEncoder, //自定義時間格式
EncodeDuration: zapcore.SecondsDurationEncoder, //編碼間隔 s
EncodeCaller: zapcore.FullCallerEncoder, //控制列印的檔案位置是絕對路徑,ShortCallerEncoder 是相對路徑
}
//根據配置檔案重新配置編碼顏色和字型
switch {
case cfg.EncodeLevel == "LowercaseLevelEncoder": // 小寫編碼器(預設)
config.EncodeLevel = zapcore.LowercaseLevelEncoder
case cfg.EncodeLevel == "LowercaseColorLevelEncoder": // 小寫編碼器帶顏色
config.EncodeLevel = zapcore.LowercaseColorLevelEncoder
case cfg.EncodeLevel == "CapitalLevelEncoder": // 大寫編碼器
config.EncodeLevel = zapcore.CapitalLevelEncoder
case cfg.EncodeLevel == "CapitalColorLevelEncoder": // 大寫編碼器帶顏色
config.EncodeLevel = zapcore.CapitalColorLevelEncoder
default:
config.EncodeLevel = zapcore.LowercaseLevelEncoder
}
return config
}
CustomTimeEncoder函式
用於自定義日誌字首的輸出格式
// 自定義日誌輸出時間格式
// 輸出格式為 prfix + 具體的時間日期
func CustomTimeEncoder(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
cfg := global.Config.Zap
enc.AppendString(t.Format(cfg.Prefix + "2006-01-02 15:04:05.000"))
}
pkg.GetWriteSyncer函式
用於切割檔案,防止日誌檔案過大
func GetWriteSyncer(file string) zapcore.WriteSyncer {
lumberJackLogger := &lumberjack.Logger{
Filename: file, // 日誌檔案的位置
MaxSize: 10, // 在進行切割之前,日誌檔案的最大大小(以MB為單位)
MaxBackups: 200, // 保留舊檔案的最大個數
MaxAge: 30, // 保留舊檔案的最大天數
Compress: true, // 是否壓縮/歸檔舊檔案
}
if global.Config.Zap.LogInConsole {
return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger))
}
return zapcore.AddSync(lumberJackLogger)
}
用法
虛擬碼,切勿直接貼上複製
package global
var log *zap.Logger
package main
import (
"catering/initialize"
"catering/global"
)
func main() {
initialize.InitZap()
global.log.Info("test")
}
列印日誌示例
log
├── server_error.log
├── server_info.log
server_info.log
[catering]2022-03-17 17:36:42.200 [34minfo[0m E:/GoPath/project/go-catering/admin/initialize/router.go:32 use middleware logger
[catering]2022-03-17 17:36:42.201 [34minfo[0m E:/GoPath/project/go-catering/admin/initialize/router.go:36 use middleware cors
[catering]2022-03-17 17:36:42.201 [34minfo[0m E:/GoPath/project/go-catering/admin/initialize/router.go:38 register swagger handler
[catering]2022-03-17 17:36:42.225 [34minfo[0m E:/GoPath/project/go-catering/admin/initialize/router.go:104 router register success
[catering]2022-03-17 17:36:42.228 [34minfo[0m E:/GoPath/project/go-catering/admin/core/server.go:27 server run success on {"address": ":8888"}
server_error.log
[catering]2022-03-09 21:35:33.812 [31merror[0m D:/goProject/src/catering/admin/pkg/app/request.go:13 Id.Required. {"message": "Id Can not be empty"}
[catering]2022-03-09 21:35:33.813 [31merror[0m D:/goProject/src/catering/admin/pkg/app/request.go:13 LevelName.Required. {"message": "LevelName Can not be empty"}
[catering]2022-03-09 21:35:33.813 [31merror[0m D:/goProject/src/catering/admin/pkg/app/request.go:13 UpNeedIntegration.Required. {"message": "UpNeedIntegration Can not be empty"}