序
本文次要钻研一下 golang 的 zap 的 zapgrpc
zapgrpc
zap@v1.16.0/zapgrpc/zapgrpc.go
package zapgrpc // import "go.uber.org/zap/zapgrpc"
import "go.uber.org/zap"
// An Option overrides a Logger's default configuration.
type Option interface {apply(*Logger)
}
type optionFunc func(*Logger)
func (f optionFunc) apply(log *Logger) {f(log)
}
// WithDebug configures a Logger to print at zap's DebugLevel instead of
// InfoLevel.
func WithDebug() Option {return optionFunc(func(logger *Logger) {logger.print = (*zap.SugaredLogger).Debug
logger.printf = (*zap.SugaredLogger).Debugf
})
}
// 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,
}
for _, option := range options {option.apply(logger)
}
return logger
}
// Logger adapts zap's Logger to be compatible with 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...)
}
// Print implements grpclog.Logger.
func (l *Logger) Print(args ...interface{}) {l.print(l.log, args...)
}
// Printf implements grpclog.Logger.
func (l *Logger) Printf(format string, args ...interface{}) {l.printf(l.log, format, args...)
}
// Println implements grpclog.Logger.
func (l *Logger) Println(args ...interface{}) {l.print(l.log, args...)
}
zapgrpc 提供了对 grpclog.Logger 的适配,NewLogger 将 zap.Logger 适配为 zapgrpc.Logger,而该 logger 实现了 grpclog.Logger 接口
grpclog/logger
https://github.com/grpc/grpc-…
package grpclog
import "google.golang.org/grpc/internal/grpclog"
// Logger mimics golang's standard Logger as an interface.
//
// Deprecated: use LoggerV2.
type Logger interface {Fatal(args ...interface{})
Fatalf(format string, args ...interface{})
Fatalln(args ...interface{})
Print(args ...interface{})
Printf(format string, args ...interface{})
Println(args ...interface{})
}
// SetLogger sets the logger that is used in grpc. Call only from
// init() functions.
//
// Deprecated: use SetLoggerV2.
func SetLogger(l Logger) {grpclog.Logger = &loggerWrapper{Logger: l}
}
// loggerWrapper wraps Logger into a LoggerV2.
type loggerWrapper struct {Logger}
func (g *loggerWrapper) Info(args ...interface{}) {g.Logger.Print(args...)
}
func (g *loggerWrapper) Infoln(args ...interface{}) {g.Logger.Println(args...)
}
func (g *loggerWrapper) Infof(format string, args ...interface{}) {g.Logger.Printf(format, args...)
}
func (g *loggerWrapper) Warning(args ...interface{}) {g.Logger.Print(args...)
}
func (g *loggerWrapper) Warningln(args ...interface{}) {g.Logger.Println(args...)
}
func (g *loggerWrapper) Warningf(format string, args ...interface{}) {g.Logger.Printf(format, args...)
}
func (g *loggerWrapper) Error(args ...interface{}) {g.Logger.Print(args...)
}
func (g *loggerWrapper) Errorln(args ...interface{}) {g.Logger.Println(args...)
}
func (g *loggerWrapper) Errorf(format string, args ...interface{}) {g.Logger.Printf(format, args...)
}
func (g *loggerWrapper) V(l int) bool {
// Returns true for all verbose level.
return true
}
grpclog.Logger 接口定义了 Fatal(args …interface{})、Fatalf(format string, args …interface{})、Fatalln(args …interface{})、Print(args …interface{})、Printf(format string, args …interface{})、Println(args …interface{}) 办法;而 grpclog.loggerWrapper 会对 grpclog.Logger 进行适配,转而提供了 Info、Infoln、Infof、Warning、Warningln、Warningf、Error、Errorln、Errorf 办法
实例
func Example_initialization() {
// Shared options for the logger, with a custom gRPC code to log level function.
opts := []grpc_zap.Option{grpc_zap.WithLevels(customFunc),
}
// Make sure that log statements internal to gRPC library are logged using the zapLogger as well.
grpc_zap.ReplaceGrpcLoggerV2(zapLogger)
// Create a server, make sure we put the grpc_ctxtags context before everything else.
_ = grpc.NewServer(
grpc_middleware.WithUnaryServerChain(grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
grpc_zap.UnaryServerInterceptor(zapLogger, opts...),
),
grpc_middleware.WithStreamServerChain(grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)),
grpc_zap.StreamServerInterceptor(zapLogger, opts...),
),
)
}
小结
zapgrpc 提供了对 grpclog.Logger 的适配,NewLogger 将 zap.Logger 适配为 zapgrpc.Logger,而该 logger 实现了 grpclog.Logger 接口。
doc
- zap
- logging/zap