github.com/defanghe/fabric@v2.1.1+incompatible/common/grpcmetrics/interceptor_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package grpcmetrics_test
     8  
     9  import (
    10  	"context"
    11  	"errors"
    12  	"io"
    13  	"net"
    14  
    15  	"github.com/hyperledger/fabric/common/grpcmetrics"
    16  	"github.com/hyperledger/fabric/common/grpcmetrics/fakes"
    17  	"github.com/hyperledger/fabric/common/grpcmetrics/testpb"
    18  	"github.com/hyperledger/fabric/common/metrics/metricsfakes"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  	"google.golang.org/grpc"
    22  	"google.golang.org/grpc/codes"
    23  	"google.golang.org/grpc/status"
    24  )
    25  
    26  var _ = Describe("Interceptor", func() {
    27  	var (
    28  		fakeEchoService   *fakes.EchoServiceServer
    29  		echoServiceClient testpb.EchoServiceClient
    30  
    31  		fakeRequestDuration   *metricsfakes.Histogram
    32  		fakeRequestsReceived  *metricsfakes.Counter
    33  		fakeRequestsCompleted *metricsfakes.Counter
    34  		fakeMessagesSent      *metricsfakes.Counter
    35  		fakeMessagesReceived  *metricsfakes.Counter
    36  
    37  		unaryMetrics  *grpcmetrics.UnaryMetrics
    38  		streamMetrics *grpcmetrics.StreamMetrics
    39  
    40  		listener        net.Listener
    41  		serveCompleteCh chan error
    42  		server          *grpc.Server
    43  	)
    44  
    45  	BeforeEach(func() {
    46  		var err error
    47  		listener, err = net.Listen("tcp", "127.0.0.1:0")
    48  		Expect(err).NotTo(HaveOccurred())
    49  
    50  		fakeEchoService = &fakes.EchoServiceServer{}
    51  		fakeEchoService.EchoStub = func(ctx context.Context, msg *testpb.Message) (*testpb.Message, error) {
    52  			msg.Sequence++
    53  			return msg, nil
    54  		}
    55  		fakeEchoService.EchoStreamStub = func(stream testpb.EchoService_EchoStreamServer) error {
    56  			for {
    57  				msg, err := stream.Recv()
    58  				if err == io.EOF {
    59  					return nil
    60  				}
    61  				if err != nil {
    62  					return err
    63  				}
    64  
    65  				msg.Sequence++
    66  				err = stream.Send(msg)
    67  				if err != nil {
    68  					return err
    69  				}
    70  			}
    71  		}
    72  
    73  		fakeRequestDuration = &metricsfakes.Histogram{}
    74  		fakeRequestDuration.WithReturns(fakeRequestDuration)
    75  		fakeRequestsReceived = &metricsfakes.Counter{}
    76  		fakeRequestsReceived.WithReturns(fakeRequestsReceived)
    77  		fakeRequestsCompleted = &metricsfakes.Counter{}
    78  		fakeRequestsCompleted.WithReturns(fakeRequestsCompleted)
    79  		fakeMessagesSent = &metricsfakes.Counter{}
    80  		fakeMessagesSent.WithReturns(fakeMessagesSent)
    81  		fakeMessagesReceived = &metricsfakes.Counter{}
    82  		fakeMessagesReceived.WithReturns(fakeMessagesReceived)
    83  
    84  		unaryMetrics = &grpcmetrics.UnaryMetrics{
    85  			RequestDuration:   fakeRequestDuration,
    86  			RequestsReceived:  fakeRequestsReceived,
    87  			RequestsCompleted: fakeRequestsCompleted,
    88  		}
    89  
    90  		streamMetrics = &grpcmetrics.StreamMetrics{
    91  			RequestDuration:   fakeRequestDuration,
    92  			RequestsReceived:  fakeRequestsReceived,
    93  			RequestsCompleted: fakeRequestsCompleted,
    94  			MessagesSent:      fakeMessagesSent,
    95  			MessagesReceived:  fakeMessagesReceived,
    96  		}
    97  
    98  		server = grpc.NewServer(
    99  			grpc.StreamInterceptor(grpcmetrics.StreamServerInterceptor(streamMetrics)),
   100  			grpc.UnaryInterceptor(grpcmetrics.UnaryServerInterceptor(unaryMetrics)),
   101  		)
   102  
   103  		testpb.RegisterEchoServiceServer(server, fakeEchoService)
   104  		serveCompleteCh = make(chan error, 1)
   105  		go func() { serveCompleteCh <- server.Serve(listener) }()
   106  
   107  		cc, err := grpc.Dial(listener.Addr().String(), grpc.WithInsecure(), grpc.WithBlock())
   108  		Expect(err).NotTo(HaveOccurred())
   109  		echoServiceClient = testpb.NewEchoServiceClient(cc)
   110  	})
   111  
   112  	AfterEach(func() {
   113  		err := listener.Close()
   114  		Expect(err).NotTo(HaveOccurred())
   115  		Eventually(serveCompleteCh).Should(Receive())
   116  	})
   117  
   118  	Describe("Unary Metrics", func() {
   119  		It("records request duration", func() {
   120  			resp, err := echoServiceClient.Echo(context.Background(), &testpb.Message{Message: "yo"})
   121  			Expect(err).NotTo(HaveOccurred())
   122  			Expect(resp).To(Equal(&testpb.Message{Message: "yo", Sequence: 1}))
   123  
   124  			Expect(fakeRequestDuration.WithCallCount()).To(Equal(1))
   125  			labelValues := fakeRequestDuration.WithArgsForCall(0)
   126  			Expect(labelValues).To(Equal([]string{
   127  				"service", "testpb_EchoService",
   128  				"method", "Echo",
   129  				"code", "OK",
   130  			}))
   131  			Expect(fakeRequestDuration.ObserveCallCount()).To(Equal(1))
   132  			Expect(fakeRequestDuration.ObserveArgsForCall(0)).NotTo(BeZero())
   133  			Expect(fakeRequestDuration.ObserveArgsForCall(0)).To(BeNumerically("<", 1.0))
   134  		})
   135  
   136  		It("records requests received before requests completed", func() {
   137  			fakeRequestsReceived.AddStub = func(delta float64) {
   138  				defer GinkgoRecover()
   139  				Expect(fakeRequestsCompleted.AddCallCount()).To(Equal(0))
   140  			}
   141  
   142  			resp, err := echoServiceClient.Echo(context.Background(), &testpb.Message{Message: "yo"})
   143  			Expect(err).NotTo(HaveOccurred())
   144  			Expect(resp).To(Equal(&testpb.Message{Message: "yo", Sequence: 1}))
   145  
   146  			Expect(fakeRequestsReceived.WithCallCount()).To(Equal(1))
   147  			labelValues := fakeRequestsReceived.WithArgsForCall(0)
   148  			Expect(labelValues).To(Equal([]string{
   149  				"service", "testpb_EchoService",
   150  				"method", "Echo",
   151  			}))
   152  			Expect(fakeRequestsReceived.AddCallCount()).To(Equal(1))
   153  			Expect(fakeRequestsReceived.AddArgsForCall(0)).To(BeNumerically("~", 1.0))
   154  		})
   155  
   156  		It("records requests completed after requests received", func() {
   157  			fakeRequestsCompleted.AddStub = func(delta float64) {
   158  				defer GinkgoRecover()
   159  				Expect(fakeRequestsReceived.AddCallCount()).To(Equal(1))
   160  			}
   161  
   162  			resp, err := echoServiceClient.Echo(context.Background(), &testpb.Message{Message: "yo"})
   163  			Expect(err).NotTo(HaveOccurred())
   164  			Expect(resp).To(Equal(&testpb.Message{Message: "yo", Sequence: 1}))
   165  
   166  			Expect(fakeRequestsCompleted.WithCallCount()).To(Equal(1))
   167  			labelValues := fakeRequestsCompleted.WithArgsForCall(0)
   168  			Expect(labelValues).To(Equal([]string{
   169  				"service", "testpb_EchoService",
   170  				"method", "Echo",
   171  				"code", "OK",
   172  			}))
   173  			Expect(fakeRequestsCompleted.AddCallCount()).To(Equal(1))
   174  			Expect(fakeRequestsCompleted.AddArgsForCall(0)).To(BeNumerically("~", 1.0))
   175  		})
   176  	})
   177  
   178  	Describe("Stream Metrics", func() {
   179  		It("records request duration", func() {
   180  			streamClient, err := echoServiceClient.EchoStream(context.Background())
   181  			Expect(err).NotTo(HaveOccurred())
   182  			streamMessages(streamClient)
   183  
   184  			Expect(fakeRequestDuration.WithCallCount()).To(Equal(1))
   185  			labelValues := fakeRequestDuration.WithArgsForCall(0)
   186  			Expect(labelValues).To(Equal([]string{
   187  				"service", "testpb_EchoService",
   188  				"method", "EchoStream",
   189  				"code", "OK",
   190  			}))
   191  			Expect(fakeRequestDuration.ObserveCallCount()).To(Equal(1))
   192  			Expect(fakeRequestDuration.ObserveArgsForCall(0)).NotTo(BeZero())
   193  			Expect(fakeRequestDuration.ObserveArgsForCall(0)).To(BeNumerically("<", 1.0))
   194  		})
   195  
   196  		It("records requests received before requests completed", func() {
   197  			fakeRequestsReceived.AddStub = func(delta float64) {
   198  				defer GinkgoRecover()
   199  				Expect(fakeRequestsCompleted.AddCallCount()).To(Equal(0))
   200  			}
   201  
   202  			streamClient, err := echoServiceClient.EchoStream(context.Background())
   203  			Expect(err).NotTo(HaveOccurred())
   204  			streamMessages(streamClient)
   205  
   206  			Expect(fakeRequestsReceived.WithCallCount()).To(Equal(1))
   207  			labelValues := fakeRequestDuration.WithArgsForCall(0)
   208  			Expect(labelValues).To(Equal([]string{
   209  				"service", "testpb_EchoService",
   210  				"method", "EchoStream",
   211  				"code", "OK",
   212  			}))
   213  			Expect(fakeRequestsReceived.AddCallCount()).To(Equal(1))
   214  			Expect(fakeRequestsReceived.AddArgsForCall(0)).To(BeNumerically("~", 1.0))
   215  		})
   216  
   217  		It("records requests completed after requests received", func() {
   218  			fakeRequestsCompleted.AddStub = func(delta float64) {
   219  				defer GinkgoRecover()
   220  				Expect(fakeRequestsReceived.AddCallCount()).To(Equal(1))
   221  			}
   222  
   223  			streamClient, err := echoServiceClient.EchoStream(context.Background())
   224  			Expect(err).NotTo(HaveOccurred())
   225  			streamMessages(streamClient)
   226  
   227  			Expect(fakeRequestsReceived.WithCallCount()).To(Equal(1))
   228  			labelValues := fakeRequestDuration.WithArgsForCall(0)
   229  			Expect(labelValues).To(Equal([]string{
   230  				"service", "testpb_EchoService",
   231  				"method", "EchoStream",
   232  				"code", "OK",
   233  			}))
   234  			Expect(fakeRequestsReceived.AddCallCount()).To(Equal(1))
   235  			Expect(fakeRequestsReceived.AddArgsForCall(0)).To(BeNumerically("~", 1.0))
   236  		})
   237  
   238  		It("records messages sent", func() {
   239  			streamClient, err := echoServiceClient.EchoStream(context.Background())
   240  			Expect(err).NotTo(HaveOccurred())
   241  			streamMessages(streamClient)
   242  
   243  			Expect(fakeMessagesSent.WithCallCount()).To(Equal(1))
   244  			labelValues := fakeMessagesSent.WithArgsForCall(0)
   245  			Expect(labelValues).To(Equal([]string{
   246  				"service", "testpb_EchoService",
   247  				"method", "EchoStream",
   248  			}))
   249  
   250  			Expect(fakeMessagesSent.AddCallCount()).To(Equal(2))
   251  			for i := 0; i < fakeMessagesSent.AddCallCount(); i++ {
   252  				Expect(fakeMessagesSent.AddArgsForCall(0)).To(BeNumerically("~", 1.0))
   253  			}
   254  		})
   255  
   256  		It("records messages received", func() {
   257  			streamClient, err := echoServiceClient.EchoStream(context.Background())
   258  			Expect(err).NotTo(HaveOccurred())
   259  			streamMessages(streamClient)
   260  
   261  			Expect(fakeMessagesReceived.WithCallCount()).To(Equal(1))
   262  			labelValues := fakeMessagesReceived.WithArgsForCall(0)
   263  			Expect(labelValues).To(Equal([]string{
   264  				"service", "testpb_EchoService",
   265  				"method", "EchoStream",
   266  			}))
   267  
   268  			Expect(fakeMessagesReceived.AddCallCount()).To(Equal(2))
   269  			for i := 0; i < fakeMessagesReceived.AddCallCount(); i++ {
   270  				Expect(fakeMessagesReceived.AddArgsForCall(0)).To(BeNumerically("~", 1.0))
   271  			}
   272  		})
   273  
   274  		Context("when stream recv returns an error", func() {
   275  			var errCh chan error
   276  
   277  			BeforeEach(func() {
   278  				errCh = make(chan error)
   279  				fakeEchoService.EchoStreamStub = func(svs testpb.EchoService_EchoStreamServer) error {
   280  					return <-errCh
   281  				}
   282  			})
   283  
   284  			It("does not increment the update count", func() {
   285  				streamClient, err := echoServiceClient.EchoStream(context.Background())
   286  				Expect(err).NotTo(HaveOccurred())
   287  
   288  				err = streamClient.Send(&testpb.Message{Message: "hello"})
   289  				Expect(err).NotTo(HaveOccurred())
   290  
   291  				errCh <- errors.New("oh bother")
   292  				_, err = streamClient.Recv()
   293  				Expect(err).To(MatchError(status.Errorf(codes.Unknown, "oh bother")))
   294  
   295  				err = streamClient.CloseSend()
   296  				Expect(err).NotTo(HaveOccurred())
   297  
   298  				_, err = streamClient.Recv()
   299  				Expect(err).To(MatchError(status.Errorf(codes.Unknown, "oh bother")))
   300  
   301  				Expect(fakeMessagesReceived.AddCallCount()).To(Equal(0))
   302  			})
   303  		})
   304  	})
   305  })
   306  
   307  func streamMessages(streamClient testpb.EchoService_EchoStreamClient) {
   308  	err := streamClient.Send(&testpb.Message{Message: "hello"})
   309  	Expect(err).NotTo(HaveOccurred())
   310  	err = streamClient.Send(&testpb.Message{Message: "hello", Sequence: 2})
   311  	Expect(err).NotTo(HaveOccurred())
   312  
   313  	msg, err := streamClient.Recv()
   314  	Expect(err).NotTo(HaveOccurred())
   315  	Expect(msg).To(Equal(&testpb.Message{Message: "hello", Sequence: 1}))
   316  	msg, err = streamClient.Recv()
   317  	Expect(err).NotTo(HaveOccurred())
   318  	Expect(msg).To(Equal(&testpb.Message{Message: "hello", Sequence: 3}))
   319  
   320  	err = streamClient.CloseSend()
   321  	Expect(err).NotTo(HaveOccurred())
   322  
   323  	msg, err = streamClient.Recv()
   324  	Expect(err).To(Equal(io.EOF))
   325  	Expect(msg).To(BeNil())
   326  }