從零封裝Gin框架實(shí)現(xiàn)日志初始化及切割歸檔功能
前言
本篇來(lái)講一下怎么將日志服務(wù)集成到項(xiàng)目中,它也是框架中必不可少的,平時(shí)代碼調(diào)試,線上 Bug 分析都離不開(kāi)它。這里將使用 zap 作為日志庫(kù),一般來(lái)說(shuō),日志都是需要寫入到文件保存的,這也是 zap 唯一缺少的部分,所以我將結(jié)合 lumberjack 來(lái)使用,實(shí)現(xiàn)日志切割歸檔的功能
安裝
go get -u go.uber.org/zap go get -u gopkg.in/natefinch/lumberjack.v2
定義日志配置項(xiàng)
新建 config/log.go
文件,定義 zap
和 lumberjack
初始化需要使用的配置項(xiàng),大家可以根據(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
增加對(duì)應(yīng)配置項(xiàng)
log: level: info # 日志等級(jí) root_dir: ./storage/logs # 日志根目錄 filename: app.log # 日志文件名稱 format: # 寫入格式 可選json show_line: true # 是否顯示調(diào)用行 max_backups: 3 # 舊文件的最大個(gè)數(shù) max_size: 500 # 日志文件最大大小(MB) 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
的具體使用說(shuō)明可查看官方文檔
新建 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 日志等級(jí) options []zap.Option // zap 配置項(xiàng) ) func InitializeLog() *zap.Logger { // 創(chuàng)建根目錄 createRootDir() // 設(shè)置日志等級(jí) 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)
測(cè)試
在 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() // 測(cè)試路由 r.GET("/ping", func(c *gin.Context) { c.String(http.StatusOK, "log test") }) // 啟動(dòng)服務(wù)器 r.Run(":" + global.App.Config.App.Port) }
啟動(dòng) main.go
,生成 storage/logs/app.log
文件,表示日志初始化成功,文件內(nèi)容顯示如下:
以上就是從零封裝Gin框架實(shí)現(xiàn)日志初始化及切割歸檔功能的詳細(xì)內(nèi)容,更多關(guān)于Gin日志切割歸檔的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Go編程中常見(jiàn)錯(cuò)誤和不良實(shí)踐解析
這篇文章主要為大家介紹了Go編程中常見(jiàn)錯(cuò)誤和不良實(shí)踐解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2024-01-01golang通過(guò)反射手動(dòng)實(shí)現(xiàn)json序列化的方法
在 Go 語(yǔ)言中,JSON 序列化和反序列化通常通過(guò)標(biāo)準(zhǔn)庫(kù) encoding/json 來(lái)實(shí)現(xiàn),本文給大家介紹golang 通過(guò)反射手動(dòng)實(shí)現(xiàn)json序列化的方法,感興趣的朋友一起看看吧2024-12-12Go語(yǔ)言字符串及strings和strconv包使用實(shí)例
字符串是工作中最常用的,值得我們專門的練習(xí)一下,下面這篇文章主要給大家介紹了關(guān)于Go語(yǔ)言字符串及strings和strconv包使用的相關(guān)資料,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下2024-06-06golang elasticsearch Client的使用詳解
這篇文章主要介紹了golang elasticsearch Client的使用詳解,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-05-05Golang實(shí)現(xiàn)請(qǐng)求限流的幾種辦法(小結(jié))
這篇文章主要介紹了Golang實(shí)現(xiàn)請(qǐng)求限流的幾種辦法(小結(jié)),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10golang控制結(jié)構(gòu)select機(jī)制及使用示例詳解
這篇文章主要介紹了golang控制結(jié)構(gòu)select機(jī)制及使用示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10go語(yǔ)言中基本數(shù)據(jù)類型及應(yīng)用快速了解
這篇文章主要為大家介紹了go語(yǔ)言中基本數(shù)據(jù)類型應(yīng)用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07