序
本文次要钻研一下 zerolog 的 LevelWriter
LevelWriter
github.com/rs/zerolog@v1.20.0/writer.go
// LevelWriter defines as interface a writer may implement in order
// to receive level information with payload.
type LevelWriter interface {
io.Writer
WriteLevel(level Level, p []byte) (n int, err error)
}
type Writer interface {Write(p []byte) (n int, err error)
}
LevelWriter 接口内嵌了 io.Writer 接口,定义了 WriteLevel 办法
levelWriterAdapter
github.com/rs/zerolog@v1.20.0/writer.go
type levelWriterAdapter struct {io.Writer}
func (lw levelWriterAdapter) WriteLevel(l Level, p []byte) (n int, err error) {return lw.Write(p)
}
levelWriterAdapter 内嵌了 io.Writer 属性,实现了 LevelWriter 的 WriteLevel 办法,该办法外部通过 io.Writer 属性的 Write 办法来输入
syncWriter
github.com/rs/zerolog@v1.20.0/writer.go
type syncWriter struct {
mu sync.Mutex
lw LevelWriter
}
func SyncWriter(w io.Writer) io.Writer {if lw, ok := w.(LevelWriter); ok {return &syncWriter{lw: lw}
}
return &syncWriter{lw: levelWriterAdapter{w}}
}
// Write implements the io.Writer interface.
func (s *syncWriter) Write(p []byte) (n int, err error) {s.mu.Lock()
defer s.mu.Unlock()
return s.lw.Write(p)
}
// WriteLevel implements the LevelWriter interface.
func (s *syncWriter) WriteLevel(l Level, p []byte) (n int, err error) {s.mu.Lock()
defer s.mu.Unlock()
return s.lw.WriteLevel(l, p)
}
syncWriter 实现了 LevelWriter 接口,其对 Write 及 WriteLevel 办法都进行了加锁;SyncWriter 办法通过 levelWriterAdapter 来适配 io.Writer
multiLevelWriter
github.com/rs/zerolog@v1.20.0/writer.go
type multiLevelWriter struct {writers []LevelWriter
}
func (t multiLevelWriter) Write(p []byte) (n int, err error) {
for _, w := range t.writers {n, err = w.Write(p)
if err != nil {return}
if n != len(p) {
err = io.ErrShortWrite
return
}
}
return len(p), nil
}
func (t multiLevelWriter) WriteLevel(l Level, p []byte) (n int, err error) {
for _, w := range t.writers {n, err = w.WriteLevel(l, p)
if err != nil {return}
if n != len(p) {
err = io.ErrShortWrite
return
}
}
return len(p), nil
}
// MultiLevelWriter creates a writer that duplicates its writes to all the
// provided writers, similar to the Unix tee(1) command. If some writers
// implement LevelWriter, their WriteLevel method will be used instead of Write.
func MultiLevelWriter(writers ...io.Writer) LevelWriter {lwriters := make([]LevelWriter, 0, len(writers))
for _, w := range writers {if lw, ok := w.(LevelWriter); ok {lwriters = append(lwriters, lw)
} else {lwriters = append(lwriters, levelWriterAdapter{w})
}
}
return multiLevelWriter{lwriters}
}
multiLevelWriter 定义了 writers 属性,它也实现了 LevelWriter 接口,其 Write 及 WriteLevel 办法均是遍历 writers 挨个执行对应操作;MultiLevelWriter 办法通过 levelWriterAdapter 来适配 io.Writer
实例
func multiLevelWriterDemo() {consoleWriter := zerolog.ConsoleWriter{Out: os.Stdout}
multi := zerolog.MultiLevelWriter(consoleWriter, os.Stdout)
logger := zerolog.New(multi).With().Timestamp().Logger()
logger.Info().Msg("Hello World!")
}
这里应用 zerolog.MultiLevelWriter 来指定多个输入
输入
8:02PM INF Hello World!
{"level":"info","time":"2021-01-02T20:02:27+08:00","message":"Hello World!"}
小结
LevelWriter 接口内嵌了 io.Writer 接口,定义了 WriteLevel 办法;levelWriterAdapter 内嵌了 io.Writer 属性,实现了 LevelWriter 的 WriteLevel 办法,该办法外部通过 io.Writer 属性的 Write 办法来输入;SyncWriter 办法通过 levelWriterAdapter 来适配 io.Writer;MultiLevelWriter 办法通过 levelWriterAdapter 来适配 io.Writer。
doc
- zerolog