golang?日志庫ZAP[uber-go?zap]示例詳解
golang 日志庫ZAP[uber-go zap]
1. 簡要說明
zap 是 uber 開源的 Go 高性能日志庫,支持不同的日志級(jí)別, 能夠打印基本信息等,但不支持日志的分割,這里我們可以使用 lumberjack 也是 zap 官方推薦用于日志分割,結(jié)合這兩個(gè)庫我們就可以實(shí)現(xiàn)以下功能的日志機(jī)制:
能夠?qū)⑹录涗浀轿募?,而不是?yīng)用程序控制臺(tái);日志切割能夠根據(jù)文件大小、時(shí)間或間隔等來切割日志文件;支持不同的日志級(jí)別,例如 DEBUG , INFO , WARN , ERROR 等;能夠打印基本信息,如調(diào)用文件、函數(shù)名和行號(hào),日志時(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)情況下日志都會(huì)打印到應(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 對(duì)比總結(jié)
Example和Production使用的是 json 格式輸出,Development 使用行的形式輸出
- Development
- 從警告級(jí)別向上打印到堆棧中來跟蹤
- 始終打印包/文件/行(方法)
- 在行尾添加任何額外字段作為 json 字符串
- 以大寫形式打印級(jí)別名稱
- 以毫秒為單位打印 ISO8601 格式的時(shí)間戳
- Production
- 調(diào)試級(jí)別消息不記錄
- Error , Dpanic 級(jí)別的記錄,會(huì)在堆棧中跟蹤文件, Warn 不會(huì)
- 始終將調(diào)用者添加到文件中
- 以時(shí)間戳格式打印日期
- 以小寫形式打印級(jí)別名稱
- 在上面的代碼中,我們首先創(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í)就是一組鍵值對(duì)參數(shù)。
3.2 Sugared Logger
默認(rèn)的 zap 記錄器需要結(jié)構(gòu)化標(biāo)簽,即對(duì)每個(gè)標(biāo)簽,需要使用特定值類型的函數(shù)。
log.Info("this is info message with fileds",zap.Int("age", 24), zap.String("agender", "man"))雖然會(huì)顯的很長,但是對(duì)性能要求較高的話,這是最快的選擇。也可以使用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 :哪種級(jí)別的日志將被寫入。
// 代碼示例:
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í)間編碼器
// 在日志文件中使用大寫字母記錄日志級(jí)別
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)容請(qǐng)搜索腳本之家以前的文章或繼續(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 日志庫使用(含文件切割、分級(jí)別存儲(chǔ)和全局使用等)
- golang zap日志庫的具體使用
相關(guān)文章
Go類型斷言提取測試接口值動(dòng)態(tài)類型及靜態(tài)轉(zhuǎn)換確保類型接口編譯安全
這篇文章主要為大家介紹了Go類型斷言提取測試接口值動(dòng)態(tài)類型及靜態(tài)轉(zhuǎn)換確保類型實(shí)現(xiàn)特定接口的編譯時(shí)安全性詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-10-10
Go語言調(diào)用SiliconFlow實(shí)現(xiàn)文本轉(zhuǎn)換為MP3格式
這篇文章主要為大家詳細(xì)介紹了Go語言如何調(diào)用?SiliconFlow?語音生成?API?的腳本,用于將文本轉(zhuǎn)換為?MP3?格式的語音文件,感興趣的小伙伴可以了解下2025-02-02
淺談goland導(dǎo)入自定義包時(shí)出錯(cuò)(一招解決問題)
這篇文章主要介紹了淺談goland導(dǎo)入自定義包時(shí)出錯(cuò)(一招解決問題),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2020-12-12
基于Go語言編寫一個(gè)能在Windows上錄音的小程序
這篇文章主要為大家詳細(xì)介紹了如何基于Go語言編寫一個(gè)能在Windows上錄音的小程序,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下2026-03-03

