Codebase list golang-github-go-kit-kit / 22ff154
log: Update NewSyncWriter to work with term.IsTerminal. - Change the return type to io.Writer - Return an io.Writer that also has the `Fd() uintptr` method of the wrapped io.Writer if present. Chris Hines 7 years ago
2 changed file(s) with 61 addition(s) and 15 deletion(s). Raw diff Collapse all Expand all
0 package log
0 package log
11
22 import (
33 "io"
3535 l.logger.Store(loggerStruct{logger})
3636 }
3737
38 // SyncWriter synchronizes concurrent writes to an io.Writer.
39 type SyncWriter struct {
40 mu sync.Mutex
41 w io.Writer
38 // NewSyncWriter returns a new writer that is safe for concurrent use by
39 // multiple goroutines. Writes to the returned writer are passed on to w. If
40 // another write is already in progress, the calling goroutine blocks until
41 // the writer is available.
42 //
43 // If w implements the following interface, so does the returned writer.
44 //
45 // interface {
46 // Fd() uintptr
47 // }
48 func NewSyncWriter(w io.Writer) io.Writer {
49 switch w := w.(type) {
50 case fdWriter:
51 return &fdSyncWriter{fdWriter: w}
52 default:
53 return &syncWriter{Writer: w}
54 }
4255 }
4356
44 // NewSyncWriter returns a new SyncWriter. The returned writer is safe for
45 // concurrent use by multiple goroutines.
46 func NewSyncWriter(w io.Writer) *SyncWriter {
47 return &SyncWriter{w: w}
57 // syncWriter synchronizes concurrent writes to an io.Writer.
58 type syncWriter struct {
59 sync.Mutex
60 io.Writer
4861 }
4962
5063 // Write writes p to the underlying io.Writer. If another write is already in
51 // progress, the calling goroutine blocks until the SyncWriter is available.
52 func (w *SyncWriter) Write(p []byte) (n int, err error) {
53 w.mu.Lock()
54 n, err = w.w.Write(p)
55 w.mu.Unlock()
64 // progress, the calling goroutine blocks until the syncWriter is available.
65 func (w *syncWriter) Write(p []byte) (n int, err error) {
66 w.Lock()
67 n, err = w.Writer.Write(p)
68 w.Unlock()
69 return n, err
70 }
71
72 // fdWriter is an io.Writer that also has an Fd method. The most common
73 // example of an fdWriter is an *os.File.
74 type fdWriter interface {
75 io.Writer
76 Fd() uintptr
77 }
78
79 // fdSyncWriter synchronizes concurrent writes to an fdWriter.
80 type fdSyncWriter struct {
81 sync.Mutex
82 fdWriter
83 }
84
85 // Write writes p to the underlying io.Writer. If another write is already in
86 // progress, the calling goroutine blocks until the fdSyncWriter is available.
87 func (w *fdSyncWriter) Write(p []byte) (n int, err error) {
88 w.Lock()
89 n, err = w.fdWriter.Write(p)
90 w.Unlock()
5691 return n, err
5792 }
5893
0 package log_test
0 package log_test
11
22 import (
33 "bytes"
44 "io"
5 "os"
56 "testing"
67
78 "github.com/go-kit/kit/log"
6970 w = log.NewSyncWriter(w)
7071 testConcurrency(t, log.NewLogfmtLogger(w), 10000)
7172 }
73
74 func TestSyncWriterFd(t *testing.T) {
75 _, ok := log.NewSyncWriter(os.Stdout).(interface {
76 Fd() uintptr
77 })
78
79 if !ok {
80 t.Error("NewSyncWriter does not pass through Fd method")
81 }
82 }