github.com/hxx258456/ccgo@v0.0.5-0.20230213014102-48b35f46f66f/go-grpc-middleware/logging/zap/payload_interceptors_test.go (about) 1 package grpc_zap_test 2 3 import ( 4 "runtime" 5 "testing" 6 7 "strings" 8 9 "github.com/hxx258456/ccgo/grpc" 10 "github.com/stretchr/testify/suite" 11 12 "io" 13 14 grpc_middleware "github.com/hxx258456/ccgo/go-grpc-middleware" 15 grpc_ctxtags "github.com/hxx258456/ccgo/go-grpc-middleware/tags" 16 pb_testproto "github.com/hxx258456/ccgo/go-grpc-middleware/testing/testproto" 17 "github.com/hxx258456/ccgo/net/context" 18 "github.com/stretchr/testify/assert" 19 "github.com/stretchr/testify/require" 20 21 grpc_zap "github.com/hxx258456/ccgo/go-grpc-middleware/logging/zap" 22 "go.uber.org/zap" 23 "go.uber.org/zap/zapcore" 24 ) 25 26 func TestZapPayloadSuite(t *testing.T) { 27 if strings.HasPrefix(runtime.Version(), "go1.7") { 28 t.Skipf("Skipping due to json.RawMessage incompatibility with go1.7") 29 return 30 } 31 32 alwaysLoggingDeciderServer := func(ctx context.Context, fullMethodName string, servingObject interface{}) bool { return true } 33 alwaysLoggingDeciderClient := func(ctx context.Context, fullMethodName string) bool { return true } 34 35 b := newBaseZapSuite(t) 36 b.InterceptorTestSuite.ClientOpts = []grpc.DialOption{ 37 grpc.WithUnaryInterceptor(grpc_zap.PayloadUnaryClientInterceptor(b.log, alwaysLoggingDeciderClient)), 38 grpc.WithStreamInterceptor(grpc_zap.PayloadStreamClientInterceptor(b.log, alwaysLoggingDeciderClient)), 39 } 40 noOpZap := zap.New(zapcore.NewNopCore()) 41 b.InterceptorTestSuite.ServerOpts = []grpc.ServerOption{ 42 grpc_middleware.WithStreamServerChain( 43 grpc_ctxtags.StreamServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)), 44 grpc_zap.StreamServerInterceptor(noOpZap), 45 grpc_zap.PayloadStreamServerInterceptor(b.log, alwaysLoggingDeciderServer)), 46 grpc_middleware.WithUnaryServerChain( 47 grpc_ctxtags.UnaryServerInterceptor(grpc_ctxtags.WithFieldExtractor(grpc_ctxtags.CodeGenRequestFieldExtractor)), 48 grpc_zap.UnaryServerInterceptor(noOpZap), 49 grpc_zap.PayloadUnaryServerInterceptor(b.log, alwaysLoggingDeciderServer)), 50 } 51 suite.Run(t, &zapPayloadSuite{b}) 52 } 53 54 type zapPayloadSuite struct { 55 *zapBaseSuite 56 } 57 58 func (s *zapPayloadSuite) getServerAndClientMessages(expectedServer int, expectedClient int) (serverMsgs []map[string]interface{}, clientMsgs []map[string]interface{}) { 59 msgs := s.getOutputJSONs() 60 for _, m := range msgs { 61 if m["span.kind"] == "server" { 62 serverMsgs = append(serverMsgs, m) 63 } else if m["span.kind"] == "client" { 64 clientMsgs = append(clientMsgs, m) 65 } 66 } 67 require.Len(s.T(), serverMsgs, expectedServer, "must match expected number of server log messages") 68 require.Len(s.T(), clientMsgs, expectedClient, "must match expected number of client log messages") 69 return serverMsgs, clientMsgs 70 } 71 72 func (s *zapPayloadSuite) TestPing_LogsBothRequestAndResponse() { 73 _, err := s.Client.Ping(s.SimpleCtx(), goodPing) 74 75 require.NoError(s.T(), err, "there must be not be an error on a successful call") 76 serverMsgs, clientMsgs := s.getServerAndClientMessages(2, 2) 77 for _, m := range append(serverMsgs, clientMsgs...) { 78 assert.Equal(s.T(), m["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain service name") 79 assert.Equal(s.T(), m["grpc.method"], "Ping", "all lines must contain method name") 80 assert.Equal(s.T(), m["level"], "info", "all payloads must be logged on info level") 81 } 82 83 serverReq, serverResp := serverMsgs[0], serverMsgs[1] 84 clientReq, clientResp := clientMsgs[0], clientMsgs[1] 85 s.T().Log(clientReq) 86 assert.Contains(s.T(), clientReq, "grpc.request.content", "request payload must be logged in a structured way") 87 assert.Contains(s.T(), serverReq, "grpc.request.content", "request payload must be logged in a structured way") 88 assert.Contains(s.T(), clientResp, "grpc.response.content", "response payload must be logged in a structured way") 89 assert.Contains(s.T(), serverResp, "grpc.response.content", "response payload must be logged in a structured way") 90 } 91 92 func (s *zapPayloadSuite) TestPingError_LogsOnlyRequestsOnError() { 93 _, err := s.Client.PingError(s.SimpleCtx(), &pb_testproto.PingRequest{Value: "something", ErrorCodeReturned: uint32(4)}) 94 95 require.Error(s.T(), err, "there must be an error on an unsuccessful call") 96 serverMsgs, clientMsgs := s.getServerAndClientMessages(1, 1) 97 for _, m := range append(serverMsgs, clientMsgs...) { 98 assert.Equal(s.T(), m["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain service name") 99 assert.Equal(s.T(), m["grpc.method"], "PingError", "all lines must contain method name") 100 assert.Equal(s.T(), m["level"], "info", "must be logged at the info level") 101 } 102 103 assert.Contains(s.T(), clientMsgs[0], "grpc.request.content", "request payload must be logged in a structured way") 104 assert.Contains(s.T(), serverMsgs[0], "grpc.request.content", "request payload must be logged in a structured way") 105 } 106 107 func (s *zapPayloadSuite) TestPingStream_LogsAllRequestsAndResponses() { 108 messagesExpected := 20 109 stream, err := s.Client.PingStream(s.SimpleCtx()) 110 111 require.NoError(s.T(), err, "no error on stream creation") 112 for i := 0; i < messagesExpected; i++ { 113 require.NoError(s.T(), stream.Send(goodPing), "sending must succeed") 114 } 115 require.NoError(s.T(), stream.CloseSend(), "no error on send stream") 116 117 for { 118 pong := &pb_testproto.PingResponse{} 119 err := stream.RecvMsg(pong) 120 if err == io.EOF { 121 break 122 } 123 require.NoError(s.T(), err, "no error on receive") 124 } 125 126 serverMsgs, clientMsgs := s.getServerAndClientMessages(2*messagesExpected, 2*messagesExpected) 127 for _, m := range append(serverMsgs, clientMsgs...) { 128 assert.Equal(s.T(), m["grpc.service"], "mwitkow.testproto.TestService", "all lines must contain service name") 129 assert.Equal(s.T(), m["grpc.method"], "PingStream", "all lines must contain method name") 130 assert.Equal(s.T(), m["level"], "info", "all lines must logged at info level") 131 132 content := m["grpc.request.content"] != nil || m["grpc.response.content"] != nil 133 assert.True(s.T(), content, "all messages must contain payloads") 134 } 135 }