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
184 changes: 151 additions & 33 deletions zapgrpc/zapgrpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,31 @@
// Package zapgrpc provides a logger that is compatible with grpclog.
package zapgrpc // import "go.uber.org/zap/zapgrpc"

import "go.uber.org/zap"
import (
"fmt"

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

// See https://github.com/grpc/grpc-go/blob/v1.35.0/grpclog/loggerv2.go#L77-L86
const (
grpcLvlInfo = 0
grpcLvlWarn = 1
grpcLvlError = 2
grpcLvlFatal = 3
)

var (
// _grpcToZapLevel maps gRPC log levels to zap log levels.
// See https://pkg.go.dev/go.uber.org/zap@v1.16.0/zapcore#Level
_grpcToZapLevel = map[int]zapcore.Level{
grpcLvlInfo: zapcore.InfoLevel,
grpcLvlWarn: zapcore.WarnLevel,
grpcLvlError: zapcore.ErrorLevel,
grpcLvlFatal: zapcore.FatalLevel,
}
)

// An Option overrides a Logger's default configuration.
type Option interface {
Expand All @@ -36,65 +60,159 @@ 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(),
levelEnabler: l.Core(),
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{})
delegate *zap.SugaredLogger
levelEnabler zapcore.LevelEnabler
printToDebug bool
fatalToWarn bool
}

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

// Fatalf implements grpclog.Logger.
func (l *Logger) Fatalf(format string, args ...interface{}) {
l.fatalf(l.log, format, args...)
// Printf implements grpclog.Logger.
// Deprecated: use Infof().
func (l *Logger) Printf(format string, args ...interface{}) {
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{}) {
if l.printToDebug {
if l.levelEnabler.Enabled(zapcore.DebugLevel) {
l.delegate.Debug(sprintln(args))
}
} else {
if l.levelEnabler.Enabled(zapcore.InfoLevel) {
l.delegate.Info(sprintln(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
if l.levelEnabler.Enabled(zapcore.InfoLevel) {
l.delegate.Info(sprintln(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{}) {
if l.levelEnabler.Enabled(zapcore.WarnLevel) {
l.delegate.Warn(sprintln(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{}) {
if l.levelEnabler.Enabled(zapcore.ErrorLevel) {
l.delegate.Error(sprintln(args))
}
}

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

// Fatalln implements grpclog.Logger.
// 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(l.log, args...)
if l.fatalToWarn {
if l.levelEnabler.Enabled(zapcore.WarnLevel) {
l.delegate.Warn(sprintln(args))
}
} else {
if l.levelEnabler.Enabled(zapcore.FatalLevel) {
l.delegate.Fatal(sprintln(args))
}
}
}

// Print implements grpclog.Logger.
func (l *Logger) Print(args ...interface{}) {
l.print(l.log, 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...)
}
}

// Printf implements grpclog.Logger.
func (l *Logger) Printf(format string, args ...interface{}) {
l.printf(l.log, format, args...)
// V implements grpclog.LoggerV2.
func (l *Logger) V(level int) bool {
return l.levelEnabler.Enabled(_grpcToZapLevel[level])
}

// Println implements grpclog.Logger.
func (l *Logger) Println(args ...interface{}) {
l.print(l.log, args...)
func sprintln(args []interface{}) string {
s := fmt.Sprintln(args...)
// Drop the new line character added by Sprintln
return s[:len(s)-1]
ash2k marked this conversation as resolved.
Show resolved Hide resolved
}
Loading