聊聊golang的zap的hook

go4it · · 305 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本文主要研究一下golang的zap的hook

实例

func hookDemo() {
    count := &atomic.Int64{}
    logger, _ := zap.NewProduction(zap.Hooks(func(entry zapcore.Entry) error {
        fmt.Println("count:", count.Inc(), "msg:", entry.Message)
        return nil
    }))
    defer logger.Sync() // flushes buffer, if any
    sugar := logger.Sugar()
    sugar.Infow("failed to fetch URL",
        // Structured context as loosely typed key-value pairs.
        "url", "https://golang.org",
        "attempt", 3,
        "backoff", time.Second,
    )
    sugar.Info("hello world")
}

输出

{"level":"info","ts":1608045721.769727,"caller":"zap/zap_demo.go:29","msg":"failed to fetch URL","url":"https://golang.org","attempt":3,"backoff":1}
count: 1 msg: failed to fetch URL
{"level":"info","ts":1608045721.769826,"caller":"zap/zap_demo.go:35","msg":"hello world"}
count: 2 msg: hello world

Hooks

zap@v1.16.0/options.go

func Hooks(hooks ...func(zapcore.Entry) error) Option {
    return optionFunc(func(log *Logger) {
        log.core = zapcore.RegisterHooks(log.core, hooks...)
    })
}

Hooks方法将log的core使用zapcore.RegisterHooks包装了一下

zapcore.RegisterHooks

zap@v1.16.0/zapcore/hook.go

func RegisterHooks(core Core, hooks ...func(Entry) error) Core {
    funcs := append([]func(Entry) error{}, hooks...)
    return &hooked{
        Core:  core,
        funcs: funcs,
    }
}

RegisterHooks方法创建hooked,hooks赋值给hooked的funcs属性

hook

zap@v1.16.0/zapcore/hook.go

type hooked struct {
    Core
    funcs []func(Entry) error
}

func (h *hooked) Check(ent Entry, ce *CheckedEntry) *CheckedEntry {
    // Let the wrapped Core decide whether to log this message or not. This
    // also gives the downstream a chance to register itself directly with the
    // CheckedEntry.
    if downstream := h.Core.Check(ent, ce); downstream != nil {
        return downstream.AddCore(ent, h)
    }
    return ce
}

func (h *hooked) With(fields []Field) Core {
    return &hooked{
        Core:  h.Core.With(fields),
        funcs: h.funcs,
    }
}

func (h *hooked) Write(ent Entry, _ []Field) error {
    // Since our downstream had a chance to register itself directly with the
    // CheckedMessage, we don't need to call it here.
    var err error
    for i := range h.funcs {
        err = multierr.Append(err, h.funcs[i](ent))
    }
    return err
}

hooked内嵌了Core,它覆盖了Check、With、Write方法;Check方法将hooked添加到downstream;Write方法遍历hooks,执行回调

小结

Hooks方法将log的core使用zapcore.RegisterHooks包装了一下;RegisterHooks方法创建hooked,hooks赋值给hooked的funcs属性;hooked包装了core,因而需要在Check的时候把自己注册进去,然后在Write的时候就可以执行到自己注册的hooks。一般可以将metrics等简单的操作通过hook来实现,而复杂的逻辑则最好通过实现zapcore.Core来做。

doc


有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:go4it

查看原文:聊聊golang的zap的hook

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

305 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传