github.com/lzy4123/fabric@v2.1.1+incompatible/common/grpcmetrics/interceptor.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package grpcmetrics 8 9 import ( 10 "context" 11 "strings" 12 "time" 13 14 "github.com/hyperledger/fabric/common/metrics" 15 "google.golang.org/grpc" 16 "google.golang.org/grpc/status" 17 ) 18 19 type UnaryMetrics struct { 20 RequestDuration metrics.Histogram 21 RequestsReceived metrics.Counter 22 RequestsCompleted metrics.Counter 23 } 24 25 func UnaryServerInterceptor(um *UnaryMetrics) grpc.UnaryServerInterceptor { 26 return func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) { 27 service, method := serviceMethod(info.FullMethod) 28 um.RequestsReceived.With("service", service, "method", method).Add(1) 29 30 startTime := time.Now() 31 resp, err := handler(ctx, req) 32 st, _ := status.FromError(err) 33 duration := time.Since(startTime) 34 35 um.RequestDuration.With( 36 "service", service, "method", method, "code", st.Code().String(), 37 ).Observe(duration.Seconds()) 38 um.RequestsCompleted.With("service", service, "method", method, "code", st.Code().String()).Add(1) 39 40 return resp, err 41 } 42 } 43 44 type StreamMetrics struct { 45 RequestDuration metrics.Histogram 46 RequestsReceived metrics.Counter 47 RequestsCompleted metrics.Counter 48 MessagesSent metrics.Counter 49 MessagesReceived metrics.Counter 50 } 51 52 func StreamServerInterceptor(sm *StreamMetrics) grpc.StreamServerInterceptor { 53 return func(svc interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error { 54 sm := sm 55 service, method := serviceMethod(info.FullMethod) 56 sm.RequestsReceived.With("service", service, "method", method).Add(1) 57 58 wrappedStream := &serverStream{ 59 ServerStream: stream, 60 messagesSent: sm.MessagesSent.With("service", service, "method", method), 61 messagesReceived: sm.MessagesReceived.With("service", service, "method", method), 62 } 63 64 startTime := time.Now() 65 err := handler(svc, wrappedStream) 66 st, _ := status.FromError(err) 67 duration := time.Since(startTime) 68 69 sm.RequestDuration.With( 70 "service", service, "method", method, "code", st.Code().String(), 71 ).Observe(duration.Seconds()) 72 sm.RequestsCompleted.With("service", service, "method", method, "code", st.Code().String()).Add(1) 73 74 return err 75 } 76 } 77 78 func serviceMethod(fullMethod string) (service, method string) { 79 normalizedMethod := strings.Replace(fullMethod, ".", "_", -1) 80 parts := strings.SplitN(normalizedMethod, "/", -1) 81 if len(parts) != 3 { 82 return "unknown", "unknown" 83 } 84 return parts[1], parts[2] 85 } 86 87 type serverStream struct { 88 grpc.ServerStream 89 messagesSent metrics.Counter 90 messagesReceived metrics.Counter 91 } 92 93 func (ss *serverStream) SendMsg(msg interface{}) error { 94 ss.messagesSent.Add(1) 95 return ss.ServerStream.SendMsg(msg) 96 } 97 98 func (ss *serverStream) RecvMsg(msg interface{}) error { 99 err := ss.ServerStream.RecvMsg(msg) 100 if err == nil { 101 ss.messagesReceived.Add(1) 102 } 103 return err 104 }