在Go语言项目中使用Zap日志库介绍

在许多Go语言项目中,我们需要一个好的日志记录器能够提供下面这些功能:

  • 能够将事件记录到文件中,而不是应用程序控制台。
  • 日志切割-能够根据文件大小、时间或间隔等来切割日志文件。
  • 支持不同的日志级别。例如INFO,DEBUG,ERROR等。
  • 能够打印基本信息,如调用文件/函数名和行号,日志时间等。

默认的Go Logger日志库

在介绍Uber-go的zap包之前,让我们先看看Go语言提供的基本日志功能。Go语言提供的默认日志包是https://golang.org/pkg/log/。

实现Go Logger

实现一个Go语言中的日志记录器非常简单——创建一个新的日志文件,然后设置它为日志的输出位置。

设置Logger

我们可以像下面的代码一样设置日志记录器

使用Logger

让我们来写一些虚拟的代码来使用这个日志记录器。

在当前的示例中,我们将建立一个到URL的HTTP连接,并将状态代码/错误记录到日志文件中。

Logger的运行

现在让我们执行上面的代码并查看日志记录器的运行情况。

test.log

Go Logger的优势和劣势

优势

io.Writer

劣势

仅限基本的日志级别

PrintINFODEBUG

对于错误日志,它有fatal和Panic

os.Exit(1)

缺乏日志格式化的能力——例如记录调用者的函数名和行号,格式化日期和时间格式。等等。

不提供日志切割的能力。

Uber-go Zap日志库

Zap是非常快的、结构化的,分日志级别的Go日志库。

为什么选择Uber-go zap

  • 它同时提供了结构化日志记录和printf风格的日志记录
  • 它非常的快

根据Uber-go Zap的文档,它的性能比类似的结构化日志包更好——也比标准库更快。 以下是Zap发布的基准测试信息

记录一条消息和10个字段:

PackageTimeTime % to zapObjects 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
logrus29501 ns/op+3322%125 allocs/op
log1529906 ns/op+3369%122 allocs/op

记录一个静态字符串,没有任何上下文或printf风格的模板:

PackageTimeTime % to zapObjects Allocated
zap118 ns/op+0%0 allocs/op
zap (sugared)191 ns/op+62%2 allocs/op
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

配置Zap Logger

Sugared LoggerLogger
SugaredLogger
LoggerSugaredLogger

Logger

zap.NewProduction()zap.NewDevelopment()zap.Example()

在上面的代码中,我们首先创建了一个Logger,然后使用Info/ Error等Logger方法记录消息。

日志记录器方法的语法是这样的:

MethodXXXzapcore.Field
zapcore.Field

我们执行上面的代码会得到如下输出结果:

Sugared Logger

现在让我们使用Sugared Logger来实现相同的功能。

. Sugar()SugaredLoggerSugaredLoggerprintf
SugaredLoggerLogger

当你执行上面的代码会得到如下输出:

你应该注意到的了,到目前为止这两个logger都打印输出JSON结构格式。

在本博客的后面部分,我们将更详细地讨论SugaredLogger,并了解如何进一步配置它。

定制logger

将日志写入文件而不是终端

我们要做的第一个更改是把日志写入文件,而不是打印到应用程序控制台。

zap.New(…)zap.NewProduction()
zapcore.Core
Encoder
WriterSyncer 
Log Level
InitLogger()main()SimpleHttpGet()
main()test.log

将JSON Encoder更改为普通的Log Encoder

NewJSONEncoder()NewConsoleEncoder()
main()test.log

更改时间编码并添加调用者详细信息

鉴于我们对配置所做的更改,有下面两个问题:

  • 时间是以非人类可读的方式展示,例如1.572161051846623e+09
  • 调用方函数的详细信息没有显示在日志中
ProductionConfig()
  • 修改时间编码器
  • 在日志文件中使用大写字母记录日志级别
zap.New(..)Option
main()test.log

使用Lumberjack进行日志切割归档

这个日志程序中唯一缺少的就是日志切割归档功能。

Zap本身不支持切割归档日志文件

为了添加日志切割归档功能,我们将使用第三方库Lumberjack来实现。

安装

执行下面的命令安装Lumberjack

zap logger中加入Lumberjack

WriteSyncergetLogWriter()

Lumberjack Logger采用以下属性作为输入:

Filename
MaxSize
MaxBackups
MaxAges
Compress

测试所有功能

最终,使用Zap/Lumberjack logger的完整示例代码如下:

执行上述代码,下面的内容会输出到文件——test.log中。

main

至此,我们总结了如何将Zap日志程序集成到Go应用程序项目中。