go.temporal.io/server@v1.23.0/common/metrics/grpc_test.go (about) 1 // The MIT License 2 // 3 // Copyright (c) 2020 Temporal Technologies Inc. All rights reserved. 4 // 5 // Copyright (c) 2020 Uber Technologies, Inc. 6 // 7 // Permission is hereby granted, free of charge, to any person obtaining a copy 8 // of this software and associated documentation files (the "Software"), to deal 9 // in the Software without restriction, including without limitation the rights 10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 // copies of the Software, and to permit persons to whom the Software is 12 // furnished to do so, subject to the following conditions: 13 // 14 // The above copyright notice and this permission notice shall be included in 15 // all copies or substantial portions of the Software. 16 // 17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 23 // THE SOFTWARE. 24 25 package metrics 26 27 import ( 28 "context" 29 "testing" 30 31 "github.com/golang/mock/gomock" 32 "github.com/stretchr/testify/require" 33 "github.com/stretchr/testify/suite" 34 "google.golang.org/grpc" 35 "google.golang.org/grpc/metadata" 36 37 metricspb "go.temporal.io/server/api/metrics/v1" 38 "go.temporal.io/server/common/log" 39 ) 40 41 type ( 42 grpcSuite struct { 43 suite.Suite 44 *require.Assertions 45 controller *gomock.Controller 46 } 47 ) 48 49 func TestGrpcSuite(t *testing.T) { 50 s := new(grpcSuite) 51 suite.Run(t, s) 52 } 53 54 func (s *grpcSuite) SetupTest() { 55 s.Assertions = require.New(s.T()) 56 s.controller = gomock.NewController(s.T()) 57 } 58 59 func (s *grpcSuite) TearDownTest() {} 60 61 func (s *grpcSuite) TestMetadataMetricInjection() { 62 logger := log.NewMockLogger(s.controller) 63 ctx := context.Background() 64 ssts := newMockServerTransportStream() 65 ctx = grpc.NewContextWithServerTransportStream(ctx, ssts) 66 anyMetricName := "any_metric_name" 67 68 smcii := NewServerMetricsContextInjectorInterceptor() 69 s.NotNil(smcii) 70 res, err := smcii( 71 ctx, nil, nil, 72 func(ctx context.Context, req interface{}) (interface{}, error) { 73 res, err := NewServerMetricsTrailerPropagatorInterceptor(logger)( 74 ctx, req, nil, 75 func(ctx context.Context, req interface{}) (interface{}, error) { 76 cmtpi := NewClientMetricsTrailerPropagatorInterceptor(logger) 77 s.NotNil(cmtpi) 78 cmtpi( 79 ctx, "any_value", nil, nil, nil, 80 func( 81 ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, 82 opts ...grpc.CallOption, 83 ) error { 84 trailer := opts[0].(grpc.TrailerCallOption) 85 propagationContext := &metricspb.Baggage{CountersInt: make(map[string]int64)} 86 propagationContext.CountersInt[anyMetricName] = 1234 87 data, err := propagationContext.Marshal() 88 if err != nil { 89 s.Fail("failed to marshal values") 90 } 91 *trailer.TrailerAddr = metadata.MD{} 92 trailer.TrailerAddr.Append(metricsTrailerKey, string(data)) 93 return nil 94 }, 95 ) 96 return 10, nil 97 }, 98 ) 99 100 s.Nil(err) 101 s.Equal(len(ssts.trailers), 1) 102 propagationContextBlobs := ssts.trailers[0].Get(metricsTrailerKey) 103 s.NotNil(propagationContextBlobs) 104 s.Equal(1, len(propagationContextBlobs)) 105 baggage := &metricspb.Baggage{} 106 err = baggage.Unmarshal(([]byte)(propagationContextBlobs[0])) 107 s.Nil(err) 108 s.Equal(int64(1234), baggage.CountersInt[anyMetricName]) 109 return res, err 110 }, 111 ) 112 113 s.Nil(err) 114 s.Equal(10, res) 115 s.Assert() 116 } 117 118 func (s *grpcSuite) TestMetadataMetricInjection_NoMetricPresent() { 119 logger := log.NewMockLogger(s.controller) 120 ctx := context.Background() 121 ssts := newMockServerTransportStream() 122 ctx = grpc.NewContextWithServerTransportStream(ctx, ssts) 123 124 smcii := NewServerMetricsContextInjectorInterceptor() 125 s.NotNil(smcii) 126 res, err := smcii( 127 ctx, nil, nil, 128 func(ctx context.Context, req interface{}) (interface{}, error) { 129 res, err := NewServerMetricsTrailerPropagatorInterceptor(logger)( 130 ctx, req, nil, 131 func(ctx context.Context, req interface{}) (interface{}, error) { 132 cmtpi := NewClientMetricsTrailerPropagatorInterceptor(logger) 133 s.NotNil(cmtpi) 134 cmtpi( 135 ctx, "any_value", nil, nil, nil, 136 func( 137 ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, 138 opts ...grpc.CallOption, 139 ) error { 140 trailer := opts[0].(grpc.TrailerCallOption) 141 propagationContext := &metricspb.Baggage{} 142 data, err := propagationContext.Marshal() 143 if err != nil { 144 s.Fail("failed to marshal values") 145 } 146 trailer.TrailerAddr = &metadata.MD{} 147 trailer.TrailerAddr.Append(metricsTrailerKey, string(data)) 148 return nil 149 }, 150 ) 151 return 10, nil 152 }, 153 ) 154 155 s.Nil(err) 156 s.Equal(len(ssts.trailers), 1) 157 propagationContextBlobs := ssts.trailers[0].Get(metricsTrailerKey) 158 s.NotNil(propagationContextBlobs) 159 s.Equal(1, len(propagationContextBlobs)) 160 baggage := &metricspb.Baggage{} 161 err = baggage.Unmarshal(([]byte)(propagationContextBlobs[0])) 162 s.Nil(err) 163 s.Nil(baggage.CountersInt) 164 return res, err 165 }, 166 ) 167 168 s.Nil(err) 169 s.Equal(10, res) 170 s.Assert() 171 } 172 173 func (s *grpcSuite) TestContextCounterAdd() { 174 ctx := AddMetricsContext(context.Background()) 175 176 testCounterName := "test_counter" 177 ContextCounterAdd(ctx, testCounterName, 100) 178 ContextCounterAdd(ctx, testCounterName, 20) 179 ContextCounterAdd(ctx, testCounterName, 3) 180 181 value, ok := ContextCounterGet(ctx, testCounterName) 182 s.True(ok) 183 s.Equal(int64(123), value) 184 } 185 186 func (s *grpcSuite) TestContextCounterAddNoMetricsContext() { 187 testCounterName := "test_counter" 188 ContextCounterAdd(context.Background(), testCounterName, 3) 189 } 190 191 func newMockServerTransportStream() *mockServerTransportStream { 192 return &mockServerTransportStream{trailers: []*metadata.MD{}} 193 } 194 195 type mockServerTransportStream struct { 196 trailers []*metadata.MD 197 } 198 199 func (s *mockServerTransportStream) Method() string { 200 return "mockssts" 201 } 202 func (s *mockServerTransportStream) SetHeader(md metadata.MD) error { 203 return nil 204 } 205 func (s *mockServerTransportStream) SendHeader(md metadata.MD) error { 206 return nil 207 } 208 func (s *mockServerTransportStream) SetTrailer(md metadata.MD) error { 209 mdCopy := md.Copy() 210 s.trailers = append(s.trailers, &mdCopy) 211 return nil 212 }