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 安装
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
等常用日志级别。
创建项目,结构为:
.
├── go.mod
├── go.sum
├── logger
│ └── zap.go
└── main.go
在zap.go文件中添加:
// Init 初始化Logger
func Init() {
writeSyncer := getLogWriter()
encoder := getEncoder()
level := zapcore.InfoLevel // 直接指定日志级别为Info
core := zapcore.NewCore(encoder, writeSyncer, level)
lg := zap.New(core, zap.AddCaller())
// 替换zap库中全局的logger
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, // megabytes
MaxBackups: 3,
MaxAge: 30, // days
}
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() 的方式来使用:
func main() {
logger.Init()
// 使用全局logger记录日志
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 文件。
.
├── go.mod
├── go.sum
├── logfile.log
├── logger
│ └── zap.go
└── main.go
logfile输出:
{"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日志库。