github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/go-grpc-middleware/logging/zap/client_interceptors_test.go (about)

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