<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
在許多Go語言專案中,我們需要一個好的紀錄檔記錄器能夠提供下面這些功能:
在介紹Uber-go的zap包之前,讓我們先看看Go語言提供的基本紀錄檔功能。Go語言提供的預設紀錄檔包是https://golang.org/pkg/log/。
實現一個Go語言中的紀錄檔記錄器非常簡單——建立一個新的紀錄檔檔案,然後設定它為紀錄檔的輸出位置。
我們可以像下面的程式碼一樣設定紀錄檔記錄器
func SetupLogger() { logFileLocation, _ := os.OpenFile("/Users/q1mi/test.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, 0744) log.SetOutput(logFileLocation) }
讓我們來寫一些虛擬的程式碼來使用這個紀錄檔記錄器。
在當前的範例中,我們將建立一個到URL的HTTP連線,並將狀態程式碼/錯誤記錄到紀錄檔檔案中。
func simpleHttpGet(url string) { resp, err := http.Get(url) if err != nil { log.Printf("Error fetching url %s : %s", url, err.Error()) } else { log.Printf("Status Code for %s : %s", url, resp.Status) resp.Body.Close() } }
現在讓我們執行上面的程式碼並檢視紀錄檔記錄器的執行情況。
func main() { SetupLogger() simpleHttpGet("www.google.com") simpleHttpGet("http://www.google.com") }
當我們執行上面的程式碼,我們能看到一個test.log
檔案被建立,下面的內容會被新增到這個紀錄檔檔案中。
2019/05/24 01:14:13 Error fetching url www.google.com : Get www.google.com: unsupported protocol scheme "" 2019/05/24 01:14:14 Status Code for http://www.google.com : 200 OK
它最大的優點是使用非常簡單。我們可以設定任何io.Writer
作為紀錄檔記錄輸出並向其傳送要寫入的紀錄檔。
僅限基本的紀錄檔級別
只有一個Print
選項。不支援INFO
/DEBUG
等多個級別。
對於錯誤紀錄檔,它有fatal和Panic
os.Exit(1)
來結束程式缺乏紀錄檔格式化的能力——例如記錄呼叫者的函數名和行號,格式化日期和時間格式。等等。
不提供紀錄檔切割的能力。
Zap是非常快的、結構化的,分紀錄檔級別的Go紀錄檔庫。
根據Uber-go Zap的檔案,它的效能比類似的結構化紀錄檔包更好——也比標準庫更快。 以下是Zap釋出的基準測試資訊
記錄一條訊息和10個欄位:
Package | Time | Time % to zap | Objects Allocated |
---|---|---|---|
zap | 862 ns/op | +0% | 5 allocs/op |
zap (sugared) | 1250 ns/op | +45% | 11 allocs/op |
zerolog | 4021 ns/op | +366% | 76 allocs/op |
go-kit | 4542 ns/op | +427% | 105 allocs/op |
apex/log | 26785 ns/op | +3007% | 115 allocs/op |
logrus | 29501 ns/op | +3322% | 125 allocs/op |
log15 | 29906 ns/op | +3369% | 122 allocs/op |
記錄一個靜態字串,沒有任何上下文或printf風格的模板:
Package | Time | Time % to zap | Objects Allocated |
---|---|---|---|
zap | 118 ns/op | +0% | 0 allocs/op |
zap (sugared) | 191 ns/op | +62% | 2 allocs/op |
zerolog | 93 ns/op | -21% | 0 allocs/op |
go-kit | 280 ns/op | +137% | 11 allocs/op |
standard library | 499 ns/op | +323% | 2 allocs/op |
apex/log | 1990 ns/op | +1586% | 10 allocs/op |
logrus | 3129 ns/op | +2552% | 24 allocs/op |
log15 | 3887 ns/op | +3194% | 23 allocs/op |
執行下面的命令安裝zap
go get -u go.uber.org/zap
Zap提供了兩種型別的紀錄檔記錄器—Sugared Logger
和Logger
。
在效能很好但不是很關鍵的上下文中,使用SugaredLogger
。它比其他結構化紀錄檔記錄包快4-10倍,並且支援結構化和printf風格的紀錄檔記錄。
在每一微秒和每一次記憶體分配都很重要的上下文中,使用Logger
。它甚至比SugaredLogger
更快,記憶體分配次數也更少,但它只支援強型別的結構化紀錄檔記錄。
zap.NewProduction()
/zap.NewDevelopment()
或者zap.Example()
建立一個Logger。var logger *zap.Logger func main() { InitLogger() defer logger.Sync() simpleHttpGet("www.google.com") simpleHttpGet("http://www.google.com") } func InitLogger() { logger, _ = zap.NewProduction() } func simpleHttpGet(url string) { resp, err := http.Get(url) if err != nil { logger.Error( "Error fetching url..", zap.String("url", url), zap.Error(err)) } else { logger.Info("Success..", zap.String("statusCode", resp.Status), zap.String("url", url)) resp.Body.Close() } }
在上面的程式碼中,我們首先建立了一個Logger,然後使用Info/ Error等Logger方法記錄訊息。
紀錄檔記錄器方法的語法是這樣的:
func (log *Logger) MethodXXX(msg string, fields ...Field)
其中MethodXXX
是一個可變引數函數,可以是Info / Error/ Debug / Panic等。每個方法都接受一個訊息字串和任意數量的zapcore.Field
場引數。
每個zapcore.Field
其實就是一組鍵值對引數。
我們執行上面的程式碼會得到如下輸出結果:
{"level":"error","ts":1572159218.912792,"caller":"zap_demo/temp.go:25","msg":"Error fetching url..","url":"www.sogo.com","error":"Get www.sogo.com: unsupported protocol scheme ""","stacktrace":"main.simpleHttpGetnt/Users/q1mi/zap_demo/temp.go:25nmain.mainnt/Users/q1mi/zap_demo/temp.go:14nruntime.mainnt/usr/local/go/src/runtime/proc.go:203"} {"level":"info","ts":1572159219.1227388,"caller":"zap_demo/temp.go:30","msg":"Success..","statusCode":"200 OK","url":"http://www.sogo.com"}
現在讓我們使用Sugared Logger來實現相同的功能。
. Sugar()
方法來獲取一個SugaredLogger
。SugaredLogger
以printf
格式記錄語句下面是修改過後使用SugaredLogger
代替Logger
的程式碼:
var sugarLogger *zap.SugaredLogger func main() { InitLogger() defer sugarLogger.Sync() simpleHttpGet("www.google.com") simpleHttpGet("http://www.google.com") } func InitLogger() { logger, _ := zap.NewProduction() sugarLogger = logger.Sugar() } func simpleHttpGet(url string) { sugarLogger.Debugf("Trying to hit GET request for %s", url) resp, err := http.Get(url) if err != nil { sugarLogger.Errorf("Error fetching URL %s : Error = %s", url, err) } else { sugarLogger.Infof("Success! statusCode = %s for URL %s", resp.Status, url) resp.Body.Close() } }
當你執行上面的程式碼會得到如下輸出:
{"level":"error","ts":1572159149.923002,"caller":"logic/temp2.go:27","msg":"Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme ""","stacktrace":"main.simpleHttpGetnt/Users/q1mi/zap_demo/logic/temp2.go:27nmain.mainnt/Users/q1mi/zap_demo/logic/temp2.go:14nruntime.mainnt/usr/local/go/src/runtime/proc.go:203"} {"level":"info","ts":1572159150.192585,"caller":"logic/temp2.go:29","msg":"Success! statusCode = 200 OK for URL http://www.sogo.com"}
你應該注意到的了,到目前為止這兩個logger都列印輸出JSON結構格式。
在本部落格的後面部分,我們將更詳細地討論SugaredLogger,並瞭解如何進一步設定它。
我們要做的第一個更改是把紀錄檔寫入檔案,而不是列印到應用程式控制臺。
我們將使用zap.New(…)
方法來手動傳遞所有設定,而不是使用像zap.NewProduction()
這樣的預置方法來建立logger。
func New(core zapcore.Core, options ...Option) *Logger
zapcore.Core
需要三個設定
1.Encoder
:編碼器(如何寫入紀錄檔)。我們將使用開箱即用的NewJSONEncoder(),並使用預先設定的ProductionEncoderConfig()。
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
2.WriterSyncer
:指定紀錄檔將寫到哪裡去。我們使用zapcore.AddSync()函數並且將開啟的檔案控制程式碼傳進去。
file, _ := os.Create("./test.log") writeSyncer := zapcore.AddSync(file)
3.Log Level
:哪種級別的紀錄檔將被寫入。
我們將修改上述部分中的Logger程式碼,並重寫InitLogger()
方法。其餘方法—main()
/SimpleHttpGet()
保持不變。
func InitLogger() { writeSyncer := getLogWriter() encoder := getEncoder() core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) logger := zap.New(core) sugarLogger = logger.Sugar() } func getEncoder() zapcore.Encoder { return zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()) } func getLogWriter() zapcore.WriteSyncer { file, _ := os.Create("./test.log") return zapcore.AddSync(file) }
當使用這些修改過的logger設定呼叫上述部分的main()
函數時,以下輸出將列印在檔案——test.log
中。
{"level":"debug","ts":1572160754.994731,"msg":"Trying to hit GET request for www.sogo.com"} {"level":"error","ts":1572160754.994982,"msg":"Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme """} {"level":"debug","ts":1572160754.994996,"msg":"Trying to hit GET request for http://www.sogo.com"} {"level":"info","ts":1572160757.3755069,"msg":"Success! statusCode = 200 OK for URL http://www.sogo.com"}
現在,我們希望將編碼器從JSON Encoder更改為普通Encoder。為此,我們需要將NewJSONEncoder()
更改為NewConsoleEncoder()
。
return zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig())
當使用這些修改過的logger設定呼叫上述部分的main()
函數時,以下輸出將列印在檔案——test.log
中。
1.572161051846623e+09 debug Trying to hit GET request for www.sogo.com 1.572161051846828e+09 error Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme "" 1.5721610518468401e+09 debug Trying to hit GET request for http://www.sogo.com 1.572161052068744e+09 info Success! statusCode = 200 OK for URL http://www.sogo.com
鑑於我們對設定所做的更改,有下面兩個問題:
我們要做的第一件事是覆蓋預設的ProductionConfig()
,並進行以下更改:
func getEncoder() zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder return zapcore.NewConsoleEncoder(encoderConfig) }
接下來,我們將修改zap logger程式碼,新增將呼叫函數資訊記錄到紀錄檔中的功能。為此,我們將在zap.New(..)
函數中新增一個Option
。
logger := zap.New(core, zap.AddCaller())
當使用這些修改過的logger設定呼叫上述部分的main()
函數時,以下輸出將列印在檔案——test.log
中。
2019-10-27T15:33:29.855+0800 DEBUG logic/temp2.go:47 Trying to hit GET request for www.sogo.com 2019-10-27T15:33:29.855+0800 ERROR logic/temp2.go:50 Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme "" 2019-10-27T15:33:29.856+0800 DEBUG logic/temp2.go:47 Trying to hit GET request for http://www.sogo.com 2019-10-27T15:33:30.125+0800 INFO logic/temp2.go:52 Success! statusCode = 200 OK for URL http://www.sogo.com
這個紀錄檔程式中唯一缺少的就是紀錄檔切割歸檔功能。
Zap本身不支援切割歸檔紀錄檔檔案
為了新增紀錄檔切割歸檔功能,我們將使用第三方庫Lumberjack來實現。
執行下面的命令安裝Lumberjack
go get -u github.com/natefinch/lumberjack
要在zap中加入Lumberjack支援,我們需要修改WriteSyncer
程式碼。我們將按照下面的程式碼修改getLogWriter()
函數:
func getLogWriter() zapcore.WriteSyncer { lumberJackLogger := &lumberjack.Logger{ Filename: "./test.log", MaxSize: 10, MaxBackups: 5, MaxAge: 30, Compress: false, } return zapcore.AddSync(lumberJackLogger) }
Lumberjack Logger採用以下屬性作為輸入:
Filename
: 紀錄檔檔案的位置
MaxSize
:在進行切割之前,紀錄檔檔案的最大大小(以MB為單位)
MaxBackups
:保留舊檔案的最大個數
MaxAges
:保留舊檔案的最大天數
Compress
:是否壓縮/歸檔舊檔案
最終,使用Zap/Lumberjack logger的完整範例程式碼如下:
package main import ( "net/http" "github.com/natefinch/lumberjack" "go.uber.org/zap" "go.uber.org/zap/zapcore" ) var sugarLogger *zap.SugaredLogger func main() { InitLogger() defer sugarLogger.Sync() simpleHttpGet("www.sogo.com") simpleHttpGet("http://www.sogo.com") } func InitLogger() { writeSyncer := getLogWriter() encoder := getEncoder() core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) logger := zap.New(core, zap.AddCaller()) sugarLogger = logger.Sugar() } func getEncoder() zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder return zapcore.NewConsoleEncoder(encoderConfig) } func getLogWriter() zapcore.WriteSyncer { lumberJackLogger := &lumberjack.Logger{ Filename: "./test.log", MaxSize: 1, MaxBackups: 5, MaxAge: 30, Compress: false, } return zapcore.AddSync(lumberJackLogger) } func simpleHttpGet(url string) { sugarLogger.Debugf("Trying to hit GET request for %s", url) resp, err := http.Get(url) if err != nil { sugarLogger.Errorf("Error fetching URL %s : Error = %s", url, err) } else { sugarLogger.Infof("Success! statusCode = %s for URL %s", resp.Status, url) resp.Body.Close() } }
執行上述程式碼,下面的內容會輸出到檔案——test.log中。
2019-10-27T15:50:32.944+0800 DEBUG logic/temp2.go:48 Trying to hit GET request for www.sogo.com 2019-10-27T15:50:32.944+0800 ERROR logic/temp2.go:51 Error fetching URL www.sogo.com : Error = Get www.sogo.com: unsupported protocol scheme "" 2019-10-27T15:50:32.944+0800 DEBUG logic/temp2.go:48 Trying to hit GET request for http://www.sogo.com 2019-10-27T15:50:33.165+0800 INFO logic/temp2.go:53 Success! statusCode = 200 OK for URL http://www.sogo.com
同時,可以在main
函數中迴圈記錄紀錄檔,測試紀錄檔檔案是否會自動切割和歸檔(紀錄檔檔案每1MB會切割並且在當前目錄下最多儲存5個備份)。
至此,我們總結了如何將Zap紀錄檔程式整合到Go應用程式專案中。
以上就是golang預設Logger紀錄檔庫在專案中使用Zap紀錄檔庫的詳細內容,更多關於golang Zap和Logger紀錄檔庫的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45