Gin 集成: 集成高性能日誌 zap

1. 項目介紹

Gin框架學習使用, 並實踐常用包在Gin框架中的集成和使用。源碼地址: https://github.com/52lu/gin-import-template.git

1.1 項目結構

├── api # 接口
├── config # 配置
├── core # 核心代碼
├── global # 全局變量和常量
├── initialize # 初始化相關
├── logs # 日誌目錄
├── main.go # 啓動文件
├── model # 實體
├── router # 路由
    └── middleware #中間件
├── test # 單元測試目錄
└── utils # 工具包

1.2 集成流程

集成代碼流程

2. 安裝

# 安裝zap
go get -u go.uber.org/zap
# 安裝lumberjack(日誌切割和打包)
go get -u github.com/natefinch/lumberjack

3. 配置

3.1 編輯app.yaml

...
log:
  path: ./logs # 日誌文件目錄
  filePrefix: gin # 日誌文件前綴
  fileFormat: 2006-01-02 # 日誌文件名格式
  level: debug # 最低記錄級別
  writeWay: file # file/console/all
  outFormat: json # json/console
  zap:
    outFormat: json # json/
  lumberJack: # 日誌文件切割和壓縮
    maxSize: 1 # 單文件最大容量(單位MB)
    maxBackups: 3 # 保留舊文件的最大數量
    maxAge: 30 # 舊文件最多保存幾天
    compress: false #是否壓縮/歸檔舊文件
...

3.2 新增對應結構體

新建文件:config/log.go

package config
// 日誌信息
type log struct {
 Path       string     `yaml:"path"`
 Level      string     `yaml:"level"`
 FilePrefix string     `yaml:"filePrefix"`
 FileFormat string     `yaml:"fileFormat"`
 OutFormat  string     `yaml:"outFormat"`
 LumberJack lumberJack `yaml:"lumberJack"`
}
// 日誌切割
type lumberJack struct {
 MaxSize    int  `yaml:"maxSize"`    //單文件最大容量(單位MB)
 MaxBackups int  `yaml:"maxBackups"` // 保留舊文件的最大數量
 MaxAge     int  `yaml:"maxAge"`     // 舊文件最多保存幾天
 Compress   bool `yaml:"compress"`   // 是否壓縮/歸檔舊文件
}

3.3 嵌入主配置

// ServerConfig 配置信息
type ServerConfig struct {
  ....
 Log   log   `yaml:"log"` // 嵌入日誌配置
}

3.4 定義全局變量logger

編輯文件:global/global.go

// 變量
var (
 ...
 GvaLogger *zap.Logger         // 日誌
)

4. 具體代碼

4.1 集成入口 (InitLogger)

const (
 // 日誌輸出格式
 outJson = "json"
)
func InitLogger() {
 logConfig := global.GvaConfig.Log
 // 判斷日誌目錄是否存在
 if exist, _ := utils.DirExist(logConfig.Path); !exist {
  _ = utils.CreateDir(logConfig.Path)
 }
 // 設置輸出格式
 var encoder zapcore.Encoder
 if logConfig.OutFormat == outJson {
  encoder = zapcore.NewJSONEncoder(getEncoderConfig())
 } else {
  encoder = zapcore.NewConsoleEncoder(getEncoderConfig())
 }
 // 設置日誌文件切割
 writeSyncer := zapcore.AddSync(getLumberjackWriteSyncer())
 // 創建NewCore
 zapCore := zapcore.NewCore(encoder, writeSyncer, getLevel())
 // 創建logger
 logger := zap.New(zapCore)
 defer logger.Sync()
 // 賦值給全局變量
 global.GvaLogger = logger
}

4.2 獲取最低記錄級別

// 獲取最低記錄日誌級別
func getLevel() zapcore.Level {
 levelMap := map[string]zapcore.Level{
  "debug":  zapcore.DebugLevel,
  "info":   zapcore.InfoLevel,
  "warn":   zapcore.WarnLevel,
  "error":  zapcore.ErrorLevel,
  "dpanic": zapcore.DPanicLevel,
  "panic":  zapcore.PanicLevel,
  "fatal":  zapcore.FatalLevel,
 }
 if level, ok := levelMap[global.GvaConfig.Log.Level]; ok {
  return level
 }
  // 默認info級別
 return zapcore.InfoLevel
}

4.3 自定義日誌輸出字段

// 自定義日誌輸出字段
func getEncoderConfig() zapcore.EncoderConfig {
 config := zapcore.EncoderConfig{
  // Keys can be anything except the empty string.
  TimeKey:        "time",
  LevelKey:       "level",
  NameKey:        "logger",
  CallerKey:      "caller",
  FunctionKey:    zapcore.OmitKey,
  MessageKey:     "msg",
  StacktraceKey:  "S",
  LineEnding:     zapcore.DefaultLineEnding,
  EncodeLevel:    zapcore.CapitalLevelEncoder,
  EncodeTime:     getEncodeTime, // 自定義輸出時間格式
  EncodeDuration: zapcore.StringDurationEncoder,
  EncodeCaller:   zapcore.ShortCallerEncoder,
 }
 return config
}
// 定義日誌輸出時間格式
func getEncodeTime(t time.Time, enc zapcore.PrimitiveArrayEncoder) {
 enc.AppendString(t.Format("2006/01/02 - 15:04:05.000"))
}

效果如下:

# 默認
{"L":"INFO","T":"2021-07-06T11:59:10.763+0800","M":"Info記錄","name":"張三"}
# 自定義後
{"level":"INFO","time":"2021/07/06 - 11:59:29.906","msg":"Info記錄","name":"張三"}

4.4 日誌文件切割

// 獲取文件切割和歸檔配置信息
func getLumberjackWriteSyncer() zapcore.WriteSyncer {
 lumberjackConfig := global.GvaConfig.Log.LumberJack
 lumberjackLogger := &lumberjack.Logger{
  Filename:   getLogFile(),                //日誌文件
  MaxSize:    lumberjackConfig.MaxSize,    //單文件最大容量(單位MB)
  MaxBackups: lumberjackConfig.MaxBackups, //保留舊文件的最大數量
  MaxAge:     lumberjackConfig.MaxAge,     // 舊文件最多保存幾天
  Compress:   lumberjackConfig.Compress,   // 是否壓縮/歸檔舊文件
 }
 // 設置日誌文件切割
 return zapcore.AddSync(lumberjackLogger)
}
// 獲取日誌文件名
func getLogFile() string {
 fileFormat := time.Now().Format(global.GvaConfig.Log.FileFormat)
 fileName := strings.Join([]string{
  global.GvaConfig.Log.FilePrefix,
  fileFormat,
  "log"}".")
 return path.Join(global.GvaConfig.Log.Path, fileName)
}

5. 測試驗證

// Sugar模式
global.GvaLogger.Sugar().Infof("日誌寫入測試: %v",strings.Repeat("hello",6))
// 默認模式
global.GvaLogger.Info("Info記錄",zap.String("name","張三"))
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/SaJQbKY6veFpp9q4C1U0Jg