本文主要研究一下zerolog的send
func sendDemo() { zerolog.TimeFieldFormat = zerolog.TimeFormatUnix log.Info(). Str("Name", "Tom"). Send() log.Info(). Str("Name", "Tom"). Msg("hello world") }
使用Send或者Msg来发送log
输出
{"level":"info","Name":"Tom","time":1609509525} {"level":"info","Name":"Tom","time":1609509525,"message":"hello world"}
github.com/rs/zerolog@v1.20.0/event.go
// Send is equivalent to calling Msg(""). // // NOTICE: once this method is called, the *Event should be disposed. func (e *Event) Send() { if e == nil { return } e.msg("") }
Send方法相当于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) } } }
msg方法先执行hook,之后对于有msg的添加message字段,如果done不为nil则defer注册回调,之后执行e.write()
github.com/rs/zerolog@v1.20.0/event.go
func (e *Event) write() (err error) { if e == nil { return nil } if e.level != Disabled { e.buf = enc.AppendEndMarker(e.buf) e.buf = enc.AppendLineBreak(e.buf) if e.w != nil { _, err = e.w.WriteLevel(e.level, e.buf) } } putEvent(e) return }
write在level不为Disabled的时候会追加endMarker及lineBreaker;对于e.w不为nil时,执行e.w.WriteLevel(e.level, e.buf)进行输出;之后执行putEvent归还event
github.com/rs/zerolog@v1.20.0/event.go
func putEvent(e *Event) { // Proper usage of a sync.Pool requires each entry to have approximately // the same memory cost. To obtain this property when the stored type // contains a variably-sized buffer, we add a hard limit on the maximum buffer // to place back in the pool. // // See https://golang.org/issue/23199 const maxSize = 1 << 16 // 64KiB if cap(e.buf) > maxSize { return } eventPool.Put(e) }
putEvent方法先判断e.buf的大小是否超过maxSize,超过则直接返回,否则执行eventPool.Put(e)将event归还到eventPool中
github.com/rs/zerolog@v1.20.0/log.go
// Info starts a new message with info level. // // You must call Msg on the returned event in order to send the event. func (l *Logger) Info() *Event { return l.newEvent(InfoLevel, nil) }
Info方法执行的l.newEvent(InfoLevel, nil)
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 } func newEvent(w LevelWriter, level Level) *Event { e := eventPool.Get().(*Event) e.buf = e.buf[:0] e.ch = nil e.buf = enc.AppendBeginMarker(e.buf) e.w = w e.level = level e.stack = false return e }
newEvent方法从eventPool获取Event,然后设置done、hooks等属性
zerolog的Send方法相当于Msg("");newEvent方法从eventPool获取Event,然后设置done、hooks等属性;write在level不为Disabled的时候会追加endMarker及lineBreaker;对于e.w不为nil时,执行e.w.WriteLevel(e.level, e.buf)进行输出;之后执行putEvent归还event;