diff --git a/log/sync.go b/log/sync.go index 8ce0db8bf..7944459b6 100644 --- a/log/sync.go +++ b/log/sync.go @@ -42,6 +42,11 @@ type SyncWriter struct { w io.Writer } +// ChildWriter returns the associated child io.Writer. +func (w *SyncWriter) ChildWriter() io.Writer { + return w.w +} + // NewSyncWriter returns a new SyncWriter. The returned writer is safe for // concurrent use by multiple goroutines. func NewSyncWriter(w io.Writer) *SyncWriter { diff --git a/log/sync_test.go b/log/sync_test.go index 3d915ec7b..08babb026 100644 --- a/log/sync_test.go +++ b/log/sync_test.go @@ -70,3 +70,13 @@ func TestSyncWriterConcurrency(t *testing.T) { w = log.NewSyncWriter(w) testConcurrency(t, log.NewLogfmtLogger(w), 10000) } + +func TestSyncWriterChildWriter(t *testing.T) { + want := &bytes.Buffer{} + w := log.NewSyncWriter(want) + got := w.ChildWriter() + + if got != want { + t.Errorf("got %v, want %v", got, want) + } +} diff --git a/log/term/colorwriter_windows.go b/log/term/colorwriter_windows.go index 4d2d67375..316b066f3 100644 --- a/log/term/colorwriter_windows.go +++ b/log/term/colorwriter_windows.go @@ -25,12 +25,14 @@ type colorWriter struct { // platform support for ANSI color codes. If w is not a terminal it is // returned unmodified. func NewColorWriter(w io.Writer) io.Writer { - if !IsTerminal(w) { + cw := resolveWriter(w) + + if !IsTerminal(cw) { return w } var csbi consoleScreenBufferInfo - handle := syscall.Handle(w.(fder).Fd()) + handle := syscall.Handle(cw.(fder).Fd()) procGetConsoleScreenBufferInfo.Call(uintptr(handle), uintptr(unsafe.Pointer(&csbi))) return &colorWriter{ diff --git a/log/term/term.go b/log/term/term.go index 3965f1c8b..c4028e5f3 100644 --- a/log/term/term.go +++ b/log/term/term.go @@ -7,11 +7,23 @@ import ( "github.com/go-kit/kit/log" ) +type parentWriter interface { + ChildWriter() io.Writer +} + +func resolveWriter(w io.Writer) io.Writer { + if w, ok := w.(parentWriter); ok { + return resolveWriter(w.ChildWriter()) + } + + return w +} + // NewLogger returns a Logger that takes advantage of terminal features if // possible. Log events are formatted by the Logger returned by newLogger. If // w is a terminal each log event is colored according to the color function. func NewLogger(w io.Writer, newLogger func(io.Writer) log.Logger, color func(keyvals ...interface{}) FgBgColor) log.Logger { - if !IsTerminal(w) { + if !IsTerminal(resolveWriter(w)) { return newLogger(w) } return NewColorLogger(NewColorWriter(w), newLogger, color)