Skip to content

Commit a304218

Browse files
committed
fix(browser): Emit the outgoingRequestSpanStart hook after the span has started
Signed-off-by: Kaung Zin Hein <[email protected]>
1 parent 20b6516 commit a304218

File tree

8 files changed

+47
-32
lines changed

8 files changed

+47
-32
lines changed

dev-packages/browser-integration-tests/suites/integrations/graphqlClient/fetch/test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import type { Event } from '@sentry/types';
44
import { sentryTest } from '../../../../utils/fixtures';
55
import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers';
66

7+
// Duplicate from subject.js
8+
const query = `query Test{
9+
people {
10+
name
11+
pet
12+
}
13+
}`;
14+
const queryPayload = JSON.stringify({ query });
15+
716
sentryTest('should create spans for GraphQL Fetch requests', async ({ getLocalTestPath, page }) => {
817
const url = await getLocalTestPath({ testDir: __dirname });
918

@@ -43,9 +52,7 @@ sentryTest('should create spans for GraphQL Fetch requests', async ({ getLocalTe
4352
'server.address': 'sentry-test.io',
4453
'sentry.op': 'http.client',
4554
'sentry.origin': 'auto.http.browser',
46-
body: {
47-
query: expect.any(String),
48-
},
55+
body: queryPayload,
4956
}),
5057
});
5158
});

dev-packages/browser-integration-tests/suites/integrations/graphqlClient/xhr/subject.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,10 @@ xhr.setRequestHeader('Accept', 'application/json');
55
xhr.setRequestHeader('Content-Type', 'application/json');
66

77
const query = `query Test{
8-
9-
people {
10-
name
11-
pet
12-
}
8+
people {
9+
name
10+
pet
11+
}
1312
}`;
1413

1514
const requestBody = JSON.stringify({ query });

dev-packages/browser-integration-tests/suites/integrations/graphqlClient/xhr/test.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@ import type { Event } from '@sentry/types';
44
import { sentryTest } from '../../../../utils/fixtures';
55
import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers';
66

7+
// Duplicate from subject.js
8+
const query = `query Test{
9+
people {
10+
name
11+
pet
12+
}
13+
}`;
14+
const queryPayload = JSON.stringify({ query });
15+
716
sentryTest('should create spans for GraphQL XHR requests', async ({ getLocalTestPath, page }) => {
817
const url = await getLocalTestPath({ testDir: __dirname });
918

@@ -43,9 +52,7 @@ sentryTest('should create spans for GraphQL XHR requests', async ({ getLocalTest
4352
'server.address': 'sentry-test.io',
4453
'sentry.op': 'http.client',
4554
'sentry.origin': 'auto.http.browser',
46-
body: {
47-
query: expect.any(String),
48-
},
55+
body: queryPayload,
4956
},
5057
});
5158
});

packages/browser/src/integrations/graphqlClient.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,19 @@ interface GraphQLClientOptions {
1212
endpoints: Array<string>;
1313
}
1414

15+
interface GraphQLRequestPayload {
16+
query: string;
17+
operationName?: string;
18+
variables?: Record<string, any>;
19+
}
20+
1521
const INTEGRATION_NAME = 'GraphQLClient';
1622

1723
const _graphqlClientIntegration = ((options: GraphQLClientOptions) => {
1824
return {
1925
name: INTEGRATION_NAME,
2026
setup(client) {
21-
client.on('spanStart', span => {
22-
client.emit('outgoingRequestSpanStart', span);
23-
});
24-
25-
client.on('outgoingRequestSpanStart', span => {
27+
client.on('outgoingRequestSpanStart', (span, { body }) => {
2628
const spanJSON = spanToJSON(span);
2729

2830
const spanAttributes = spanJSON.data || {};
@@ -38,19 +40,17 @@ const _graphqlClientIntegration = ((options: GraphQLClientOptions) => {
3840

3941
if (isTracedGraphqlEndpoint) {
4042
const httpMethod = spanAttributes[SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD] || spanAttributes['http.method'];
41-
const graphqlBody = spanAttributes['body'];
43+
const graphqlBody = body as GraphQLRequestPayload;
4244

4345
// Standard graphql request shape: https://graphql.org/learn/serving-over-http/#post-request
44-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
45-
const graphqlQuery = graphqlBody && (graphqlBody['query'] as string);
46-
47-
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
48-
const graphqlOperationName = graphqlBody && (graphqlBody['operationName'] as string);
46+
const graphqlQuery = graphqlBody.query;
47+
const graphqlOperationName = graphqlBody.operationName;
4948

5049
const { operationName = graphqlOperationName, operationType } = parseGraphQLQuery(graphqlQuery);
5150
const newOperation = operationName ? `${operationType} ${operationName}` : `${operationType}`;
5251

5352
span.updateName(`${httpMethod} ${httpUrl} (${newOperation})`);
53+
span.setAttribute('body', JSON.stringify(graphqlBody));
5454
}
5555
}
5656
});

packages/browser/src/tracing/request.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -363,8 +363,6 @@ export function xhrCallback(
363363

364364
const hasParent = !!getActiveSpan();
365365

366-
const graphqlRequest = getGraphQLRequestPayload(sentryXhrData.body as string);
367-
368366
const span =
369367
shouldCreateSpanResult && hasParent
370368
? startInactiveSpan({
@@ -377,7 +375,6 @@ export function xhrCallback(
377375
'server.address': host,
378376
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',
379377
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',
380-
body: graphqlRequest,
381378
},
382379
})
383380
: new SentryNonRecordingSpan();
@@ -398,6 +395,10 @@ export function xhrCallback(
398395
);
399396
}
400397

398+
if (client) {
399+
client.emit('outgoingRequestSpanStart', span, { body: getGraphQLRequestPayload(sentryXhrData.body as string) });
400+
}
401+
401402
return span;
402403
}
403404

packages/core/src/baseclient.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
463463
public on(hook: 'startNavigationSpan', callback: (options: StartSpanOptions) => void): () => void;
464464

465465
/** @inheritdoc */
466-
public on(hook: 'outgoingRequestSpanStart', callback: (span: Span) => void): () => void;
466+
public on(hook: 'outgoingRequestSpanStart', callback: (span: Span, { body }: { body: unknown }) => void): () => void;
467467

468468
public on(hook: 'flush', callback: () => void): () => void;
469469

@@ -544,7 +544,7 @@ export abstract class BaseClient<O extends ClientOptions> implements Client<O> {
544544
public emit(hook: 'startNavigationSpan', options: StartSpanOptions): void;
545545

546546
/** @inheritdoc */
547-
public emit(hook: 'outgoingRequestSpanStart', span: Span): void;
547+
public emit(hook: 'outgoingRequestSpanStart', span: Span, { body }: { body: unknown }): void;
548548

549549
/** @inheritdoc */
550550
public emit(hook: 'flush'): void;

packages/core/src/fetch.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,6 @@ export function instrumentFetchRequest(
7373

7474
const hasParent = !!getActiveSpan();
7575

76-
const graphqlRequest = getGraphQLRequestPayload(body as string);
77-
7876
const span =
7977
shouldCreateSpanResult && hasParent
8078
? startInactiveSpan({
@@ -87,7 +85,6 @@ export function instrumentFetchRequest(
8785
'server.address': host,
8886
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: spanOrigin,
8987
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',
90-
body: graphqlRequest,
9188
},
9289
})
9390
: new SentryNonRecordingSpan();
@@ -116,6 +113,10 @@ export function instrumentFetchRequest(
116113
);
117114
}
118115

116+
if (client) {
117+
client.emit('outgoingRequestSpanStart', span, { body: getGraphQLRequestPayload(body as string) });
118+
}
119+
119120
return span;
120121
}
121122

packages/types/src/client.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ export interface Client<O extends ClientOptions = ClientOptions> {
295295
* A hook for GraphQL client integration to enhance a span and breadcrumbs with request data.
296296
* @returns A function that, when executed, removes the registered callback.
297297
*/
298-
on(hook: 'outgoingRequestSpanStart', callback: (span: Span) => void): () => void;
298+
on(hook: 'outgoingRequestSpanStart', callback: (span: Span, { body }: { body: unknown }) => void): () => void;
299299

300300
/**
301301
* A hook that is called when the client is flushing
@@ -396,7 +396,7 @@ export interface Client<O extends ClientOptions = ClientOptions> {
396396
/**
397397
* Emit a hook event for GraphQL client integration to enhance a span and breadcrumbs with request data.
398398
*/
399-
emit(hook: 'outgoingRequestSpanStart', span: Span): void;
399+
emit(hook: 'outgoingRequestSpanStart', span: Span, { body }: { body: unknown }): void;
400400

401401
/**
402402
* Emit a hook event for client flush

0 commit comments

Comments
 (0)