聊聊golang的zap的hook
序
本文主要研究一下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
[email protected]/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
[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, } }
RegisterHooks方法创建hooked,hooks赋值给hooked的funcs属性
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 }
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
「其他文章」
- 10 个解放双手超实用在线工具,有些代码真的不用手写
- 再见了,搬运党们
- JwChat:一款基于Vue和ElementUI的极简聊天框组件
- 主机回来以及,简单的环境配置(RTX3070 CUDA11.1 CUDNN TensorRT)
- 打造综合性智慧城市之朔州开发区3d可视化
- 如何实现一个简易版的 Spring - 如何实现 @Autowired 注解
- Java性能优化的十条小技巧
- Java的循环结构
- java中的数据类型
- Chrome 录屏神器!自称“最强大”的屏幕录制和注释工具!
- 如何在微信小程序中使用多色icon
- 关于Webpack
- 举世闻名的 SQL 注入是什么?这个漫画告诉你!
- 分布式缓存-Redis
- JDK1.8 ConcurrentHashMap解析
- Kubernetes 实战 —— 02. 开始使用 Kubernetes 和 Docker
- PromQL的简单使用
- Redis 持久化之 rdb
- 二、Spring事务执行流程
- 浅谈设计模式 - 模板方法(十)