Skip to content

Commit

Permalink
Support construction of zap-backed log.Loggers (#353)
Browse files Browse the repository at this point in the history
In addition to letting users redirect the output of the standard library's package-global log functions, we should also support wrapping a zap logger in a log.Logger.

This is the same PR as #344, which I somehow closed by mistake :/
  • Loading branch information
akshayjshah committed Mar 7, 2017
1 parent 1d90273 commit 05dc1c4
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 7 deletions.
24 changes: 17 additions & 7 deletions global.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ import (
"sync"
)

const (
_stdLogDefaultDepth = 4
_loggerWriterDepth = 1
)

var (
_globalMu sync.RWMutex
_globalL = NewNop()
Expand Down Expand Up @@ -67,24 +72,29 @@ func ReplaceGlobals(logger *Logger) func() {
return func() { ReplaceGlobals(prev) }
}

// RedirectStdLog redirects output from the standard library's "log" package to
// the supplied logger at InfoLevel. Since zap already handles caller
// NewStdLog returns a *log.Logger which writes to the supplied zap Logger at
// InfoLevel. To redirect the standard library's package-global logging
// functions, use RedirectStdLog instead.
func NewStdLog(l *Logger) *log.Logger {
return log.New(&loggerWriter{l.WithOptions(
AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth),
)}, "" /* prefix */, 0 /* flags */)
}

// RedirectStdLog redirects output from the standard library's package-global
// logger to the supplied logger at InfoLevel. Since zap already handles caller
// annotations, timestamps, etc., it automatically disables the standard
// library's annotations and prefixing.
//
// It returns a function to restore the original prefix and flags and reset the
// standard library's output to os.Stdout.
func RedirectStdLog(l *Logger) func() {
const (
stdLogDefaultDepth = 4
loggerWriterDepth = 1
)
flags := log.Flags()
prefix := log.Prefix()
log.SetFlags(0)
log.SetPrefix("")
log.SetOutput(&loggerWriter{l.WithOptions(
AddCallerSkip(stdLogDefaultDepth + loggerWriterDepth),
AddCallerSkip(_stdLogDefaultDepth + _loggerWriterDepth),
)})
return func() {
log.SetFlags(flags)
Expand Down
13 changes: 13 additions & 0 deletions global_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,19 @@ func TestGlobalsConcurrentUse(t *testing.T) {
wg.Wait()
}

func TestNewStdLog(t *testing.T) {
withLogger(t, DebugLevel, []Option{AddCaller()}, func(l *Logger, logs *observer.ObservedLogs) {
std := NewStdLog(l)
std.Print("redirected")

require.Equal(t, 1, logs.Len(), "Expected exactly one entry to be logged.")
entry := logs.AllUntimed()[0]
assert.Equal(t, []zapcore.Field{}, entry.Context, "Unexpected entry context.")
assert.Equal(t, "redirected", entry.Entry.Message, "Unexpected entry message.")
assert.Contains(t, entry.Entry.Caller.File, "global_test.go", "Unexpected caller annotation.")
})
}

func TestRedirectStdLog(t *testing.T) {
initialFlags := log.Flags()
initialPrefix := log.Prefix()
Expand Down

0 comments on commit 05dc1c4

Please sign in to comment.