sentry-javascript icon indicating copy to clipboard operation
sentry-javascript copied to clipboard

Sentry Browser - Better Graphql support

Open plxel opened this issue 1 year ago • 12 comments

Problem Statement

Problem

Sentry does not really helps with GraphQL, since there is just one endpoint, it is kind of hard to understand what is going on. Since GraphQL is not a new thing anymore, would be nice to have better support for GraphQL out of the box

Would be nice to have query/mutation name

Image

I know there are some existing issues regarding this, but looks like they are closed and people trying to implement it themselves

Solution Brainstorm

Would be nice to have query/mutation name whenever GraphQL request is met

plxel avatar Aug 03 '24 05:08 plxel

Hello, thanks for writing in. What are you using to interact with graphql on the frontend? Is it instrumented by sentry?

If you instrument your backend with Sentry you should be getting query spans via our graphql instrumentation.

andreiborza avatar Aug 05 '24 14:08 andreiborza

hey @andreiborza on frontend for graphql we use graphql-request package

Is it instrumented by sentry

we have sentry installed on FE and on BE now, but not sure we did anything except standard setup there

plxel avatar Aug 05 '24 14:08 plxel

Could you please provide a reproduction repo or stackblitz so we can look into it?

As for the description of the transaction, that's correct but you should be able to see query spans as children to this transaction.

andreiborza avatar Aug 05 '24 14:08 andreiborza

making repo would be kind of hard.. maybe there is something else I can provide ?

I only see this :(

Image

plxel avatar Aug 05 '24 15:08 plxel

Please provide the link that that event, it would help investigating this. Only Sentry staff will be able to view the event.

andreiborza avatar Aug 05 '24 15:08 andreiborza

Although we do have GraphQL client integrations specced out in our sdk docs, we don't currently have frontend integrations for GraphQL clients in the SDK that can take care of mutating spans and similar.

I assume this is for Apollo client support? Or are you looking at changing names for others?

AbhiPrasad avatar Aug 06 '24 14:08 AbhiPrasad

Also, another thing I noticed, could it be that you have not configured tracePropagationTargets in your frontend app? See: https://docs.sentry.io/platforms/javascript/tracing/#configure - you'll need to configure the API of your backend where the graphql server runs, then you should see the http.server request with the child spans below the http.client request. So e.g.

Sentry.init({
  // continue traces to these external URLs
  tracePropagationTargets: ['my-api-page.com/api']
})

mydea avatar Aug 06 '24 15:08 mydea

@andreiborza example link: https://coperniq.sentry.io/performance/trace/8251b384a627423b9047b0294c701500/?eventId=f29c0d0272704b62815d9dedff0adfe7&fov=1%2C3563.699951171875&node=span-a493df09ce5e403c&node=txn-f29c0d0272704b62815d9dedff0adfe7&project=5515247&query=&source=performance_transaction_summary&spanSlug=http.client%3Af29c0d0272704b62815d9dedff0adfe7&statsPeriod=14d&tab=spans&timestamp=1722961548&transaction=%2F%2A%2Fprojects

@mydea interesting. yeah, we didnt specify tracePropagationTargets on frontend. Will try do we need to specify anything on backend sentry?

plxel avatar Aug 06 '24 16:08 plxel

@AbhiPrasad we dont use apollo atm, just react-query with graphql-request

plxel avatar Aug 06 '24 16:08 plxel

@mydea interesting. yeah, we didnt specify tracePropagationTargets on frontend. Will try do we need to specify anything on backend sentry?

No, you just need to configure this on the frontend, the backend will automatically pick this up then!

Let us know how that works - with this in place, you should be able to properly see the connected traces including the info about the query captured on the backend, at least!

mydea avatar Aug 07 '24 11:08 mydea

I came here looking for better graphql support as well. Mainly just interested in OperationNames at this point. I see the ios sdks got something similar a few months ago: https://github.com/getsentry/sentry-cocoa/pull/3931

scottopherson avatar Aug 14 '24 17:08 scottopherson

Hmm I see - that's a great pointer! I believe we could add an optional integration for this, which enhances breadcrumbs & spans accordingly, when used! Something like this:

Sentry.init({
  integrations: [
    Sentry.graphqlClientIntegration({
      endpoints: ['/graphql'],  
    })
  ]
})

I created an issue to properly track this, PRs are welcome for this feature :D https://github.com/getsentry/sentry-javascript/issues/13399

mydea avatar Aug 16 '24 07:08 mydea

It would be great if this works also for the react-native SDK 🤞

sregg avatar Aug 28 '24 17:08 sregg

@sregg thanks for the feedback. I referenced your comment on the issue we created from this: https://github.com/getsentry/sentry-javascript/issues/13399

andreiborza avatar Aug 29 '24 08:08 andreiborza

I made this patch for now.

diff --git a/node_modules/@sentry-internal/tracing/cjs/browser/request.js b/node_modules/@sentry-internal/tracing/cjs/browser/request.js
index a2e39de..6aa1cd2 100644
--- a/node_modules/@sentry-internal/tracing/cjs/browser/request.js
+++ b/node_modules/@sentry-internal/tracing/cjs/browser/request.js
@@ -227,9 +227,15 @@ function xhrCallback(
   const fullUrl = getFullURL(sentryXhrData.url);
   const host = fullUrl ? utils.parseUrl(fullUrl).host : undefined;
 
+  // hack: detect if the request is a graphql operation and if so, use the operation name as span name
+  const body = handlerData?.xhr?.__sentry_xhr_v3__?.body;
+  const graphqlBody = JSON.parse(body);
+  const graphqlOperationName = body ? graphqlBody?.operationName : undefined;
+  const name = graphqlOperationName ? `graphql - ${graphqlOperationName}` : `${sentryXhrData.method} ${sentryXhrData.url}`;
+
   const span = shouldCreateSpanResult
     ? core.startInactiveSpan({
-        name: `${sentryXhrData.method} ${sentryXhrData.url}`,
+        name,
         onlyIfParent: true,
         attributes: {
           type: 'xhr',
@@ -238,6 +244,7 @@ function xhrCallback(
           url: sentryXhrData.url,
           'server.address': host,
           [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',
+          'graphql.body': graphqlBody,
         },
         op: 'http.client',
       })

Before After
Image Image

sregg avatar Aug 29 '24 13:08 sregg

Closing this issue as a task for this has already been created: https://github.com/getsentry/sentry-javascript/issues/13399

s1gr1d avatar Dec 10 '24 14:12 s1gr1d