Add SyncWriter utility type for non-thread-safe writers
This commit is contained in:
parent
5ebf00efab
commit
af9dd4ec23
8
log.go
8
log.go
|
@ -139,7 +139,13 @@ type Logger struct {
|
||||||
counter *uint32
|
counter *uint32
|
||||||
}
|
}
|
||||||
|
|
||||||
// New creates a root logger with given output writer.
|
// New creates a root logger with given output writer. If the output writer implements
|
||||||
|
// the LevelWriter interface, the WriteLevel method will be called instead of the Write
|
||||||
|
// one.
|
||||||
|
//
|
||||||
|
// Each logging operation makes a single call to the Writer's Write method. There is no
|
||||||
|
// guaranty on access serialization to the Writer. If your Writer is not thread safe,
|
||||||
|
// you may consider using sync wrapper.
|
||||||
func New(w io.Writer) Logger {
|
func New(w io.Writer) Logger {
|
||||||
if w == nil {
|
if w == nil {
|
||||||
panic("w is nil")
|
panic("w is nil")
|
||||||
|
|
41
writer.go
41
writer.go
|
@ -1,6 +1,9 @@
|
||||||
package zerolog
|
package zerolog
|
||||||
|
|
||||||
import "io"
|
import (
|
||||||
|
"io"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
// LevelWriter defines as interface a writer may implement in order
|
// LevelWriter defines as interface a writer may implement in order
|
||||||
// to receive level information with payload.
|
// to receive level information with payload.
|
||||||
|
@ -13,10 +16,44 @@ type levelWriterAdapter struct {
|
||||||
io.Writer
|
io.Writer
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lw levelWriterAdapter) WriteLevel(level Level, p []byte) (n int, err error) {
|
func (lw levelWriterAdapter) WriteLevel(l Level, p []byte) (n int, err error) {
|
||||||
return lw.Write(p)
|
return lw.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type syncWriter struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
lw LevelWriter
|
||||||
|
}
|
||||||
|
|
||||||
|
// SyncWriter wraps w so that each call to Write is synchronized with a mutex.
|
||||||
|
// This syncer can be the call to writer's Write method is not thread safe.
|
||||||
|
// Note that os.File Write operation is using write() syscall which is supposed
|
||||||
|
// to be thread-safe on POSIX systems. So there is no need to use this with
|
||||||
|
// os.File on such systems as zerolog guaranties to issue a single Write call
|
||||||
|
// per log event.
|
||||||
|
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()
|
||||||
|
n, err = s.lw.Write(p)
|
||||||
|
s.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// WriteLevel implements the LevelWriter interface.
|
||||||
|
func (s *syncWriter) WriteLevel(l Level, p []byte) (n int, err error) {
|
||||||
|
s.mu.Lock()
|
||||||
|
n, err = s.lw.WriteLevel(l, p)
|
||||||
|
s.mu.Unlock()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
type multiLevelWriter struct {
|
type multiLevelWriter struct {
|
||||||
writers []LevelWriter
|
writers []LevelWriter
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue