本文主要研究一下zerolog的LevelWritergit
github.com/rs/zerolog@v1.20.0/writer.gogithub
// 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方法
github.com/rs/zerolog@v1.20.0/writer.goapp
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方法來輸出
github.com/rs/zerolog@v1.20.0/writer.goide
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
github.com/rs/zerolog@v1.20.0/writer.gocode
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來指定多個輸出
輸出orm
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。接口