Skip to content

Commit 3e5659f

Browse files
committed
fix(browser): Refactor breadcrumb handlers to use hint
Signed-off-by: Kaung Zin Hein <[email protected]>
1 parent b36a4be commit 3e5659f

File tree

9 files changed

+41
-57
lines changed

9 files changed

+41
-57
lines changed

packages/browser/src/integrations/breadcrumbs.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
safeJoin,
3737
severityLevelFromString,
3838
} from '@sentry/core';
39+
import type { FetchHint, XhrHint } from '@sentry-internal/replay';
3940
import { DEBUG_BUILD } from '../debug-build';
4041
import { WINDOW } from '../helpers';
4142

@@ -258,7 +259,7 @@ function _getXhrBreadcrumbHandler(client: Client): (handlerData: HandlerDataXhr)
258259
level: getBreadcrumbLogLevelFromHttpStatusCode(status_code),
259260
};
260261

261-
client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, handlerData);
262+
client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as XhrHint);
262263

263264
addBreadcrumb(breadcrumb, hint);
264265
};
@@ -305,7 +306,7 @@ function _getFetchBreadcrumbHandler(client: Client): (handlerData: HandlerDataFe
305306
type: 'http',
306307
} satisfies Breadcrumb;
307308

308-
client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, handlerData);
309+
client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as FetchHint);
309310

310311
addBreadcrumb(breadcrumb, hint);
311312
} else {
@@ -329,7 +330,7 @@ function _getFetchBreadcrumbHandler(client: Client): (handlerData: HandlerDataFe
329330
level: getBreadcrumbLogLevelFromHttpStatusCode(data.status_code),
330331
};
331332

332-
client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, handlerData);
333+
client.emit('beforeOutgoingRequestBreadcrumb', breadcrumb, hint as FetchHint);
333334

334335
addBreadcrumb(breadcrumb, hint);
335336
}

packages/browser/src/integrations/graphqlClient.ts

Lines changed: 10 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { SENTRY_XHR_DATA_KEY } from '@sentry-internal/browser-utils';
2-
import { FetchHint, getBodyString, XhrHint } from '@sentry-internal/replay';
2+
import { getBodyString } from '@sentry-internal/replay';
3+
import type { FetchHint, XhrHint } from '@sentry-internal/replay';
34
import {
45
SEMANTIC_ATTRIBUTE_HTTP_REQUEST_METHOD,
56
SEMANTIC_ATTRIBUTE_SENTRY_OP,
@@ -22,6 +23,11 @@ interface GraphQLRequestPayload {
2223
extensions?: Record<string, unknown>;
2324
}
2425

26+
interface GraphQLOperation {
27+
operationType: string | undefined;
28+
operationName: string | undefined;
29+
}
30+
2531
const INTEGRATION_NAME = 'GraphQLClient';
2632

2733
const _graphqlClientIntegration = ((options: GraphQLClientOptions) => {
@@ -65,7 +71,6 @@ function _updateSpanWithGraphQLData(client: Client, options: GraphQLClientOption
6571
span.updateName(`${httpMethod} ${httpUrl} (${operationInfo})`);
6672
span.setAttribute('graphql.document', payload);
6773
}
68-
6974
});
7075
}
7176

@@ -92,11 +97,6 @@ function _updateBreadcrumbWithGraphQLData(client: Client, options: GraphQLClient
9297
data['graphql.document'] = (graphqlBody as GraphQLRequestPayload).query;
9398
data['graphql.operation'] = operationInfo;
9499
}
95-
96-
// The body prop attached to HandlerDataFetch for the span should be removed.
97-
if (isFetch && data.body) {
98-
delete data.body;
99-
}
100100
}
101101
}
102102
});
@@ -121,7 +121,7 @@ function _getGraphQLOperation(requestBody: GraphQLRequestPayload): string {
121121
*/
122122
function _getRequestPayloadXhrOrFetch(hint: XhrHint | FetchHint): string | undefined {
123123
const isXhr = 'xhr' in hint;
124-
const isFetch = !isXhr
124+
const isFetch = !isXhr;
125125

126126
let body: string | undefined;
127127

@@ -136,6 +136,7 @@ function _getRequestPayloadXhrOrFetch(hint: XhrHint | FetchHint): string | undef
136136
return body;
137137
}
138138

139+
// Duplicate from deprecated @sentry-utils/src/instrument/fetch.ts
139140
function hasProp<T extends string>(obj: unknown, prop: T): obj is Record<string, string> {
140141
return !!obj && typeof obj === 'object' && !!(obj as Record<string, string>)[prop];
141142
}
@@ -154,13 +155,9 @@ export function parseFetchPayload(fetchArgs: unknown[]): string | undefined {
154155
return hasProp(arg, 'body') ? String(arg.body) : undefined;
155156
}
156157

157-
interface GraphQLOperation {
158-
operationType: string | undefined;
159-
operationName: string | undefined;
160-
}
161-
162158
/**
163159
* Extract the name and type of the operation from the GraphQL query.
160+
* Exported for tests only.
164161
* @param query
165162
*/
166163
export function parseGraphQLQuery(query: string): GraphQLOperation {

packages/browser/src/tracing/request.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
addXhrInstrumentationHandler,
55
} from '@sentry-internal/browser-utils';
66
import type { Client, HandlerDataXhr, SentryWrappedXMLHttpRequest, Span } from '@sentry/core';
7+
import type { XhrHint } from '@sentry-internal/replay';
78
import {
89
SEMANTIC_ATTRIBUTE_SENTRY_OP,
910
SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,
@@ -33,7 +34,6 @@ import {
3334
stringMatchesSomePattern,
3435
} from '@sentry/core';
3536
import { WINDOW } from '../helpers';
36-
import { XhrHint } from '@sentry-internal/replay';
3737

3838
/** Options for Request Instrumentation */
3939
export interface RequestInstrumentationOptions {

packages/browser/test/integrations/graphqlClient.test.ts

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
1-
import { getGraphQLRequestPayload, parseFetchPayload, parseGraphQLQuery } from "../../src/integrations/graphqlClient";
1+
import { getGraphQLRequestPayload, parseFetchPayload, parseGraphQLQuery } from '../../src/integrations/graphqlClient';
22

33
describe('GraphqlClient', () => {
4-
describe('parseFetchPayload', () => {
5-
4+
describe('parseFetchPayload', () => {
65
const data = [1, 2, 3];
76
const jsonData = '{"data":[1,2,3]}';
8-
7+
98
it.each([
109
['string URL only', ['http://example.com'], undefined],
1110
['URL object only', [new URL('http://example.com')], undefined],
@@ -28,10 +27,10 @@ describe('GraphqlClient', () => {
2827
],
2928
])('%s', (_name, args, expected) => {
3029
const actual = parseFetchPayload(args as unknown[]);
31-
30+
3231
expect(actual).toEqual(expected);
3332
});
34-
});
33+
});
3534

3635
describe('parseGraphQLQuery', () => {
3736
const queryOne = `query Test {
@@ -72,7 +71,7 @@ describe('GraphqlClient', () => {
7271
expect(parseGraphQLQuery(input)).toEqual(output);
7372
});
7473
});
75-
74+
7675
describe('getGraphQLRequestPayload', () => {
7776
test('should return undefined for non-GraphQL request', () => {
7877
const requestBody = { data: [1, 2, 3] };
@@ -90,5 +89,3 @@ describe('GraphqlClient', () => {
9089
});
9190
});
9291
});
93-
94-

packages/core/src/client.ts

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@ import type {
1616
FeedbackEvent,
1717
FetchBreadcrumbHint,
1818
HandlerDataFetch,
19-
HandlerDataXhr,
2019
Integration,
2120
MonitorConfig,
2221
Outcome,
@@ -69,12 +68,12 @@ const MISSING_RELEASE_FOR_SESSION_ERROR = 'Discarded session because of missing
6968
type RequestBody = null | Blob | BufferSource | FormData | URLSearchParams | string;
7069

7170
export type XhrHint = XhrBreadcrumbHint & {
72-
xhr: XMLHttpRequest & SentryWrappedXMLHttpRequest;
73-
input?: RequestBody;
71+
xhr: XMLHttpRequest & SentryWrappedXMLHttpRequest;
72+
input?: RequestBody;
7473
};
7574
export type FetchHint = FetchBreadcrumbHint & {
76-
input: HandlerDataFetch['args'];
77-
response: Response;
75+
input: HandlerDataFetch['args'];
76+
response: Response;
7877
};
7978

8079
/**
@@ -596,15 +595,12 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
596595
public on(hook: 'startNavigationSpan', callback: (options: StartSpanOptions) => void): () => void;
597596

598597
/** @inheritdoc */
599-
public on(
600-
hook: 'beforeOutgoingRequestSpan',
601-
callback: (span: Span, hint: XhrHint | FetchHint ) => void,
602-
): () => void;
598+
public on(hook: 'beforeOutgoingRequestSpan', callback: (span: Span, hint: XhrHint | FetchHint) => void): () => void;
603599

604600
/** @inheritdoc */
605601
public on(
606602
hook: 'beforeOutgoingRequestBreadcrumb',
607-
callback: (breadcrumb: Breadcrumb, handlerData: HandlerDataXhr | HandlerDataFetch) => void,
603+
callback: (breadcrumb: Breadcrumb, hint: XhrHint | FetchHint) => void,
608604
): () => void;
609605

610606
public on(hook: 'flush', callback: () => void): () => void;
@@ -737,11 +733,7 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
737733
public emit(hook: 'beforeOutgoingRequestSpan', span: Span, hint: XhrHint | FetchHint): void;
738734

739735
/** @inheritdoc */
740-
public emit(
741-
hook: 'beforeOutgoingRequestBreadcrumb',
742-
breadcrumb: Breadcrumb,
743-
handlerData: HandlerDataXhr | HandlerDataFetch,
744-
): void;
736+
public emit(hook: 'beforeOutgoingRequestBreadcrumb', breadcrumb: Breadcrumb, hint: XhrHint | FetchHint): void;
745737

746738
/** @inheritdoc */
747739
public emit(hook: 'flush'): void;

packages/core/src/fetch.ts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import {
66
isInstanceOf,
77
parseUrl,
88
} from '@sentry/utils';
9+
import type { FetchHint } from './baseclient';
910
import { getClient, getCurrentScope, getIsolationScope } from './currentScopes';
1011
import { SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN } from './semanticAttributes';
1112
import { SPAN_STATUS_ERROR, setHttpStatus, startInactiveSpan } from './tracing';
@@ -17,7 +18,6 @@ import { parseUrl } from './utils-hoist/url';
1718
import { hasTracingEnabled } from './utils/hasTracingEnabled';
1819
import { getActiveSpan } from './utils/spanUtils';
1920
import { getTraceData } from './utils/traceData';
20-
import { FetchHint } from './baseclient';
2121

2222
type PolymorphicRequestHeaders =
2323
| Record<string, string | undefined>
@@ -110,8 +110,14 @@ export function instrumentFetchRequest(
110110
}
111111

112112
if (client) {
113-
const fetchHint = { input: handlerData.args , response: handlerData.response, startTimestamp: handlerData.startTimestamp, endTimestamp: handlerData.endTimestamp } satisfies FetchHint
114-
client.emit('beforeOutgoingRequestSpan', span, fetchHint);
113+
// There's no 'input' key in HandlerDataFetch
114+
const fetchHint = {
115+
input: handlerData.args,
116+
response: handlerData.response,
117+
startTimestamp: handlerData.startTimestamp,
118+
endTimestamp: handlerData.endTimestamp,
119+
};
120+
client.emit('beforeOutgoingRequestSpan', span, fetchHint as FetchHint);
115121
}
116122

117123
return span;

packages/core/src/utils-hoist/instrument/fetch.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,3 @@ export function parseFetchArgs(fetchArgs: unknown[]): { method: string; url: str
234234
method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',
235235
};
236236
}
237-

packages/types/src/client.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import type { DynamicSamplingContext, Envelope } from './envelope';
99
import type { Event, EventHint } from './event';
1010
import type { EventProcessor } from './eventprocessor';
1111
import type { FeedbackEvent } from './feedback';
12-
import type { HandlerDataFetch, HandlerDataXhr, SentryWrappedXMLHttpRequest } from './instrument';
12+
import type { HandlerDataFetch, SentryWrappedXMLHttpRequest } from './instrument';
1313
import type { Integration } from './integration';
1414
import type { ClientOptions } from './options';
1515
import type { ParameterizedString } from './parameterize';
@@ -309,18 +309,15 @@ export interface Client<O extends ClientOptions = ClientOptions> {
309309
* A hook for GraphQL client integration to enhance a span with request data.
310310
* @returns A function that, when executed, removes the registered callback.
311311
*/
312-
on(
313-
hook: 'beforeOutgoingRequestSpan',
314-
callback: (span: Span, hint: XhrHint | FetchHint) => void,
315-
): () => void;
312+
on(hook: 'beforeOutgoingRequestSpan', callback: (span: Span, hint: XhrHint | FetchHint) => void): () => void;
316313

317314
/**
318315
* A hook for GraphQL client integration to enhance a breadcrumb with request data.
319316
* @returns A function that, when executed, removes the registered callback.
320317
*/
321318
on(
322319
hook: 'beforeOutgoingRequestBreadcrumb',
323-
callback: (breadcrumb: Breadcrumb, handlerData: HandlerDataXhr | HandlerDataFetch) => void,
320+
callback: (breadcrumb: Breadcrumb, hint: XhrHint | FetchHint) => void,
324321
): () => void;
325322

326323
/**
@@ -427,11 +424,7 @@ export interface Client<O extends ClientOptions = ClientOptions> {
427424
/**
428425
* Emit a hook event for GraphQL client integration to enhance a breadcrumb with request data.
429426
*/
430-
emit(
431-
hook: 'beforeOutgoingRequestBreadcrumb',
432-
breadcrumb: Breadcrumb,
433-
handlerData: HandlerDataXhr | HandlerDataFetch,
434-
): void;
427+
emit(hook: 'beforeOutgoingRequestBreadcrumb', breadcrumb: Breadcrumb, hint: XhrHint | FetchHint): void;
435428

436429
/**
437430
* Emit a hook event for client flush

packages/utils/test/instrument/fetch.test.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ describe('instrument > parseFetchArgs', () => {
2727
expect(actual).toEqual(expected);
2828
});
2929
});
30-
3130
describe('instrument > parseFetchPayload', () => {
3231
const data = [1, 2, 3];
3332
const jsonData = '{"data":[1,2,3]}';

0 commit comments

Comments
 (0)