Zap日志库使用文档
Zap是由Uber开源的一个Go语言高性能日志库。它以极高的性能和极少的内存分配著称,非常适合用于对性能要求严苛的场景。
快速入门
首先,你需要安装Zap库:
1
| go get -u go.uber.org/zap
|
下面是一个最简单的使用示例:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| package main
import ( "go.uber.org/zap" )
func main() { logger, _ := zap.NewDevelopment() defer logger.Sync()
logger.Info("这是一条普通信息", zap.String("name", "Go"), zap.Int("age", 15), ) logger.Warn("这是一条警告信息")
logger.Error("这是一条错误信息", zap.Error(nil)) }
|
运行以上代码,你将会在控制台看到如下输出:
1 2 3
| {"level":"info","ts":1678886400.123456,"caller":"main/main.go:12","msg":"这是一条普通信息","name":"Go","age":15} {"level":"warn","ts":1678886400.123456,"caller":"main/main.go:15","msg":"这是一条警告信息"} {"level":"error","ts":1678886400.123456,"caller":"main/main.go:17","msg":"这是一条错误信息"}
|
Zap Logger 的类型
Zap 提供了两种主要的 Logger 类型:
zap.NewProduction(): 适用于生产环境。它会以 JSON 格式输出日志,并禁用调用者(caller)信息,以获得最佳性能。
zap.NewDevelopment(): 适用于开发环境。它会以更易读的格式输出日志,并包含文件和行号信息,方便调试。
如果你需要更细粒度的控制,可以使用 zap.New() 或 zap.Config。
核心概念
Logger
*zap.Logger 是 Zap 的核心。它是线程安全的,可以被全局共享。你可以通过它来记录不同级别的日志。
SugaredLogger
为了方便,Zap 还提供了一个更人性化的 SugaredLogger。它使用 Printf 风格的 API,但性能略低于 Logger。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| package main
import ( "go.uber.org/zap" )
func main() { logger, _ := zap.NewProduction() defer logger.Sync()
sugar := logger.Sugar()
sugar.Infow("记录一个结构化的事件", "url", "http://example.com", "attempt", 3, "backoff", "5s", )
sugar.Infof("请求失败,重试中... %s", "http://example.com") }
|
SugaredLogger 适用于以下场景:
- 日志格式变化频繁。
- 应用程序对性能要求不高。
- 想要快速迁移旧项目中的日志代码。
Field
zap.Field 用于将结构化数据附加到日志中。Zap 提供了多种预定义的 Field 类型,以减少内存分配:
- 基本类型:
zap.String(), zap.Int(), zap.Float64(), zap.Bool()
- 错误:
zap.Error()
- 时间:
zap.Time(), zap.Duration()
- 通用:
zap.Any()(使用反射,性能较低,尽量避免)
高级用法
自定义配置
你可以使用 zap.Config 来完全自定义 Logger 的行为,包括日志级别、输出目标、编码器等。
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 32
| package main
import ( "os"
"go.uber.org/zap" "go.uber.org/zap/zapcore" )
func main() { encoderConfig := zap.NewProductionEncoderConfig() encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
core := zapcore.NewCore( zapcore.NewJSONEncoder(encoderConfig), zapcore.AddSync(os.Stdout), zapcore.DebugLevel, )
logger := zap.New(core) defer logger.Sync()
logger.Debug("这条日志是Debug级别的") logger.Info("这条日志是Info级别的") }
|
日志级别
Zap 支持以下日志级别:
DebugLevel
InfoLevel
WarnLevel
ErrorLevel
DPanicLevel(仅在开发环境panic)
PanicLevel
FatalLevel(记录日志后调用os.Exit(1))
你可以通过 zap.Config 或 zap.AtomicLevel 来动态更改日志级别。
输出到文件
你可以通过 zapcore.AddSync() 将日志写入文件。
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 32 33 34
| package main
import ( "os" "path/filepath"
"go.uber.org/zap" "go.uber.org/zap/zapcore" "gopkg.in/natefinch/lumberjack.v2" )
func main() { lumberjackLogger := &lumberjack.Logger{ Filename: filepath.Join(os.TempDir(), "app.log"), MaxSize: 10, MaxBackups: 3, MaxAge: 7, Compress: true, }
writeSyncer := zapcore.AddSync(lumberjackLogger)
core := zapcore.NewCore( zapcore.NewJSONEncoder(zap.NewProductionEncoderConfig()), writeSyncer, zap.InfoLevel, )
logger := zap.New(core) defer logger.Sync()
logger.Info("日志已成功写入文件") }
|
总结
| 特性 |
Logger(zap.Logger) |
SugaredLogger(zap.SugaredLogger) |
| 性能 |
更高,零内存分配(zero allocation) |
较低,有反射和接口调用开销 |
| API风格 |
结构化,使用 zap.Field |
类似 fmt.Printf |
| 适用场景 |
对性能要求高,日志格式相对固定,如微服务、高并发应用 |
快速开发,日志格式不固定,对性能要求不高 |