從零封裝Gin框架實現(xiàn)日志初始化及切割歸檔功能
前言
本篇來講一下怎么將日志服務(wù)集成到項目中,它也是框架中必不可少的,平時代碼調(diào)試,線上 Bug 分析都離不開它。這里將使用 zap 作為日志庫,一般來說,日志都是需要寫入到文件保存的,這也是 zap 唯一缺少的部分,所以我將結(jié)合 lumberjack 來使用,實現(xiàn)日志切割歸檔的功能
安裝
go get -u go.uber.org/zap go get -u gopkg.in/natefinch/lumberjack.v2
定義日志配置項
新建 config/log.go 文件,定義 zap 和 lumberjack 初始化需要使用的配置項,大家可以根據(jù)自己的喜好去定制
package config
type Log struct {
Level string `mapstructure:"level" json:"level" yaml:"level"`
RootDir string `mapstructure:"root_dir" json:"root_dir" yaml:"root_dir"`
Filename string `mapstructure:"filename" json:"filename" yaml:"filename"`
Format string `mapstructure:"format" json:"format" yaml:"format"`
ShowLine bool `mapstructure:"show_line" json:"show_line" yaml:"show_line"`
MaxBackups int `mapstructure:"max_backups" json:"max_backups" yaml:"max_backups"`
MaxSize int `mapstructure:"max_size" json:"max_size" yaml:"max_size"` // MB
MaxAge int `mapstructure:"max_age" json:"max_age" yaml:"max_age"` // day
Compress bool `mapstructure:"compress" json:"compress" yaml:"compress"`
}config/config.go 添加 Log 成員屬性
package config
type Configuration struct {
App App `mapstructure:"app" json:"app" yaml:"app"`
Log Log `mapstructure:"log" json:"log" yaml:"log"`
}config.yaml 增加對應(yīng)配置項
log: level: info # 日志等級 root_dir: ./storage/logs # 日志根目錄 filename: app.log # 日志文件名稱 format: # 寫入格式 可選json show_line: true # 是否顯示調(diào)用行 max_backups: 3 # 舊文件的最大個數(shù) max_size: 500 # 日志文件最大大?。∕B) max_age: 28 # 舊文件的最大保留天數(shù) compress: true # 是否壓縮
定義 utils 工具函數(shù)
新建 utils/directory.go 文件,編寫 PathExists 函數(shù),用于判斷路徑是否存在
package utils
import "os"
func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
}初始化 zap
zap 的具體使用說明可查看官方文檔
新建 bootstrap/log.go 文件,編寫:
package bootstrap
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
"jassue-gin/global"
"jassue-gin/utils"
"os"
"time"
)
var (
level zapcore.Level // zap 日志等級
options []zap.Option // zap 配置項
)
func InitializeLog() *zap.Logger {
// 創(chuàng)建根目錄
createRootDir()
// 設(shè)置日志等級
setLogLevel()
if global.App.Config.Log.ShowLine {
options = append(options, zap.AddCaller())
}
// 初始化 zap
return zap.New(getZapCore(), options...)
}
func createRootDir() {
if ok, _ := utils.PathExists(global.App.Config.Log.RootDir); !ok {
_ = os.Mkdir(global.App.Config.Log.RootDir, os.ModePerm)
}
}
func setLogLevel() {
switch global.App.Config.Log.Level {
case "debug":
level = zap.DebugLevel
options = append(options, zap.AddStacktrace(level))
case "info":
level = zap.InfoLevel
case "warn":
level = zap.WarnLevel
case "error":
level = zap.ErrorLevel
options = append(options, zap.AddStacktrace(level))
case "dpanic":
level = zap.DPanicLevel
case "panic":
level = zap.PanicLevel
case "fatal":
level = zap.FatalLevel
default:
level = zap.InfoLevel
}
}
// 擴(kuò)展 Zap
func getZapCore() zapcore.Core {
var encoder zapcore.Encoder
// 調(diào)整編碼器默認(rèn)配置
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = func(time time.Time, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(time.Format("[" + "2006-01-02 15:04:05.000" + "]"))
}
encoderConfig.EncodeLevel = func(l zapcore.Level, encoder zapcore.PrimitiveArrayEncoder) {
encoder.AppendString(global.App.Config.App.Env + "." + l.String())
}
// 設(shè)置編碼器
if global.App.Config.Log.Format == "json" {
encoder = zapcore.NewJSONEncoder(encoderConfig)
} else {
encoder = zapcore.NewConsoleEncoder(encoderConfig)
}
return zapcore.NewCore(encoder, getLogWriter(), level)
}
// 使用 lumberjack 作為日志寫入器
func getLogWriter() zapcore.WriteSyncer {
file := &lumberjack.Logger{
Filename: global.App.Config.Log.RootDir + "/" + global.App.Config.Log.Filename,
MaxSize: global.App.Config.Log.MaxSize,
MaxBackups: global.App.Config.Log.MaxBackups,
MaxAge: global.App.Config.Log.MaxAge,
Compress: global.App.Config.Log.Compress,
}
return zapcore.AddSync(file)
}定義全局變量 Log
在 global/app.go 中,添加 Log 成員屬性
package global
import (
"github.com/spf13/viper"
"go.uber.org/zap"
"jassue-gin/config"
)
type Application struct {
ConfigViper *viper.Viper
Config config.Configuration
Log *zap.Logger
}
var App = new(Application)測試
在 main.go 中調(diào)用日志初始化函數(shù),并嘗試寫入日志
package main
import (
"github.com/gin-gonic/gin"
"jassue-gin/bootstrap"
"jassue-gin/global"
"net/http"
)
func main() {
// 初始化配置
bootstrap.InitializeConfig()
// 初始化日志
global.App.Log = bootstrap.InitializeLog()
global.App.Log.Info("log init success!")
r := gin.Default()
// 測試路由
r.GET("/ping", func(c *gin.Context) {
c.String(http.StatusOK, "log test")
})
// 啟動服務(wù)器
r.Run(":" + global.App.Config.App.Port)
}啟動 main.go ,生成 storage/logs/app.log 文件,表示日志初始化成功,文件內(nèi)容顯示如下:

以上就是從零封裝Gin框架實現(xiàn)日志初始化及切割歸檔功能的詳細(xì)內(nèi)容,更多關(guān)于Gin日志切割歸檔的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
golang通過反射手動實現(xiàn)json序列化的方法
在 Go 語言中,JSON 序列化和反序列化通常通過標(biāo)準(zhǔn)庫 encoding/json 來實現(xiàn),本文給大家介紹golang 通過反射手動實現(xiàn)json序列化的方法,感興趣的朋友一起看看吧2024-12-12
golang elasticsearch Client的使用詳解
這篇文章主要介紹了golang elasticsearch Client的使用詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-05-05
Golang實現(xiàn)請求限流的幾種辦法(小結(jié))
這篇文章主要介紹了Golang實現(xiàn)請求限流的幾種辦法(小結(jié)),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10
golang控制結(jié)構(gòu)select機(jī)制及使用示例詳解
這篇文章主要介紹了golang控制結(jié)構(gòu)select機(jī)制及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
go語言中基本數(shù)據(jù)類型及應(yīng)用快速了解
這篇文章主要為大家介紹了go語言中基本數(shù)據(jù)類型應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07

