zap 学习笔记
zap
zap 是 uber 提供的 一个高性能的组件库
结构
一条结构化的日志大致包含5个过程:
- 分配日志 Entry: 创建整个结构体,此时虽然没有传参(fields)进来,但是 fields 参数其实创建了
- 检查级别,添加core: 如果 logger 同时配置了 hook,则 hook 会在 core check 后把自己添加到 cores 中
- 根据选项添加 caller info 和 stack 信息: 只有大于等于级别的日志才会创建checked entry
- Encoder 对 checked entry 进行编码: 创建最终的 byte slice,将 fields 通过自己的编码方式(append)编码成目标串
- Write 编码后的目标串,并对剩余的 core 执行操作, hook也会在这时被调用
核心部分:
- logger: zap 的接口层,包含Log 对象、Level 对象、Field 对象、config 等基本对象
- zapcore: zap 的核心逻辑,包含field 的管理、level 的判断、encode 编码日志、输出日志
- encoder: json 或者其它编码方式的实现
- utils: SubLog,Hook,SurgarLog/grpclogger/stdlogger
代码
demo
func main() {
logger, _ := zap.NewProduction()
// 生产配置信息
defer logger.Sync()
// flush
logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", "127.0.0.1"),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
}
核心代码
func (log *Logger) Info(msg string, fields ...Field) {
if ce := log.check(InfoLevel, msg); ce != nil {
// 检查是否需要写入日志
ce.Write(fields...)
}
}
func (ce *CheckedEntry) Write(fields ...Field) {
......
// 写日志
for i := range ce.cores {
err = multierr.Append(err, ce.cores[i].Write(ce.Entry, fields))
}
// ce.cores[i].Write(ce.Entry, fields)
// 先获取 encode 然后 write
....
}