1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
// Copyright (c) The go-grpc-middleware Authors.
// Licensed under the Apache License 2.0.
package prometheus
import (
"io"
"testing"
"github.com/grpc-ecosystem/go-grpc-middleware/v2/testing/testpb"
"github.com/stretchr/testify/require"
"github.com/stretchr/testify/suite"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
func TestClientInterceptorSuite(t *testing.T) {
c := NewClientMetrics(WithClientHandlingTimeHistogram())
suite.Run(t, &ClientInterceptorTestSuite{
InterceptorTestSuite: &testpb.InterceptorTestSuite{
TestService: &testpb.TestPingService{},
ClientOpts: []grpc.DialOption{
grpc.WithUnaryInterceptor(c.UnaryClientInterceptor()),
grpc.WithStreamInterceptor(c.StreamClientInterceptor()),
},
},
clientMetrics: c,
})
}
type ClientInterceptorTestSuite struct {
*testpb.InterceptorTestSuite
clientMetrics *ClientMetrics
}
func (s *ClientInterceptorTestSuite) SetupTest() {
s.clientMetrics.clientStartedCounter.Reset()
s.clientMetrics.clientHandledCounter.Reset()
s.clientMetrics.clientHandledHistogram.Reset()
s.clientMetrics.clientStreamMsgReceived.Reset()
s.clientMetrics.clientStreamMsgSent.Reset()
}
func (s *ClientInterceptorTestSuite) TestUnaryIncrementsMetrics() {
_, err := s.Client.PingEmpty(s.SimpleCtx(), &testpb.PingEmptyRequest{})
require.NoError(s.T(), err)
requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("unary", testpb.TestServiceFullName, "PingEmpty"))
requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("unary", testpb.TestServiceFullName, "PingEmpty", "OK"))
requireValueHistCount(s.T(), 1, s.clientMetrics.clientHandledHistogram.WithLabelValues("unary", testpb.TestServiceFullName, "PingEmpty"))
_, err = s.Client.PingError(s.SimpleCtx(), &testpb.PingErrorRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)})
require.Error(s.T(), err)
requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("unary", testpb.TestServiceFullName, "PingError"))
requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("unary", testpb.TestServiceFullName, "PingError", "FailedPrecondition"))
requireValueHistCount(s.T(), 1, s.clientMetrics.clientHandledHistogram.WithLabelValues("unary", testpb.TestServiceFullName, "PingError"))
}
func (s *ClientInterceptorTestSuite) TestStartedStreamingIncrementsStarted() {
_, err := s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{})
require.NoError(s.T(), err)
requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
_, err = s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)})
require.NoError(s.T(), err, "PingList must not fail immediately")
requireValue(s.T(), 2, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
}
func (s *ClientInterceptorTestSuite) TestStreamingIncrementsMetrics() {
ss, err := s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{})
require.NoError(s.T(), err)
// Do a read, just for kicks.
count := 0
for {
_, err = ss.Recv()
if err == io.EOF {
break
}
require.NoError(s.T(), err, "reading pingList shouldn't fail")
count++
}
require.EqualValues(s.T(), testpb.ListResponseCount, count, "Number of received msg on the wire must match")
requireValue(s.T(), 1, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList", "OK"))
requireValue(s.T(), testpb.ListResponseCount+1 /* + EOF */, s.clientMetrics.clientStreamMsgReceived.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
requireValue(s.T(), 1, s.clientMetrics.clientStreamMsgSent.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
requireValueHistCount(s.T(), 1, s.clientMetrics.clientHandledHistogram.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
ss, err = s.Client.PingList(s.SimpleCtx(), &testpb.PingListRequest{ErrorCodeReturned: uint32(codes.FailedPrecondition)})
require.NoError(s.T(), err, "PingList must not fail immediately")
// Do a read, just to progate errors.
_, err = ss.Recv()
st, _ := status.FromError(err)
require.Equal(s.T(), codes.FailedPrecondition, st.Code(), "Recv must return FailedPrecondition, otherwise the test is wrong")
requireValue(s.T(), 2, s.clientMetrics.clientStartedCounter.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
requireValue(s.T(), 1, s.clientMetrics.clientHandledCounter.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList", "FailedPrecondition"))
requireValueHistCount(s.T(), 2, s.clientMetrics.clientHandledHistogram.WithLabelValues("server_stream", testpb.TestServiceFullName, "PingList"))
}
func (s *ClientInterceptorTestSuite) TestWithSubsystem() {
counterOpts := []CounterOption{
WithSubsystem("subsystem1"),
}
histOpts := []HistogramOption{
WithHistogramSubsystem("subsystem1"),
}
clientCounterOpts := WithClientCounterOptions(counterOpts...)
clientMetrics := NewClientMetrics(clientCounterOpts, WithClientHandlingTimeHistogram(histOpts...))
requireSubsystemName(s.T(), "subsystem1", clientMetrics.clientStartedCounter.WithLabelValues("unary", testpb.TestServiceFullName, "dummy"))
requireHistSubsystemName(s.T(), "subsystem1", clientMetrics.clientHandledHistogram.WithLabelValues("unary", testpb.TestServiceFullName, "dummy"))
}
|