1. 前言 在go项目中,日志记录是必不可少的一部分,可以帮助开发者调试和排查问题以及为系统的运行状况提供数据。本文介绍了go业内非常流行的zap日志库,同时结合Lumberjack实现日志的切割和归档。
2. zap 日志库 2.1 为什么使用zap go本身也有logger日志,但它仅有基本的日志级别,没有格式化日志的能力以及不提供日志切割,故舍弃。
zap官网描述Blazing fast, structured, leveled logging in Go.
记录一条消息和10个字段的性能对比:
Package
Time
Time % to zap
Objects Allocated
⚡ zap
656 ns/op
+0%
5 allocs/op
⚡ zap (sugared)
935 ns/op
+43%
10 allocs/op
zerolog
380 ns/op
-42%
1 allocs/op
go-kit
2249 ns/op
+243%
57 allocs/op
slog (LogAttrs)
2479 ns/op
+278%
40 allocs/op
slog
2481 ns/op
+278%
42 allocs/op
apex/log
9591 ns/op
+1362%
63 allocs/op
log15
11393 ns/op
+1637%
75 allocs/op
logrus
11654 ns/op
+1677%
79 allocs/op
2.2 安装 1 go get -u go.uber.org/zap
2.3 配置并引入 lumberjack 日志切分 zap核心是使用 zapcore.NewCore() 来配置,接收三个参数:encoder, writeSyncer, level。
encoder表示写入以什么样的格式写入日志,如:指定时间格式为2024-06-23T10:28:52.011+0800。
writeSyncer表示日志写到哪里去(终端或文件),lumberjack 也在这里配置。
level指定日志级别,zap支持Debug, Info, Error, Warn, Fatal等常用日志级别。
创建项目,结构为:
1 2 3 4 5 6 . ├── go.mod ├── go.sum ├── logger │ └── zap.go └── main.go
在zap.go文件中添加:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 func Init () { writeSyncer := getLogWriter() encoder := getEncoder() level := zapcore.InfoLevel core := zapcore.NewCore(encoder, writeSyncer, level) lg := zap.New(core, zap.AddCaller()) zap.ReplaceGlobals(lg) }func getEncoder () zapcore.Encoder { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder encoderConfig.TimeKey = "time" encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder encoderConfig.EncodeDuration = zapcore.SecondsDurationEncoder encoderConfig.EncodeCaller = zapcore.ShortCallerEncoder return zapcore.NewJSONEncoder(encoderConfig) }func getLogWriter () zapcore.WriteSyncer { lumberJackLogger := &lumberjack.Logger{ Filename: "logfile.log" , MaxSize: 100 , MaxBackups: 3 , MaxAge: 30 , } return zapcore.AddSync(lumberJackLogger) }
关键配置:
level := zapcore.InfoLevel可以指定其他的日志级别。
zap.ReplaceGlobals(lg)可以在项目的任何地方通过 zap.L() 访问全局的 zap 日志记录器,记录日志信息。
getEncoder和getLogWriter可以理解为固定写法,其中Filename表示生成日志文件的名称,MaxSize,MaxBackups, MaxAge为切分日志参数设置。
2.4 测试验证 在main.go或项目任意地方通过 zap.L() 的方式来使用:
1 2 3 4 5 6 7 8 9 func main () { logger.Init() zap.L().Debug("This is a debug message" ) zap.L().Info("This is an info message" ) zap.L().Warn("This is a warn message" ) zap.L().Error("This is an error message" ) zap.L().DPanic("This is a dpanic message" ) }
执行完会在项目目录下生成 logfile.log 文件。
1 2 3 4 5 6 7 . ├── go.mod ├── go.sum ├── logfile.log ├── logger │ └── zap.go └── main.go
logfile输出:
1 2 3 4 {"level" :"INFO" ,"time" :"2024-06-27T11:19:20.045+0800" ,"caller" :"zap_demo/main.go:13" ,"msg" :"This is an info message" } {"level" :"WARN" ,"time" :"2024-06-27T11:19:20.046+0800" ,"caller" :"zap_demo/main.go:14" ,"msg" :"This is a warn message" } {"level" :"ERROR" ,"time" :"2024-06-27T11:19:20.046+0800" ,"caller" :"zap_demo/main.go:15" ,"msg" :"This is an error message" } {"level" :"DPANIC" ,"time" :"2024-06-27T11:19:20.046+0800" ,"caller" :"zap_demo/main.go:16" ,"msg" :"This is a dpanic message" }
以上为zap日志在项目中的快速使用,后续文章会介绍在Gin框架中结合zap日志库。