【Go进阶】如何让你Go项目中日志清晰有趣-Zap日志库

更新时间:2023-07-12 18:08:20 阅读: 评论:0

【Go进阶】如何让你Go项⽬中⽇志清晰有趣-Zap⽇志库
本⽂先介绍了Go语⾔原⽣的⽇志库的使⽤,然后详细介绍了⾮常流⾏的Uber开源的zap⽇志库,同时介绍了如何搭配Lumberjack实现⽇志的切割和归档。
Zap⽇志库在Go语⾔项⽬中的使⽤
在许多Go语⾔项⽬中,我们需要⼀个好的⽇志记录器能够提供下⾯这些功能:
能够将事件记录到⽂件中,⽽不是应⽤程序控制台。
⽇志切割-能够根据⽂件⼤⼩、时间或间隔等来切割⽇志⽂件。
⽀持不同的⽇志级别。例如INFO,DEBUG,ERROR等。
能够打印基本信息,如调⽤⽂件/函数名和⾏号,⽇志时间等。
默认的Go Logger
实现Go Logger
实现⼀个Go语⾔中的⽇志记录器⾮常简单——创建⼀个新的⽇志⽂件,然后设置它为⽇志的输出位置。
设置Logger
我们可以像下⾯的代码⼀样设置⽇志记录器
func SetupLogger(){
logFileLocation, _ := os.OpenFile("/Urs/q1mi/test.log", os.O_CREATE|os.O_APPEND|os.O_RDWR,0744)
log.SetOutput(logFileLocation)
}
使⽤Logger
neocomimi
让我们来写⼀些虚拟的代码来使⽤这个⽇志记录器。
在当前的⽰例中,我们将建⽴⼀个到URL的HTTP连接,并将状态代码/错误记录到⽇志⽂件中。
func simpleHttpGet(url string){
resp, err := http.Get(url)
if err != nil {
log.Printf("Error fetching url %s : %s", url, err.Error())
phoebus}el{littlest things
meadow
log.Printf("Status Code for %s : %s", url, resp.Status)
resp.Body.Clo()
}
}
Logger的运⾏
现在让我们执⾏上⾯的代码并查看⽇志记录器的运⾏情况。
func main(){
SetupLogger()
9月 英文simpleHttpGet("")
simpleHttpGet("")
}
当我们执⾏上⾯的代码,我们能看到⼀个test.log⽂件被创建,下⾯的内容会被添加到这个⽇志⽂件中。
2019/05/2401:14:13 Error fetching le.com : le.com: unsupported protocol scheme ""
2019/05/2401:14:14 Status Code le.com : 200 OK
Go Logger的优势和劣势
优势
它最⼤的优点是使⽤⾮常简单。我们可以设置任何io.Writer作为⽇志记录输出并向其发送要写⼊的⽇志。
劣势
仅限基本的⽇志级别
只有⼀个Print选项。不⽀持INFO/DEBUG等多个级别。
对于错误⽇志,它有Fatal和Panic
Fatal⽇志通过调⽤os.Exit(1)来结束程序
Panic⽇志在写⼊⽇志消息之后抛出⼀个panic
但是它缺少⼀个ERROR⽇志级别,这个级别可以在不抛出panic或退出程序的情况下记录错误缺乏⽇志格式化的能⼒——例如记录调⽤者的函数名和⾏号,格式化⽇期和时间格式。等等。
不提供⽇志切割的能⼒。
Uber-go Zap
是⾮常快的、结构化的,分⽇志级别的Go⽇志库。
为什么选择Uber-go zap
它同时提供了结构化⽇志记录和printf风格的⽇志记录intelligent
它⾮常的快
根据Uber-go Zap的⽂档,它的性能⽐类似的结构化⽇志包更好——也⽐标准库更快。 以下是Zap发布的基准测试信息
记录⼀条消息和10个字段:
Package Time Time % to zap Objects Allocated
⚡  zap862 ns/op+0%  5 allocs/op ⚡  zap (sugared)1250 ns/op+45%11 allocs/op zerolog4021 ns/op+366%76 allocs/op
go-kit4542 ns/op+427%105 allocs/op
apex/log26785 ns/op+3007%115 allocs/op英语四级成绩查询时间2020年9月
logrus29501 ns/op+3322%125 allocs/op
log1529906 ns/op+3369%122 allocs/op
记录⼀个静态字符串,没有任何上下⽂或printf风格的模板:
Package Time Time % to zap Objects Allocated
⚡  zap118 ns/op+0%0 allocs/op ⚡  zap (sugared)191 ns/op+62%  2 allocs/op
Package Time Time % to zap Objects Allocated
zerolog93 ns/op-21%0 allocs/op
go-kit280 ns/op+137%11 allocs/op standard library499 ns/op+323%  2 allocs/op apex/log1990 ns/op+1586%10 allocs/op
logrus3129 ns/op+2552%24 allocs/op
log153887 ns/op+3194%23 allocs/op
洪恩英语在线安装
运⾏下⾯的命令安装zap
go get -u go.uber/zap
配置Zap Logger
Zap提供了两种类型的⽇志记录器—Sugared Logger和Logger。
在性能很好但不是很关键的上下⽂中,使⽤SugaredLogger。它⽐其他结构化⽇志记录包快4-10倍,并且⽀持结构化和printf风格的⽇志记录。
在每⼀微秒和每⼀次内存分配都很重要的上下⽂中,使⽤Logger。它甚⾄⽐SugaredLogger更快,内存分配次数也更少,但它只⽀持强类型的结构化⽇志记录。
Logger
通过调⽤zap.NewProduction()/zap.NewDevelopment()或者zap.Example()创建⼀个Logger。
上⾯的每⼀个函数都将创建⼀个logger。唯⼀的区别在于它将记录的信息不同。例如production logger默认记录调⽤函数信息、⽇期和时间等。
通过Logger调⽤Info/Error等。
默认情况下⽇志都会打印到应⽤程序的console界⾯。
var logger *zap.Logger
func main(){
InitLogger()
defer logger.Sync()
simpleHttpGet("")
simpleHttpGet("")
}
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))
}el{
logger.Info("Success..",
zap.String("statusCode", resp.Status),
zap.String("url", url))
resp.Body.Clo()
}
}
在上⾯的代码中,我们⾸先创建了⼀个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_:25","msg":"Error fetching url..","url":"","error":"Get : unsu pported protocol scheme \"\"","stacktrace":"main.simpleHttpGet\n\t/Urs/q1mi/zap_:25\nmain.main\n\t/Urs/q1mi/zap_:14\nr untime.main\n\t/usr/local/go/src/:203"}
{"level":"info","ts":1572159219.1227388,"caller":"zap_:30","msg":"Success..","statusCode":"200 OK","url":""}
Sugared Logger
现在让我们使⽤Sugared Logger来实现相同的功能。
⼤部分的实现基本都相同。
惟⼀的区别是,我们通过调⽤主logger的. Sugar()⽅法来获取⼀个SugaredLogger。
然后使⽤SugaredLogger以printf格式记录语句
下⾯是修改过后使⽤SugaredLogger代替Logger的代码:
var sugarLogger *zap.SugaredLogger
func main(){
InitLogger()
defer sugarLogger.Sync()
simpleHttpGet("")
simpleHttpGet("")
}
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)
}el{
sugarLogger.Infof("Success! statusCode = %s for URL %s", resp.Status, url)
resp.Body.Clo()
}reverb
}
当你执⾏上⾯的代码会得到如下输出:
{"level":"error","ts":1572159149.923002,"caller":":27","msg":"Error fetching URL www.
< : Error = Get : unsupported p rotocol scheme \"\"","stacktrace":"main.simpleHttpGet\n\t/Urs/q1mi/zap_demo/:27\nmain.main\n\t/Urs/q1mi/zap_demo/:1 4\nruntime.main\n\t/usr/local/go/src/:203"}
{"level":"info","ts":1572159150.192585,"caller":":29","msg":"Success! statusCode = 200 OK for URL "}
你应该注意到的了,到⽬前为⽌这两个logger都打印输出JSON结构格式。
在本博客的后⾯部分,我们将更详细地讨论SugaredLogger,并了解如何进⼀步配置它。
定制logger
将⽇志写⼊⽂件⽽不是终端
我们要做的第⼀个更改是把⽇志写⼊⽂件,⽽不是打印到应⽤程序控制台。
我们将使⽤zap.New(…)⽅法来⼿动传递所有配置,⽽不是使⽤像zap.NewProduction()这样的预置⽅法来创建logger。
func New(core zapcore.Core, options ...Option)*Logger
zapcore.Core需要三个配置——Encoder,WriteSyncer,LogLevel。
1.Encoder:编码器(如何写⼊⽇志)。我们将使⽤开箱即⽤的NewJSONEncoder(),并使⽤预先设置的ProductionEncoderConfig()。
zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig())
2.WriterSyncer :指定⽇志将写到哪⾥去。我们使⽤zapcore.AddSync()函数并且将打开的⽂件句柄传进去。
file, _ := os.Create("./test.log")
writeSyncer := zapcore.AddSync(file)
3.Log Level:哪种级别的⽇志将被写⼊。

本文发布于:2023-07-12 18:08:20,感谢您对本站的认可!

本文链接:https://www.wtabcd.cn/fanwen/fan/90/175306.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:记录   代码   信息   输出   结构化   消息   函数   基本
相关文章
留言与评论(共有 0 条评论)
   
验证码:
Copyright ©2019-2022 Comsenz Inc.Powered by © 专利检索| 网站地图