From 34980fac0b6ccf07950addbe8dfb7f755031d36e Mon Sep 17 00:00:00 2001 From: Dien Vo <163492606+dienvoandpadcojp@users.noreply.github.com> Date: Fri, 27 Sep 2024 15:52:24 +0700 Subject: [PATCH] contrib/99designs/gqlgen/tracer.go: nil check response (#2792) --- contrib/99designs/gqlgen/tracer.go | 23 ++++--- contrib/99designs/gqlgen/tracer_test.go | 88 +++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 8 deletions(-) diff --git a/contrib/99designs/gqlgen/tracer.go b/contrib/99designs/gqlgen/tracer.go index 66b0208c362..ffdcb0c5501 100644 --- a/contrib/99designs/gqlgen/tracer.go +++ b/contrib/99designs/gqlgen/tracer.go @@ -123,14 +123,21 @@ func (t *gqlTracer) InterceptOperation(ctx context.Context, next graphql.Operati } defer span.Finish(tracer.WithError(err)) } - query.Finish(graphqlsec.ExecutionOperationRes{ - Data: response.Data, // NB - This is raw data, but rather not parse it (possibly expensive). - Error: response.Errors, - }) - req.Finish(span, graphqlsec.RequestOperationRes{ - Data: response.Data, // NB - This is raw data, but rather not parse it (possibly expensive). - Error: response.Errors, - }) + + var ( + executionOperationRes graphqlsec.ExecutionOperationRes + requestOperationRes graphqlsec.RequestOperationRes + ) + if response != nil { + executionOperationRes.Data = response.Data + executionOperationRes.Error = response.Errors + + requestOperationRes.Data = response.Data + requestOperationRes.Error = response.Errors + } + + query.Finish(executionOperationRes) + req.Finish(span, requestOperationRes) return response } } diff --git a/contrib/99designs/gqlgen/tracer_test.go b/contrib/99designs/gqlgen/tracer_test.go index 0517aef9762..09e6eab6288 100644 --- a/contrib/99designs/gqlgen/tracer_test.go +++ b/contrib/99designs/gqlgen/tracer_test.go @@ -261,3 +261,91 @@ func newTestClient(t *testing.T, h *testserver.TestServer, tracer graphql.Handle h.Use(tracer) return client.New(h) } + +func TestInterceptOperation(t *testing.T) { + assertions := assert.New(t) + graphqlTestSrv := testserver.New() + c := newTestClient(t, graphqlTestSrv, NewTracer()) + + t.Run("intercept operation with graphQL Query", func(t *testing.T) { + mt := mocktracer.Start() + defer mt.Stop() + + err := c.Post(`{ name }`, &testServerResponse{}) + assertions.Nil(err) + + allSpans := mt.FinishedSpans() + var root mocktracer.Span + var resNames []string + var opNames []string + for _, span := range allSpans { + if span.ParentID() == 0 { + root = span + } + resNames = append(resNames, span.Tag(ext.ResourceName).(string)) + opNames = append(opNames, span.OperationName()) + assertions.Equal("99designs/gqlgen", span.Tag(ext.Component)) + } + assertions.ElementsMatch(resNames, []string{readOp, parsingOp, validationOp, "Query.name", `{ name }`}) + assertions.ElementsMatch(opNames, []string{readOp, parsingOp, validationOp, fieldOp, "graphql.query"}) + assertions.NotNil(root) + assertions.Nil(root.Tag(ext.Error)) + }) + + t.Run("intercept operation with graphQL Mutation", func(t *testing.T) { + mt := mocktracer.Start() + defer mt.Stop() + + err := c.Post(`mutation Name { name }`, &testServerResponse{}) + // due to testserver.New() implementation, mutation is not supported + assertions.NotNil(err) + + allSpans := mt.FinishedSpans() + var root mocktracer.Span + var resNames []string + var opNames []string + for _, span := range allSpans { + if span.ParentID() == 0 { + root = span + } + resNames = append(resNames, span.Tag(ext.ResourceName).(string)) + opNames = append(opNames, span.OperationName()) + assertions.Equal("99designs/gqlgen", span.Tag(ext.Component)) + } + assertions.ElementsMatch(resNames, []string{readOp, parsingOp, validationOp, `mutation Name { name }`}) + assertions.ElementsMatch(opNames, []string{readOp, parsingOp, validationOp, "graphql.mutation"}) + assertions.NotNil(root) + assertions.NotNil(root.Tag(ext.Error)) + }) + + t.Run("intercept operation with graphQL Subscription", func(t *testing.T) { + mt := mocktracer.Start() + defer mt.Stop() + + go func() { + graphqlTestSrv.SendCompleteSubscriptionMessage() + }() + + // using raw post because post try to access nil response's Data field + resp, err := c.RawPost(`subscription Name { name }`) + assertions.Nil(err) + assertions.Nil(resp) + + allSpans := mt.FinishedSpans() + var root mocktracer.Span + var resNames []string + var opNames []string + for _, span := range allSpans { + if span.ParentID() == 0 { + root = span + } + resNames = append(resNames, span.Tag(ext.ResourceName).(string)) + opNames = append(opNames, span.OperationName()) + assertions.Equal("99designs/gqlgen", span.Tag(ext.Component)) + } + assertions.ElementsMatch(resNames, []string{`subscription Name { name }`, `subscription Name { name }`, "subscription Name { name }"}) + assertions.ElementsMatch(opNames, []string{readOp, parsingOp, validationOp}) + assertions.NotNil(root) + assertions.Nil(root.Tag(ext.Error)) + }) +}