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 }