...

Source file src/github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/server_interceptors.go

Documentation: github.com/grpc-ecosystem/go-grpc-middleware/logging/zap

     1  package grpc_zap
     2  
     3  import (
     4  	"context"
     5  	"path"
     6  	"time"
     7  
     8  	grpc_middleware "github.com/grpc-ecosystem/go-grpc-middleware"
     9  	"github.com/grpc-ecosystem/go-grpc-middleware/logging/zap/ctxzap"
    10  	"go.uber.org/zap"
    11  	"go.uber.org/zap/zapcore"
    12  	"google.golang.org/grpc"
    13  )
    14  
    15  var (
    16  	// SystemField is used in every log statement made through grpc_zap. Can be overwritten before any initialization code.
    17  	SystemField = zap.String("system", "grpc")
    18  
    19  	// ServerField is used in every server-side log statement made through grpc_zap.Can be overwritten before initialization.
    20  	ServerField = zap.String("span.kind", "server")
    21  )
    22  
    23  // UnaryServerInterceptor returns a new unary server interceptors that adds zap.Logger to the context.
    24  func UnaryServerInterceptor(logger *zap.Logger, opts ...Option) grpc.UnaryServerInterceptor {
    25  	o := evaluateServerOpt(opts)
    26  	return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {
    27  		startTime := time.Now()
    28  
    29  		newCtx := newLoggerForCall(ctx, logger, info.FullMethod, startTime, o.timestampFormat)
    30  
    31  		resp, err := handler(newCtx, req)
    32  		if !o.shouldLog(info.FullMethod, err) {
    33  			return resp, err
    34  		}
    35  		code := o.codeFunc(err)
    36  		level := o.levelFunc(code)
    37  		duration := o.durationFunc(time.Since(startTime))
    38  
    39  		o.messageFunc(newCtx, "finished unary call with code "+code.String(), level, code, err, duration)
    40  		return resp, err
    41  	}
    42  }
    43  
    44  // StreamServerInterceptor returns a new streaming server interceptor that adds zap.Logger to the context.
    45  func StreamServerInterceptor(logger *zap.Logger, opts ...Option) grpc.StreamServerInterceptor {
    46  	o := evaluateServerOpt(opts)
    47  	return func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {
    48  		startTime := time.Now()
    49  		newCtx := newLoggerForCall(stream.Context(), logger, info.FullMethod, startTime, o.timestampFormat)
    50  		wrapped := grpc_middleware.WrapServerStream(stream)
    51  		wrapped.WrappedContext = newCtx
    52  
    53  		err := handler(srv, wrapped)
    54  		if !o.shouldLog(info.FullMethod, err) {
    55  			return err
    56  		}
    57  		code := o.codeFunc(err)
    58  		level := o.levelFunc(code)
    59  		duration := o.durationFunc(time.Since(startTime))
    60  
    61  		o.messageFunc(newCtx, "finished streaming call with code "+code.String(), level, code, err, duration)
    62  		return err
    63  	}
    64  }
    65  
    66  func serverCallFields(fullMethodString string) []zapcore.Field {
    67  	service := path.Dir(fullMethodString)[1:]
    68  	method := path.Base(fullMethodString)
    69  	return []zapcore.Field{
    70  		SystemField,
    71  		ServerField,
    72  		zap.String("grpc.service", service),
    73  		zap.String("grpc.method", method),
    74  	}
    75  }
    76  
    77  func newLoggerForCall(ctx context.Context, logger *zap.Logger, fullMethodString string, start time.Time, timestampFormat string) context.Context {
    78  	var f []zapcore.Field
    79  	f = append(f, zap.String("grpc.start_time", start.Format(timestampFormat)))
    80  	if d, ok := ctx.Deadline(); ok {
    81  		f = append(f, zap.String("grpc.request.deadline", d.Format(timestampFormat)))
    82  	}
    83  	callLog := logger.With(append(f, serverCallFields(fullMethodString)...)...)
    84  	return ctxzap.ToContext(ctx, callLog)
    85  }
    86  

View as plain text