本文次要钻研一下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

  • zap