Performance Monitoring "head-based"

I’m having trouble fully understanding how Performance Monitoring works. I’ve read a few times and near the end there is a section called “Consistency Within a Trace”

Here it talks about how Sentry uses headers to tell the backend that tracing should be enabled.

However my setup is as follows

  • SPA (React)
  • Backend (GraphQL)

The SPA and Backend are disconnected. When a user does something in the frontend then react triggers graphql to ‘load’ that portion of the data. So during a single SPA session there can be multiple requests to the backend.

The sentry documentation states:

When each browser makes requests to your backend, it includes in those requests the “yes, please collect transactions” or the “no, don’t collect transactions this time” decision in the headers.

However whenever the SPA requests data from the backend there is no such header set. I don’t expect there to be either because the header would have to be added to the client library servicing the GraphQL requests from the frontend to the backend.

Perhaps there is something I am missing here? The only way I can think to do it is how transaction_ids works (

Transaction IDs work pretty well and in this case I set the header manually on my client library. Do I need to do the same for tracing? EG Set the header manually on the front end and then detect it on the backend (during sample_tracing callbacks)

Your high-level understanding is correct.

The JavaScript SDK generally instruments all outgoing XHR so if your clientside graphql library does do regular XHR it should work just fine and you should see a sentry-trace header as part of the request.

However, due to CORS the header may not be sent in all cases, because doing so would be a content security policy violation. Please refer to

I think that’s the issue you may be running into. If not there’s also the possibility that the JS SDK fails to instrument or ended its own transaction too early, ending the trace. Failing all that, there are also less stable APIs in the SDK to get the data for manually sending this header (or using a custom “transaction ID”), but I’ll post info about this when necessary because ultimatively they’re workarounds, not how it’s supposed to work.

1 Like

This thread on GitHub may also shed some light:


Thanks for the information. It answers a bunch of questions. So sentry patches both fetch and XHR but only if the domain matches. I’m actually using axios with Apollo. I’m not sure if axios uses XHR under the hood but I assume it does as the options are limited. If not I might need to do it the “manual” way where I patch the sentry-trace header into axios when needed

Confirmed that once I modified tracingOrigins to include my backend domain (which is not the same as the SPA) sentry_trace was included. Additionally I had to temporarily increase idleTimeout to be able to test this. So infact XHR and fetch are getting modified before being used by Axios and then Apollo. Thanks @untitaker and @rhcarvalho!!!