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