Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(browser): Add graphqlClientIntegration #13783

Open
wants to merge 5 commits into
base: develop
Choose a base branch
from

Conversation

Zen-cronic
Copy link
Contributor

@Zen-cronic Zen-cronic commented Sep 25, 2024

Resolves #13399

Todo:

  • Support fetch spans and tests
  • Support shorthand graphql queries (i.e., without a name)
  • Enhance breadcrumb data

  • If you've added code that should be tested, please add tests.
  • Ensure your code lints and the test suite passes (yarn lint) & (yarn test).

Added support for graphql query with `xhr` with tests.

Signed-off-by: Kaung Zin Hein <[email protected]>
@@ -357,6 +357,8 @@ export function xhrCallback(
return undefined;
}

const requestBody = JSON.parse(sentryXhrData.body as string);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is dangerous, any such operations we have to try-catch as bodies may not be JSON!

@@ -374,6 +376,7 @@ export function xhrCallback(
'server.address': host,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',
body: requestBody,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

h: We should not do this - this will attach the request bodies to all spans, always, which is a) large, b) potentially PII sensitive 😬

Instead of doing this in on('spanStart'), I think we'll need a hook that provides the request or body in some way. I am thinking of a new hook like:

client.on('outgoingRequestSpanStart', (span: Span, { body }: { body: unknown }) => {
  // ...
});

and emit this hook in this file after the span was started 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Noted. I implemented that hook and attached the req payload only to graphql spans.

Added test for fetch graphql.
Created new utility functions and added tests.
Updated `instrumentFetch` to collect fetch request payload.

Signed-off-by: Kaung Zin Hein <[email protected]>
const handlerData: HandlerDataFetch = {
args,
fetchData: {
method,
url,
body,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO collecting fetch req payload shouldn't be a problem as long as only the graphql requests are sampled. Because xhr instrumentation already collects the payload.

Signed-off-by: Kaung Zin Hein <[email protected]>
@Zen-cronic
Copy link
Contributor Author

Zen-cronic commented Sep 26, 2024

  • Todo: fix failing fetch tests by removing body from non-graphql requests

const requestBody = JSON.parse(payload);

// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
const isGraphQLRequest = !!requestBody['query'];
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This may not be the most accurate and safest way to detect a graphql request?

Comment on lines 21 to 23
client.on('spanStart', span => {
client.emit('outgoingRequestSpanStart', span);
});
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was maybe a bit confusingly explained by me - I would not do this, so I'd remove these lines here. I'll leave a comment further below where/how I would suggest to do this!

Suggested change
client.on('spanStart', span => {
client.emit('outgoingRequestSpanStart', span);
});

@@ -374,6 +377,7 @@ export function xhrCallback(
'server.address': host,
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',
body: graphqlRequest,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of adding this here, after the span was started, in this file do:

client.emit('outgoingRequestSpanStart', span, { body });

So the hook receives the body as second argument, and then in the integration we can use the body and add it to the span or use it otherwise. This way, this is not added to all spans, as we do not want to generally capture this for every span.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I get what you mean now! Will implement

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Add optional graphqlClientIntegration to @sentry/browser
2 participants