第 21 期 2018-11-28 Go errors 处理及 zap 源码分析

观看视频

分享者

叶飞/阙坦

1赞

请问下,这里的那个分享文档可以在那里看到 。谢谢。

年久失修,文档没有存档,你只能看视频看文档了。很抱歉啊。

不清楚是不是有 叶飞/阙坦 的github ,他们的github不清楚是否有相关的文档。

zap源码解析

一、与其他框架对比的优势:

  1. logrus: 代码清晰简单,同时提供结构化的日志。
  2. zap: uber 开源的高性能日志库,面向高性能并且也确实做到了高性能。

官方对比图

一、结构

目录结构如下:


├── benchmarks
├── buffer
├── internal
│   ├── bufferpool
│   ├── color
│   ├── exit
│   ├── readme
│   └── ztest
├── zapcore
├── zapgrpc
└── zaptest
    ├── observer

源码架构图

zapcore

定义所有底层接口,接口和对应实现分离,每种接口都有对应的集中默认实现方式(参见Encoder),这样降低耦合,增加扩展性,方便二次开发

zapgrpc

grpclog的封装实现

internal buffer相关

buffer提供了最底层 append拼接buffer的方法(参见zapcore/json_encoder.go), 将entry信息转换为buffer用于最终的输出

二、流程

打印一条日志大致的流程:

  1. 分配 zapcore.Entry结构体
  2. 检查级别,通过zapcore.Core接口的check函数添加core(实现在zapcore/core.go, zapcore/tee.go中),产生一个 zapcore.CheckedEntry对象
  3. 根据当前日志级别判断是否需要panic(产生一条panic)和fatal(会调用os.Exit(1)退出应用)
  4. 根据zapcore.Option配置,看是否加入 caller和 什么级别增加stack
  5. Encoder 为 zapcore.CheckedEntry 对应的编码器: 通过 EncodeEntry方法 把zapcore.Entry和 zapcore.Field最终编码成目标格式的结构:(json,console对应buffer.Buffer,memory encoder对应是map)

三、高性能

  1. 通过 zapcore.Field避免反射
  2. Buffer Pool避免缓存
  3. 内建简化版Json Encoder
  4. 读写分离,写时复制(log.Check检查可写后,再通过checked entry的write方法写,避免Field内存分配)

四、设计模式

接口,实现分离,举例 zapcore/encoder.go zapcore/json_encoder.go

五、项目实践