一、Zap 简介
zap 是 Uber 开源的高性能结构化日志库,兼顾结构化日志与 printf 风格日志,速度快,广泛用于 Go 后端项目。 官方仓库:uber-go/zap: Blazing fast, structured, leveled logging in Go.
日志库核心能力(日常开发掌握这 6 点基本够用)
- 时间格式化
- 输出美化
- 预设字段
- 使用全局日志
- 日志双写(同时输出控制台 + 文件)
- 日志分片
安装
go get -u go.uber.org/zap
二、快速开始:两种 Logger
Zap 提供两套日志 API:
- SugarLogger:支持 printf 风格,使用简单,性能略低
- Logger:强类型结构化日志,性能高,写法繁琐
重要:
defer logger.Sync(),程序退出时把缓冲区日志刷入文件,防止日志丢失。
示例 1:SugarLogger
Go
logger, _ := zap.NewProduction()
defer logger.Sync() // 程序结束同步缓存日志
sugar := logger.Sugar()
// 结构化键值输出
sugar.Infow("failed to fetch URL",
"url", url,
"attempt", 3,
"backoff", time.Second,
)
// printf风格
sugar.Infof("Failed to fetch URL: %s", url)
示例 2:原生 Logger(高性能强类型)
Go
logger, _ := zap.NewProduction()
defer logger.Sync()
logger.Info("failed to fetch URL",
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
TIP:Zap 上手简单,难点在于自定义适配项目的日志配置。官方示例较少,复杂配置建议阅读源码注释。
三、Zap 配置 Config 结构体
Zap 支持 yaml/json 配置文件反序列化加载配置,但高级配置官方示例不足,需要手动配置。
Go
type Config struct {
// 最小日志级别
Level AtomicLevel `json:"level" yaml:"level"`
// 开发模式,影响堆栈跟踪
Development bool `json:"development" yaml:"development"`
// 是否关闭调用者追踪(打印日志所在行号)
DisableCaller bool `json:"disableCaller" yaml:"disableCaller"`
// 是否关闭堆栈信息
DisableStacktrace bool `json:"disableStacktrace" yaml:"disableStacktrace"`
// 采样配置:限制日志输出量,选择性记录日志,降低性能开销
Sampling *SamplingConfig `json:"sampling" yaml:"sampling"`
// 编码格式:json / console
Encoding string `json:"encoding" yaml:"encoding"`
// 编码细节配置(时间、级别格式化等)
EncoderConfig zapcore.EncoderConfig `json:"encoderConfig" yaml:"encoderConfig"`
// 日志输出路径,可多个
OutputPaths []string `json:"outputPaths" yaml:"outputPaths"`
// 错误日志单独输出路径
ErrorOutputPaths []string `json:"errorOutputPaths" yaml:"errorOutputPaths"`
// 全局预设字段,每条日志默认携带
InitialFields map[string]interface{} `json:"initialFields" yaml:"initialFields"`
}
EncoderConfig 编码配置(日志输出格式化核心)
控制日志各个字段的 key 名称、格式化方式。
Go
type EncoderConfig struct {
// 各个字段的key名称,为空则不输出该字段
MessageKey string `json:"messageKey" yaml:"messageKey"`
LevelKey string `json:"levelKey" yaml:"levelKey"`
TimeKey string `json:"timeKey" yaml:"timeKey"`
NameKey string `json:"nameKey" yaml:"nameKey"`
CallerKey string `json:"callerKey" yaml:"callerKey"`
FunctionKey string `json:"functionKey" yaml:"functionKey"`
StacktraceKey string `json:"stacktraceKey" yaml:"stacktraceKey"`
SkipLineEnding bool `json:"skipLineEnding" yaml:"skipLineEnding"`
LineEnding string `json:"lineEnding" yaml:"lineEnding"`
// 各类自定义编码器
EncodeLevel LevelEncoder `json:"levelEncoder" yaml:"levelEncoder"`
EncodeTime TimeEncoder `json:"timeEncoder" yaml:"timeEncoder"`
EncodeDuration DurationEncoder `json:"durationEncoder" yaml:"durationEncoder"`
EncodeCaller CallerEncoder `json:"callerEncoder"`
EncodeName NameEncoder `json:"nameEncoder" yaml:"nameEncoder"`
// 反射编码器,处理interface{}类型
NewReflectedEncoder func(io.Writer) ReflectedEncoder `json:"-" yaml:"-"`
// console模式下字段分隔符
ConsoleSeparator string `json:"consoleSeparator" yaml:"consoleSeparator"`
}
四、Option 配置项
Option 用于对 Logger 做附加配置,底层是接口:
Go
type Option interface {
apply(*Logger)
}
// 底层实现
type optionFunc func(*Logger)
func (f optionFunc) apply(log *Logger) {
f(log)
}
// 示例:开启开发模式
func Development() Option {
return optionFunc(func(log *Logger) {
log.development = true
})
}
五、ZapCore 三大核心组件(理解 zap 的关键)
Go
type ioCore struct {
LevelEnabler // 日志级别开关:低于该级别直接丢弃
enc Encoder // 编码器:负责日志内容格式化(json/console)
out WriteSyncer // 日志写入器:输出到控制台/文件,支持Sync刷缓存
}
- Encoder:日志格式化、编码,定义长什么样
- WriteSyncer:日志输出目标,控制台、文件等
- LevelEnabler:日志级别过滤,控制哪些级别日志放行
自定义日志(双写、日志分割)基本都是基于
zapcore组合这三个组件实现。