// Copyright 2017 Michal Witkowski. All Rights Reserved. // See LICENSE for licensing terms. package grpc_zap import ( "fmt" grpc_logsettable "github.com/grpc-ecosystem/go-grpc-middleware/logging/settable" "go.uber.org/zap" "google.golang.org/grpc/grpclog" ) // ReplaceGrpcLogger sets the given zap.Logger as a gRPC-level logger. // This should be called *before* any other initialization, preferably from init() functions. // Deprecated: use ReplaceGrpcLoggerV2. func ReplaceGrpcLogger(logger *zap.Logger) { zgl := &zapGrpcLogger{logger.With(SystemField, zap.Bool("grpc_log", true))} grpclog.SetLogger(zgl) } type zapGrpcLogger struct { logger *zap.Logger } func (l *zapGrpcLogger) Fatal(args ...interface{}) { l.logger.Fatal(fmt.Sprint(args...)) } func (l *zapGrpcLogger) Fatalf(format string, args ...interface{}) { l.logger.Fatal(fmt.Sprintf(format, args...)) } func (l *zapGrpcLogger) Fatalln(args ...interface{}) { l.logger.Fatal(fmt.Sprint(args...)) } func (l *zapGrpcLogger) Print(args ...interface{}) { l.logger.Info(fmt.Sprint(args...)) } func (l *zapGrpcLogger) Printf(format string, args ...interface{}) { l.logger.Info(fmt.Sprintf(format, args...)) } func (l *zapGrpcLogger) Println(args ...interface{}) { l.logger.Info(fmt.Sprint(args...)) } // ReplaceGrpcLoggerV2 replaces the grpclog.LoggerV2 with the provided logger. // It should be called before any gRPC functions. Logging verbosity defaults to info level. // To adjust gRPC logging verbosity, see ReplaceGrpcLoggerV2WithVerbosity. func ReplaceGrpcLoggerV2(logger *zap.Logger) { ReplaceGrpcLoggerV2WithVerbosity(logger, 0) } // ReplaceGrpcLoggerV2WithVerbosity replaces the grpclog.Logger with the provided logger and verbosity. // It should be called before any gRPC functions. // verbosity correlates to grpclogs verbosity levels. A higher verbosity value results in less logging. func ReplaceGrpcLoggerV2WithVerbosity(logger *zap.Logger, verbosity int) { zgl := &zapGrpcLoggerV2{ logger: logger.With(SystemField, zap.Bool("grpc_log", true)).WithOptions(zap.AddCallerSkip(2)), verbosity: verbosity, } grpclog.SetLoggerV2(zgl) } // SetGrpcLoggerV2 replaces the grpc_log.Logger with the provided logger. // It can be used even when grpc infrastructure was initialized. func SetGrpcLoggerV2(settable grpc_logsettable.SettableLoggerV2, logger *zap.Logger) { SetGrpcLoggerV2WithVerbosity(settable, logger, 0) } // SetGrpcLoggerV2WithVerbosity replaces the grpc_.LoggerV2 with the provided logger and verbosity. // It can be used even when grpc infrastructure was initialized. func SetGrpcLoggerV2WithVerbosity(settable grpc_logsettable.SettableLoggerV2, logger *zap.Logger, verbosity int) { zgl := &zapGrpcLoggerV2{ logger: logger.With(SystemField, zap.Bool("grpc_log", true)), verbosity: verbosity, } settable.Set(zgl) } type zapGrpcLoggerV2 struct { logger *zap.Logger verbosity int } func (l *zapGrpcLoggerV2) Info(args ...interface{}) { l.logger.Info(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Infoln(args ...interface{}) { l.logger.Info(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Infof(format string, args ...interface{}) { l.logger.Info(fmt.Sprintf(format, args...)) } func (l *zapGrpcLoggerV2) Warning(args ...interface{}) { l.logger.Warn(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Warningln(args ...interface{}) { l.logger.Warn(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Warningf(format string, args ...interface{}) { l.logger.Warn(fmt.Sprintf(format, args...)) } func (l *zapGrpcLoggerV2) Error(args ...interface{}) { l.logger.Error(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Errorln(args ...interface{}) { l.logger.Error(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Errorf(format string, args ...interface{}) { l.logger.Error(fmt.Sprintf(format, args...)) } func (l *zapGrpcLoggerV2) Fatal(args ...interface{}) { l.logger.Fatal(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Fatalln(args ...interface{}) { l.logger.Fatal(fmt.Sprint(args...)) } func (l *zapGrpcLoggerV2) Fatalf(format string, args ...interface{}) { l.logger.Fatal(fmt.Sprintf(format, args...)) } func (l *zapGrpcLoggerV2) V(level int) bool { // Check whether the verbosity of the current log ('level') is within the specified threshold ('l.verbosity'). // As in https://github.com/grpc/grpc-go/blob/41e044e1c82fcf6a5801d6cbd7ecf952505eecb1/grpclog/loggerv2.go#L199-L201. return level <= l.verbosity }