...

Source file src/github.com/grpc-ecosystem/go-grpc-middleware/logging/kit/client_interceptors_test.go

Documentation: github.com/grpc-ecosystem/go-grpc-middleware/logging/kit

     1  package kit_test
     2  
     3  import (
     4  	"io"
     5  	"runtime"
     6  	"strings"
     7  	"testing"
     8  
     9  	"github.com/go-kit/log"
    10  	"github.com/go-kit/log/level"
    11  	grpc_kit "github.com/grpc-ecosystem/go-grpc-middleware/logging/kit"
    12  	pb_testproto "github.com/grpc-ecosystem/go-grpc-middleware/testing/testproto"
    13  	"github.com/stretchr/testify/assert"
    14  	"github.com/stretchr/testify/require"
    15  	"github.com/stretchr/testify/suite"
    16  	"google.golang.org/grpc"
    17  	"google.golang.org/grpc/codes"
    18  )
    19  
    20  func customClientCodeToLevel(c codes.Code, logger log.Logger) log.Logger {
    21  	if c == codes.Unauthenticated {
    22  		// Make this a special case for tests, and an error.
    23  		return level.Error(logger)
    24  	}
    25  	return grpc_kit.DefaultClientCodeToLevel(c, logger)
    26  }
    27  
    28  func TestKitClientSuite(t *testing.T) {
    29  	opts := []grpc_kit.Option{
    30  		grpc_kit.WithLevels(customClientCodeToLevel),
    31  	}
    32  	b := newKitBaseSuite(t)
    33  	b.logger = level.NewFilter(b.logger, level.AllowDebug()) // a lot of our stuff is on debug level by default
    34  	b.InterceptorTestSuite.ClientOpts = []grpc.DialOption{
    35  		grpc.WithUnaryInterceptor(grpc_kit.UnaryClientInterceptor(b.logger, opts...)),
    36  		grpc.WithStreamInterceptor(grpc_kit.StreamClientInterceptor(b.logger, opts...)),
    37  	}
    38  	suite.Run(t, &kitClientSuite{b})
    39  }
    40  
    41  type kitClientSuite struct {
    42  	*kitBaseSuite
    43  }
    44  
    45  func (s *kitClientSuite) TestPing() {
    46  	_, err := s.Client.Ping(s.SimpleCtx(), goodPing)
    47  	assert.NoError(s.T(), err, "there must be not be an on a successful call")
    48  
    49  	msgs := s.getOutputJSONs()
    50  	require.Len(s.T(), msgs, 1, "one log statement should be logged")
    51  
    52  	assert.Equal(s.T(), msgs[0]["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain the correct service name")
    53  	assert.Equal(s.T(), msgs[0]["grpc.method"], "Ping", "all lines must contain the correct method name")
    54  	assert.Equal(s.T(), msgs[0]["msg"], "finished client unary call", "handler's message must contain the correct message")
    55  	assert.Equal(s.T(), msgs[0]["span.kind"], "client", "all lines must contain the kind of call (client)")
    56  	assert.Equal(s.T(), msgs[0]["level"], "debug", "OK codes must be logged on debug level.")
    57  
    58  	assert.Contains(s.T(), msgs[0], "grpc.time_ms", "interceptor log statement should contain execution time (duration in ms)")
    59  }
    60  
    61  func (s *kitClientSuite) TestPingList() {
    62  	stream, err := s.Client.PingList(s.SimpleCtx(), goodPing)
    63  	require.NoError(s.T(), err, "should not fail on establishing the stream")
    64  	for {
    65  		_, err := stream.Recv()
    66  		if err == io.EOF {
    67  			break
    68  		}
    69  		require.NoError(s.T(), err, "reading stream should not fail")
    70  	}
    71  
    72  	msgs := s.getOutputJSONs()
    73  	require.Len(s.T(), msgs, 1, "one log statement should be logged")
    74  
    75  	assert.Equal(s.T(), msgs[0]["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain the correct service name")
    76  	assert.Equal(s.T(), msgs[0]["grpc.method"], "PingList", "all lines must contain the correct method name")
    77  	assert.Equal(s.T(), msgs[0]["msg"], "finished client streaming call", "handler's message must contain the correct message")
    78  	assert.Equal(s.T(), msgs[0]["span.kind"], "client", "all lines must contain the kind of call (client)")
    79  	assert.Equal(s.T(), msgs[0]["level"], "debug", "OK codes must be logged on debug level.")
    80  	assert.Contains(s.T(), msgs[0], "grpc.time_ms", "interceptor log statement should contain execution time (duration in ms)")
    81  }
    82  
    83  func (s *kitClientSuite) TestPingError_WithCustomLevels() {
    84  	for _, tcase := range []struct {
    85  		code  codes.Code
    86  		level level.Value
    87  		msg   string
    88  	}{
    89  		{
    90  			code:  codes.Internal,
    91  			level: level.WarnValue(),
    92  			msg:   "Internal must remap to WarnLevel in DefaultClientCodeToLevel",
    93  		},
    94  		{
    95  			code:  codes.NotFound,
    96  			level: level.DebugValue(),
    97  			msg:   "NotFound must remap to DebugLevel in DefaultClientCodeToLevel",
    98  		},
    99  		{
   100  			code:  codes.FailedPrecondition,
   101  			level: level.DebugValue(),
   102  			msg:   "FailedPrecondition must remap to DebugLevel in DefaultClientCodeToLevel",
   103  		},
   104  		{
   105  			code:  codes.Unauthenticated,
   106  			level: level.ErrorValue(),
   107  			msg:   "Unauthenticated is overwritten to ErrorLevel with customClientCodeToLevel override, which probably didn't work",
   108  		},
   109  	} {
   110  		s.SetupTest()
   111  		_, err := s.Client.PingError(
   112  			s.SimpleCtx(),
   113  			&pb_testproto.PingRequest{Value: "something", ErrorCodeReturned: uint32(tcase.code)})
   114  
   115  		assert.Error(s.T(), err, "each call here must return an error")
   116  
   117  		msgs := s.getOutputJSONs()
   118  		require.Len(s.T(), msgs, 1, "only a single log message is printed")
   119  
   120  		assert.Equal(s.T(), msgs[0]["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain the correct service name")
   121  		assert.Equal(s.T(), msgs[0]["grpc.method"], "PingError", "all lines must contain the correct method name")
   122  		assert.Equal(s.T(), msgs[0]["grpc.code"], tcase.code.String(), "all lines must contain a grpc code")
   123  		assert.Equal(s.T(), msgs[0]["level"], tcase.level.String(), tcase.msg)
   124  	}
   125  }
   126  
   127  func TestKitClientOverrideSuite(t *testing.T) {
   128  	if strings.HasPrefix(runtime.Version(), "go1.7") {
   129  		t.Skip("Skipping due to json.RawMessage incompatibility with go1.7")
   130  		return
   131  	}
   132  	opts := []grpc_kit.Option{
   133  		grpc_kit.WithDurationField(grpc_kit.DurationToDurationField),
   134  	}
   135  	b := newKitBaseSuite(t)
   136  	b.logger = level.NewFilter(b.logger, level.AllowDebug()) // a lot of our stuff is on debug level by default
   137  	b.InterceptorTestSuite.ClientOpts = []grpc.DialOption{
   138  		grpc.WithUnaryInterceptor(grpc_kit.UnaryClientInterceptor(b.logger, opts...)),
   139  		grpc.WithStreamInterceptor(grpc_kit.StreamClientInterceptor(b.logger, opts...)),
   140  	}
   141  	suite.Run(t, &kitClientOverrideSuite{b})
   142  }
   143  
   144  type kitClientOverrideSuite struct {
   145  	*kitBaseSuite
   146  }
   147  
   148  func (s *kitClientOverrideSuite) TestPing_HasOverrides() {
   149  	_, err := s.Client.Ping(s.SimpleCtx(), goodPing)
   150  	assert.NoError(s.T(), err, "there must be not be an on a successful call")
   151  
   152  	msgs := s.getOutputJSONs()
   153  	require.Len(s.T(), msgs, 1, "one log statement should be logged")
   154  	assert.Equal(s.T(), msgs[0]["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain the correct service name")
   155  	assert.Equal(s.T(), msgs[0]["grpc.method"], "Ping", "all lines must contain the correct method name")
   156  	assert.Equal(s.T(), msgs[0]["msg"], "finished client unary call", "handler's message must contain the correct message")
   157  
   158  	assert.NotContains(s.T(), msgs[0], "grpc.time_ms", "message must not contain default duration")
   159  	assert.Contains(s.T(), msgs[0], "grpc.duration", "message must contain overridden duration")
   160  }
   161  
   162  func (s *kitClientOverrideSuite) TestPingList_HasOverrides() {
   163  	stream, err := s.Client.PingList(s.SimpleCtx(), goodPing)
   164  	require.NoError(s.T(), err, "should not fail on establishing the stream")
   165  	for {
   166  		_, err := stream.Recv()
   167  		if err == io.EOF {
   168  			break
   169  		}
   170  		require.NoError(s.T(), err, "reading stream should not fail")
   171  	}
   172  
   173  	msgs := s.getOutputJSONs()
   174  	require.Len(s.T(), msgs, 1, "one log statement should be logged")
   175  
   176  	assert.Equal(s.T(), msgs[0]["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain the correct service name")
   177  	assert.Equal(s.T(), msgs[0]["grpc.method"], "PingList", "all lines must contain the correct method name")
   178  	assert.Equal(s.T(), msgs[0]["msg"], "finished client streaming call", "log message must be correct")
   179  	assert.Equal(s.T(), msgs[0]["span.kind"], "client", "all lines must contain the kind of call (client)")
   180  	assert.Equal(s.T(), msgs[0]["level"], "debug", "OK codes must be logged on debug level.")
   181  
   182  	assert.NotContains(s.T(), msgs[0], "grpc.time_ms", "message must not contain default duration")
   183  	assert.Contains(s.T(), msgs[0], "grpc.duration", "message must contain overridden duration")
   184  }
   185  

View as plain text