golang?日志庫ZAP[uber-go?zap]示例詳解
golang 日志庫ZAP[uber-go zap]
1. 簡要說明
zap 是 uber 開源的 Go 高性能日志庫,支持不同的日志級別, 能夠打印基本信息等,但不支持日志的分割,這里我們可以使用 lumberjack 也是 zap 官方推薦用于日志分割,結(jié)合這兩個(gè)庫我們就可以實(shí)現(xiàn)以下功能的日志機(jī)制:
能夠?qū)⑹录涗浀轿募?,而不是?yīng)用程序控制臺;日志切割能夠根據(jù)文件大小、時(shí)間或間隔等來切割日志文件;支持不同的日志級別,例如 DEBUG , INFO , WARN , ERROR 等;能夠打印基本信息,如調(diào)用文件、函數(shù)名和行號,日志時(shí)間等;官網(wǎng)地址:https://github.com/uber-go/zap
2. 下載安裝
// 初始化go mod 通過mod管理擴(kuò)展包 go mod init zaplog //使用下面命令安裝 go get -u go.uber.org/zap //如果下載失敗,則使用以下命令重新下載安裝 go get github.com/uber-go/zap //下載安裝成功后還有如下提示: package github.com/uber-go/zap: code in directory src/github.com/uber-go/zap expects import "go.uber.org/zap"
3. 配置 zap Logger
zap 提供了兩種類型的日志記錄器—和 Logger 和 Sugared Logger 。兩者之間的區(qū)別是:
- 在每一微秒和每一次內(nèi)存分配都很重要的上下文中,使用Logger。它甚至比SugaredLogger更快,內(nèi)存分配次數(shù)也更少,但它只支持強(qiáng)類型的結(jié)構(gòu)化日志記錄。
- 在性能很好但不是很關(guān)鍵的上下文中,使用SugaredLogger。它比其他結(jié)構(gòu)化日志記錄包快 4-10 倍,并且支持結(jié)構(gòu)化和 printf 風(fēng)格的日志記錄。
- 所以一般場景下我們使用 Sugared Logger 就足夠了。
3.1 Logger
- 通過調(diào)用zap.NewProduction()/zap.NewDevelopment()或者zap.NewExample()創(chuàng)建一個(gè) Logger 。
- 上面的每一個(gè)函數(shù)都將創(chuàng)建一個(gè) logger 。唯一的區(qū)別在于它將記錄的信息不同。例如 production logger 默認(rèn)記錄調(diào)用函數(shù)信息、日期和時(shí)間等。
- 通過 Logger 調(diào)用 INFO 、 ERROR 等。
- 默認(rèn)情況下日志都會打印到應(yīng)用程序的 console 界面。
3.1.1 NewExample
//代碼示例:
package main
import (
"go.uber.org/zap"
)
func main() {
log := zap.NewExample()
log.Debug("this is debug message")
log.Info("this is info message")
log.Info("this is info message with fileds",
zap.Int("age", 24), zap.String("agender", "man"))
log.Warn("this is warn message")
log.Error("this is error message")
log.Panic("this is panic message")
}
//輸出結(jié)果:
{"level":"debug","msg":"this is debug message"}
{"level":"info","msg":"this is info message"}
{"level":"info","msg":"this is info message with fileds","age":24,"agender":"man"}
{"level":"warn","msg":"this is warn message"}
{"level":"error","msg":"this is error message"}
{"level":"panic","msg":"this is panic message"}
panic: this is panic message3.1.2 NewDevelopment
//代碼示例:
func main() {
log, _ := zap.NewDevelopment()
log.Debug("this is debug message")
log.Info("this is info message")
log.Info("this is info message with fileds",
zap.Int("age", 24), zap.String("agender", "man"))
log.Warn("this is warn message")
log.Error("this is error message")
// log.DPanic("This is a DPANIC message")
// log.Panic("this is panic message")
// log.Fatal("This is a FATAL message")
}
//輸出結(jié)果:
2020-06-12T18:51:11.457+0800 DEBUG task/main.go:9 this is debug message
2020-06-12T18:51:11.457+0800 INFO task/main.go:10 this is info message
2020-06-12T18:51:11.457+0800 INFO task/main.go:11 this is info message with fileds {"age": 24, "agender": "man"}
2020-06-12T18:51:11.457+0800 WARN task/main.go:13 this is warn message
main.main
/home/wohu/GoCode/src/task/main.go:13
runtime.main
/usr/local/go/src/runtime/proc.go:200
2020-06-12T18:51:11.457+0800 ERROR task/main.go:14 this is error message
main.main
/home/wohu/GoCode/src/task/main.go:14
runtime.main
/usr/local/go/src/runtime/proc.go:2003.1.3 NewProduction
代碼示例:
func main() {
log, _ := zap.NewProduction()
log.Debug("this is debug message")
log.Info("this is info message")
log.Info("this is info message with fileds",
zap.Int("age", 24), zap.String("agender", "man"))
log.Warn("this is warn message")
log.Error("this is error message")
// log.DPanic("This is a DPANIC message")
// log.Panic("this is panic message")
// log.Fatal("This is a FATAL message")
}
輸出結(jié)果:
{"level":"info","ts":1591959367.316352,"caller":"task/main.go:10","msg":"this is info message"}
{"level":"info","ts":1591959367.3163702,"caller":"task/main.go:11","msg":"this is info message with fileds","age":24,"agender":"man"}
{"level":"warn","ts":1591959367.3163917,"caller":"task/main.go:13","msg":"this is warn message"}
{"level":"error","ts":1591959367.3163974,"caller":"task/main.go:14","msg":"this is error message","stacktrace":"main.main\n\t/home/wohu/GoCode/src/task/main.go:14\nruntime.main\n\t/usr/local/go/src/runtime/proc.go:200"}3.1.4 對比總結(jié)
Example和Production使用的是 json 格式輸出,Development 使用行的形式輸出
- Development
- 從警告級別向上打印到堆棧中來跟蹤
- 始終打印包/文件/行(方法)
- 在行尾添加任何額外字段作為 json 字符串
- 以大寫形式打印級別名稱
- 以毫秒為單位打印 ISO8601 格式的時(shí)間戳
- Production
- 調(diào)試級別消息不記錄
- Error , Dpanic 級別的記錄,會在堆棧中跟蹤文件, Warn 不會
- 始終將調(diào)用者添加到文件中
- 以時(shí)間戳格式打印日期
- 以小寫形式打印級別名稱
- 在上面的代碼中,我們首先創(chuàng)建了一個(gè) Logger ,然后使用 Info / Error 等 Logger 方法記錄消息。
日志記錄器方法的語法是這樣的:
func (log *Logger) MethodXXX(msg string, fields ...Field)
其中 MethodXXX 是一個(gè)可變參數(shù)函數(shù),可以是 Info / Error / Debug / Panic 等。每個(gè)方法都接受一個(gè)消息字符串和任意數(shù)量的 zapcore.Field 長參數(shù)。
每個(gè) zapcore.Field 其實(shí)就是一組鍵值對參數(shù)。
3.2 Sugared Logger
默認(rèn)的 zap 記錄器需要結(jié)構(gòu)化標(biāo)簽,即對每個(gè)標(biāo)簽,需要使用特定值類型的函數(shù)。
log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))雖然會顯的很長,但是對性能要求較高的話,這是最快的選擇。也可以使用suger logger, 它基于 printf 分割的反射類型檢測,提供更簡單的語法來添加混合類型的標(biāo)簽。
我們使用 Sugared Logger 來實(shí)現(xiàn)相同的功能。
- 大部分的實(shí)現(xiàn)基本都相同;
- 惟一的區(qū)別是,我們通過調(diào)用主 logger 的.Sugar()方法來獲取一個(gè)SugaredLogger;
- 然后使用SugaredLogger以printf格式記錄語句;
func main() {
logger, _ := zap.NewDevelopment()
slogger := logger.Sugar()
slogger.Debugf("debug message age is %d, agender is %s", 19, "man")
slogger.Info("Info() uses sprint")
slogger.Infof("Infof() uses %s", "sprintf")
slogger.Infow("Infow() allows tags", "name", "Legolas", "type", 1)
}
//輸出結(jié)果:
2020-06-12T19:23:54.184+0800 DEBUG task/main.go:11 debug message age is 19, agender is man
2020-06-12T19:23:54.185+0800 INFO task/main.go:12 Info() uses sprint
2020-06-12T19:23:54.185+0800 INFO task/main.go:13 Infof() uses sprintf
2020-06-12T19:23:54.185+0800 INFO task/main.go:14 Infow() allows tags {"name": "Legolas", "type": 1}如果需要,可以隨時(shí)使用記錄器上的 .Desugar() 方法從 sugar logger 切換到標(biāo)準(zhǔn)記錄器。
log := slogger.Desugar()
log.Info("After Desugar; INFO message")
log.Warn("After Desugar; WARN message")
log.Error("After Desugar; ERROR message")4. 將日志寫入文件
我們將使用zap.New(…)方法來手動(dòng)傳遞所有配置,而不是使用像zap.NewProduction()這樣的預(yù)置方法來創(chuàng)建 logger 。
func New(core zapcore.Core, options ...Option) *Logger
zapcore.Core需要三個(gè)配置——Encoder,WriteSyncer,LogLevel。
Encoder :編碼器(如何寫入日志)。我們將使用開箱即用的 NewConsoleEncoder() ,并使用預(yù)先設(shè)置的 ProductionEncoderConfig() 。
zapcore.NewConsoleEncoder(zap.NewProductionEncoderConfig())
WriterSyncer :指定日志將寫到哪里去。我們使用 zapcore.AddSync() 函數(shù)并且將打開的文件句柄傳進(jìn)去。
file, _ := os.Create("./test.log")
writeSyncer := zapcore.AddSync(file)Log Level :哪種級別的日志將被寫入。
// 代碼示例:
package main
import (
"os"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
var sugarLogger *zap.SugaredLogger
func InitLogger() {
encoder := getEncoder()
writeSyncer := getLogWriter()
core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel)
// zap.AddCaller() 添加將調(diào)用函數(shù)信息記錄到日志中的功能。
logger := zap.New(core, zap.AddCaller())
sugarLogger = logger.Sugar()
}
func getEncoder() zapcore.Encoder {
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder // 修改時(shí)間編碼器
// 在日志文件中使用大寫字母記錄日志級別
encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder
// NewConsoleEncoder 打印更符合人們觀察的方式
return zapcore.NewConsoleEncoder(encoderConfig)
}
func getLogWriter() zapcore.WriteSyncer {
file, _ := os.Create("./test.log")
return zapcore.AddSync(file)
}
func main() {
InitLogger()
sugarLogger.Info("this is info message")
sugarLogger.Infof("this is %s, %d", "aaa", 1234)
sugarLogger.Error("this is error message")
sugarLogger.Info("this is info message")
}
// 輸出日志文件:
2020-06-16T09:01:06.192+0800 INFO task/main.go:40 this is info message
2020-06-16T09:01:06.192+0800 INFO task/main.go:41 this is aaa, 1234
2020-06-16T09:01:06.192+0800 ERROR task/main.go:42 this is error message
2020-06-16T09:01:06.192+0800 INFO task/main.go:43 this is info message到此這篇關(guān)于golang 日志庫ZAP[uber-go zap]詳解的文章就介紹到這了,更多相關(guān)golang 日志庫ZAP內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- golang整合日志zap的實(shí)現(xiàn)示例
- Golang日志操作庫zap的使用詳解
- golang框架gin的日志處理和zap lumberjack日志使用方式
- GoLang基于zap日志庫的封裝過程詳解
- Golang定制化zap日志庫使用過程分析
- golang?xorm?自定義日志記錄器之使用zap實(shí)現(xiàn)日志輸出、切割日志(最新)
- golang默認(rèn)Logger日志庫在項(xiàng)目中使用Zap日志庫
- golang有用的庫及工具 之 zap.Logger包的使用指南
- 深入淺析golang zap 日志庫使用(含文件切割、分級別存儲和全局使用等)
- golang zap日志庫的具體使用
相關(guān)文章
golang將切片或數(shù)組根據(jù)某個(gè)字段進(jìn)行分組操作
這篇文章主要介紹了golang將切片或數(shù)組根據(jù)某個(gè)字段進(jìn)行分組操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-12-12
golang 實(shí)現(xiàn)一個(gè)restful微服務(wù)的操作
這篇文章主要介紹了golang 實(shí)現(xiàn)一個(gè)restful微服務(wù)的操作,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-04-04
Go語言內(nèi)建函數(shù)cap的實(shí)現(xiàn)示例
cap 是一個(gè)常用的內(nèi)建函數(shù),它用于獲取某些數(shù)據(jù)結(jié)構(gòu)的容量,本文主要介紹了Go語言內(nèi)建函數(shù)cap的實(shí)現(xiàn)示例,具有一定的參考價(jià)值,感興趣的可以了解一下2024-08-08
關(guān)于Golang標(biāo)準(zhǔn)庫flag的全面講解
這篇文章主要介紹了關(guān)于Golang標(biāo)準(zhǔn)庫flag的全面講解,這個(gè)庫的代碼量只有1000行左右,卻提供了非常完善的命令行參數(shù)解析功能,更多相關(guān)內(nèi)容需要的朋友可以參考一下2022-09-09
goland把go項(xiàng)目打包進(jìn)docker鏡像的全過程記錄
golang編譯的應(yīng)用是不需要依賴其他運(yùn)行環(huán)境的,下面這篇文章主要給大家介紹了關(guān)于goland把go項(xiàng)目打包進(jìn)docker鏡像的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08

