sequence
This paper mainly studies the hook of Golang’s Zap
The instance
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")
}
Copy the code
The output
{" 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 worldCopy the code
Hooks
[email protected] / options. Go
func Hooks(hooks ...func(zapcore.Entry) error) Option {
return optionFunc(func(log *Logger) {
log.core = zapcore.RegisterHooks(log.core, hooks...)
})
}
Copy the code
The Hooks method wraps the log core using zapcore.registerhooks
zapcore.RegisterHooks
[email protected] / zapcore/hook. Go
func RegisterHooks(core Core, hooks ... func(Entry) error) Core { funcs := append([]func(Entry) error{}, hooks...) return &hooked{ Core: core, funcs: funcs, } }Copy the code
The RegisterHooks method creates hooked, which hooks assign to the funcs property of hooked
hook
[email protected] / 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 }Copy the code
Hooked is embedded With Core, which overrides the Check, With, and Write methods. The Check method adds a hooked to the downstream; The Write method iterates through hooks, performing the callback
summary
The Hooks method wraps the log core with zapcore.registerhooks; The RegisterHooks method creates hooked, which assigns the funcs attribute to that hooked; Hooked wraps Core, so you need to register yourself when you Check, and then execute your registered hooks when you Write. You can hook things like metrics, but more complex logic is best done by implementing Zapcore.core.
doc
- zap