Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for grpclog.LoggerV2 #881

Merged
merged 13 commits into from Feb 12, 2021
135 changes: 101 additions & 34 deletions zapgrpc/zapgrpc.go
Expand Up @@ -21,7 +21,10 @@
// Package zapgrpc provides a logger that is compatible with grpclog.
package zapgrpc // import "go.uber.org/zap/zapgrpc"

import "go.uber.org/zap"
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)

// An Option overrides a Logger's default configuration.
type Option interface {
Expand All @@ -36,65 +39,129 @@ func (f optionFunc) apply(log *Logger) {

// WithDebug configures a Logger to print at zap's DebugLevel instead of
// InfoLevel.
// It only affects the Printf, Println and Print methods, which are only used in the gRPC v1 grpclog.Logger API.
// Deprecated: use grpclog.SetLoggerV2() for v2 API.
func WithDebug() Option {
return optionFunc(func(logger *Logger) {
logger.print = (*zap.SugaredLogger).Debug
logger.printf = (*zap.SugaredLogger).Debugf
logger.printToDebug = true
})
}

// NewLogger returns a new Logger.
//
// By default, Loggers print at zap's InfoLevel.
func NewLogger(l *zap.Logger, options ...Option) *Logger {
logger := &Logger{
log: l.Sugar(),
fatal: (*zap.SugaredLogger).Fatal,
fatalf: (*zap.SugaredLogger).Fatalf,
print: (*zap.SugaredLogger).Info,
printf: (*zap.SugaredLogger).Infof,
delegate: l.Sugar(),
printToDebug: false,
fatalToWarn: false,
}
for _, option := range options {
option.apply(logger)
}
return logger
}

// Logger adapts zap's Logger to be compatible with grpclog.Logger.
// Logger adapts zap's Logger to be compatible with grpclog.LoggerV2 and the deprecated grpclog.Logger.
type Logger struct {
log *zap.SugaredLogger
fatal func(*zap.SugaredLogger, ...interface{})
fatalf func(*zap.SugaredLogger, string, ...interface{})
print func(*zap.SugaredLogger, ...interface{})
printf func(*zap.SugaredLogger, string, ...interface{})
}

// Fatal implements grpclog.Logger.
func (l *Logger) Fatal(args ...interface{}) {
l.fatal(l.log, args...)
}

// Fatalf implements grpclog.Logger.
func (l *Logger) Fatalf(format string, args ...interface{}) {
l.fatalf(l.log, format, args...)
}

// Fatalln implements grpclog.Logger.
func (l *Logger) Fatalln(args ...interface{}) {
l.fatal(l.log, args...)
delegate *zap.SugaredLogger
printToDebug bool
fatalToWarn bool
}

// Print implements grpclog.Logger.
// Deprecated: use Info().
func (l *Logger) Print(args ...interface{}) {
l.print(l.log, args...)
if l.printToDebug {
l.delegate.Debug(args...)
} else {
l.delegate.Info(args...)
}
}

// Printf implements grpclog.Logger.
// Deprecated: use Infof().
func (l *Logger) Printf(format string, args ...interface{}) {
l.printf(l.log, format, args...)
if l.printToDebug {
l.delegate.Debugf(format, args...)
} else {
l.delegate.Infof(format, args...)
}
}

// Println implements grpclog.Logger.
// Deprecated: use Info().
func (l *Logger) Println(args ...interface{}) {
l.print(l.log, args...)
l.Print(args...)
}

// Info implements grpclog.LoggerV2.
func (l *Logger) Info(args ...interface{}) {
l.delegate.Info(args...)
}

// Infoln implements grpclog.LoggerV2.
func (l *Logger) Infoln(args ...interface{}) {
ash2k marked this conversation as resolved.
Show resolved Hide resolved
l.delegate.Info(args...)
}

// Infof implements grpclog.LoggerV2.
func (l *Logger) Infof(format string, args ...interface{}) {
l.delegate.Infof(format, args...)
}

// Warning implements grpclog.LoggerV2.
func (l *Logger) Warning(args ...interface{}) {
l.delegate.Warn(args...)
}

// Warningln implements grpclog.LoggerV2.
func (l *Logger) Warningln(args ...interface{}) {
l.delegate.Warn(args...)
}

// Warningf implements grpclog.LoggerV2.
func (l *Logger) Warningf(format string, args ...interface{}) {
l.delegate.Warnf(format, args...)
}

// Error implements grpclog.LoggerV2.
func (l *Logger) Error(args ...interface{}) {
l.delegate.Error(args...)
}

// Errorln implements grpclog.LoggerV2.
func (l *Logger) Errorln(args ...interface{}) {
l.delegate.Error(args...)
}

// Errorf implements grpclog.LoggerV2.
func (l *Logger) Errorf(format string, args ...interface{}) {
l.delegate.Errorf(format, args...)
}

// Fatal implements grpclog.LoggerV2.
func (l *Logger) Fatal(args ...interface{}) {
if l.fatalToWarn {
l.delegate.Warn(args...)
} else {
l.delegate.Fatal(args...)
}
}

// Fatalln implements grpclog.LoggerV2.
func (l *Logger) Fatalln(args ...interface{}) {
l.Fatal(args...)
}

// Fatalf implements grpclog.LoggerV2.
func (l *Logger) Fatalf(format string, args ...interface{}) {
if l.fatalToWarn {
l.delegate.Warnf(format, args...)
} else {
l.delegate.Fatalf(format, args...)
}
}

// V implements grpclog.LoggerV2.
func (l *Logger) V(level int) bool {
return l.delegate.Desugar().Core().Enabled(zapcore.Level(level))
ash2k marked this conversation as resolved.
Show resolved Hide resolved
}
61 changes: 59 additions & 2 deletions zapgrpc/zapgrpc_test.go
Expand Up @@ -35,7 +35,13 @@ func TestLoggerInfoExpected(t *testing.T) {
"hello",
"world",
"foo",
"hello",
"world",
"foo",
}, func(logger *Logger) {
logger.Info("hello")
logger.Infof("world")
logger.Infoln("foo")
logger.Print("hello")
logger.Printf("world")
logger.Println("foo")
Expand All @@ -62,6 +68,30 @@ func TestLoggerDebugSuppressed(t *testing.T) {
})
}

func TestLoggerWarningExpected(t *testing.T) {
checkMessages(t, zapcore.DebugLevel, nil, zapcore.WarnLevel, []string{
"hello",
"world",
"foo",
}, func(logger *Logger) {
logger.Warning("hello")
logger.Warningf("world")
logger.Warningln("foo")
})
}

func TestLoggerErrorExpected(t *testing.T) {
checkMessages(t, zapcore.DebugLevel, nil, zapcore.ErrorLevel, []string{
"hello",
"world",
"foo",
}, func(logger *Logger) {
logger.Error("hello")
logger.Errorf("world")
logger.Errorln("foo")
})
}

func TestLoggerFatalExpected(t *testing.T) {
checkMessages(t, zapcore.DebugLevel, nil, zapcore.FatalLevel, []string{
"hello",
Expand All @@ -74,6 +104,34 @@ func TestLoggerFatalExpected(t *testing.T) {
})
}

func TestLoggerVTrueExpected(t *testing.T) {
checkLevel(t, zapcore.DebugLevel, true, func(logger *Logger) bool {
return logger.V(0)
})
}

func TestLoggerVFalseExpected(t *testing.T) {
ash2k marked this conversation as resolved.
Show resolved Hide resolved
checkLevel(t, zapcore.WarnLevel, false, func(logger *Logger) bool {
return logger.V(0)
})
}

func checkLevel(
t testing.TB,
enab zapcore.LevelEnabler,
expectedBool bool,
f func(*Logger) bool,
) {
withLogger(enab, nil, func(logger *Logger, observedLogs *observer.ObservedLogs) {
actualBool := f(logger)
if expectedBool {
require.True(t, actualBool)
} else {
require.False(t, actualBool)
}
})
}

func checkMessages(
t testing.TB,
enab zapcore.LevelEnabler,
Expand Down Expand Up @@ -109,7 +167,6 @@ func withLogger(
// easier.
func withWarn() Option {
return optionFunc(func(logger *Logger) {
logger.fatal = (*zap.SugaredLogger).Warn
logger.fatalf = (*zap.SugaredLogger).Warnf
logger.fatalToWarn = true
})
}