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  }