序
本文主要研究一下zerolog的Hook
Hook
github.com/rs/zerolog@v1.20.0/hook.go
// Hook defines an interface to a log hook.
type Hook interface {
// Run runs the hook with the event.
Run(e *Event, level Level, message string)
}
Hook接口定义了Run方法,它接收event、level、message参数
LevelHook
github.com/rs/zerolog@v1.20.0/hook.go
// LevelHook applies a different hook for each level.
type LevelHook struct {
NoLevelHook, TraceHook, DebugHook, InfoHook, WarnHook, ErrorHook, FatalHook, PanicHook Hook
}
// Run implements the Hook interface.
func (h LevelHook) Run(e *Event, level Level, message string) {
switch level {
case TraceLevel:
if h.TraceHook != nil {
h.TraceHook.Run(e, level, message)
}
case DebugLevel:
if h.DebugHook != nil {
h.DebugHook.Run(e, level, message)
}
case InfoLevel:
if h.InfoHook != nil {
h.InfoHook.Run(e, level, message)
}
case WarnLevel:
if h.WarnHook != nil {
h.WarnHook.Run(e, level, message)
}
case ErrorLevel:
if h.ErrorHook != nil {
h.ErrorHook.Run(e, level, message)
}
case FatalLevel:
if h.FatalHook != nil {
h.FatalHook.Run(e, level, message)
}
case PanicLevel:
if h.PanicHook != nil {
h.PanicHook.Run(e, level, message)
}
case NoLevel:
if h.NoLevelHook != nil {
h.NoLevelHook.Run(e, level, message)
}
}
}
// NewLevelHook returns a new LevelHook.
func NewLevelHook() LevelHook {
return LevelHook{}
}
LevelHook定义了各种level的hook,其Run方法根据指定的level执行指定的hook
HookFunc
github.com/rs/zerolog@v1.20.0/hook.go
// HookFunc is an adaptor to allow the use of an ordinary function
// as a Hook.
type HookFunc func(e *Event, level Level, message string)
// Run implements the Hook interface.
func (h HookFunc) Run(e *Event, level Level, message string) {
h(e, level, message)
}
HookFunc是个func类型,它实现了Hook接口的Run方法
log.Hook
github.com/rs/zerolog@v1.20.0/log.go
type Logger struct {
w LevelWriter
level Level
sampler Sampler
context []byte
hooks []Hook
}
// Hook returns a logger with the h Hook.
func (l Logger) Hook(h Hook) Logger {
l.hooks = append(l.hooks, h)
return l
}
log.Hook方法用于注册hook
log.newEvent
github.com/rs/zerolog@v1.20.0/log.go
func (l *Logger) newEvent(level Level, done func(string)) *Event {
enabled := l.should(level)
if !enabled {
return nil
}
e := newEvent(l.w, level)
e.done = done
e.ch = l.hooks
if level != NoLevel {
e.Str(LevelFieldName, LevelFieldMarshalFunc(level))
}
if l.context != nil && len(l.context) > 1 {
e.buf = enc.AppendObjectData(e.buf, l.context)
}
return e
}
log.newEvent方法在创建event的时候会把自己的hooks拷贝给event
msg
github.com/rs/zerolog@v1.20.0/event.go
func (e *Event) msg(msg string) {
for _, hook := range e.ch {
hook.Run(e, e.level, msg)
}
if msg != "" {
e.buf = enc.AppendString(enc.AppendKey(e.buf, MessageFieldName), msg)
}
if e.done != nil {
defer e.done(msg)
}
if err := e.write(); err != nil {
if ErrorHandler != nil {
ErrorHandler(err)
} else {
fmt.Fprintf(os.Stderr, "zerolog: could not write event: %v\n", err)
}
}
}
event的msg方法会遍历event的hooks,然后挨个执行Hook的Run方法
实例
type SeverityHook struct{}
func (h SeverityHook) Run(e *zerolog.Event, level zerolog.Level, msg string) {
if level != zerolog.NoLevel {
e.Str("abc", "form hook")
}
}
func hookDemo() {
hooked := log.Hook(SeverityHook{})
hooked.Warn().Msg("hello")
}
输出
{"level":"warn","time":"2021-01-07T23:07:13+08:00","abc":"form hook","message":"hello"}
小结
zerolog提供了Hook接口,用于修改event;log.Hook方法用于注册hook;log.newEvent方法在创建event的时候会把自己的hooks拷贝给event;event的msg方法会遍历event的hooks,然后挨个执行Hook的Run方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。