Skip to content

Commit 6dcefbf

Browse files
committed
only use for default browser tracing
1 parent 5ae1d09 commit 6dcefbf

File tree

5 files changed

+80
-23
lines changed

5 files changed

+80
-23
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as Sentry from '@sentry/browser';
2+
3+
window.Sentry = Sentry;
4+
5+
Sentry.init({
6+
dsn: 'https://[email protected]/1337',
7+
integrations: [
8+
Sentry.browserTracingIntegration({
9+
detectRedirects: false,
10+
}),
11+
],
12+
tracesSampleRate: 1,
13+
});
14+
15+
// trigger redirect immediately
16+
window.history.pushState({}, '', '/sub-page');
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import { expect } from '@playwright/test';
2+
import { sentryTest } from '../../../../../utils/fixtures';
3+
import { envelopeRequestParser, shouldSkipTracingTest, waitForTransactionRequest } from '../../../../../utils/helpers';
4+
5+
sentryTest(
6+
'should not create a navigation.redirect span if `detectRedirects` is set to false',
7+
async ({ getLocalTestUrl, page }) => {
8+
if (shouldSkipTracingTest()) {
9+
sentryTest.skip();
10+
}
11+
12+
const url = await getLocalTestUrl({ testDir: __dirname });
13+
14+
const pageloadRequestPromise = waitForTransactionRequest(page, event => event.contexts?.trace?.op === 'pageload');
15+
const navigationRequestPromise = waitForTransactionRequest(
16+
page,
17+
event => event.contexts?.trace?.op === 'navigation',
18+
);
19+
20+
await page.goto(url);
21+
22+
const pageloadRequest = envelopeRequestParser(await pageloadRequestPromise);
23+
// Ensure a navigation span is sent, too
24+
await navigationRequestPromise;
25+
26+
const spans = pageloadRequest.spans || [];
27+
28+
expect(spans).not.toContainEqual(
29+
expect.objectContaining({
30+
op: 'navigation.redirect',
31+
}),
32+
);
33+
},
34+
);

packages/browser/src/tracing/browserTracingIntegration.ts

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -422,13 +422,12 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
422422
}
423423
}
424424

425-
client.on('startNavigationSpan', startSpanOptions => {
425+
client.on('startNavigationSpan', (startSpanOptions, navigationOptions) => {
426426
if (getClient() !== client) {
427427
return;
428428
}
429429

430-
const activeSpan = getActiveIdleSpan(client);
431-
if (detectRedirects && activeSpan && isRedirect(activeSpan, lastClickTimestamp)) {
430+
if (navigationOptions?.isRedirect) {
432431
DEBUG_BUILD && logger.warn('[Tracing] Detected redirect, navigation span will not be the root span.');
433432
_createRouteSpan(
434433
client,
@@ -522,7 +521,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
522521
startingUrl = undefined;
523522
const parsed = parseStringToURLObject(to);
524523
const activeSpan = getActiveIdleSpan(client);
525-
const navigationIsRedirect = activeSpan && isRedirect(activeSpan, lastClickTimestamp);
524+
const navigationIsRedirect = activeSpan && detectRedirects && isRedirect(activeSpan, lastClickTimestamp);
526525
startBrowserTracingNavigationSpan(
527526
client,
528527
{
@@ -532,7 +531,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
532531
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.browser',
533532
},
534533
},
535-
!navigationIsRedirect ? { url: to } : undefined,
534+
{ url: to, isRedirect: navigationIsRedirect },
536535
);
537536
});
538537
}
@@ -588,17 +587,18 @@ export function startBrowserTracingPageLoadSpan(
588587
export function startBrowserTracingNavigationSpan(
589588
client: Client,
590589
spanOptions: StartSpanOptions,
591-
options?: { url?: string },
590+
options?: { url?: string; isRedirect?: boolean },
592591
): Span | undefined {
593-
client.emit('startNavigationSpan', spanOptions);
592+
const { url, isRedirect } = options || {};
593+
594+
client.emit('startNavigationSpan', spanOptions, { isRedirect });
594595

595596
const scope = getCurrentScope();
596597
scope.setTransactionName(spanOptions.name);
597598

598599
// We store the normalized request data on the scope, so we get the request data at time of span creation
599600
// otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL
600-
const url = options?.url;
601-
if (url) {
601+
if (url && !isRedirect) {
602602
scope.setSDKProcessingMetadata({
603603
normalizedRequest: {
604604
...getHttpRequestData(),

packages/browser/test/tracing/browserTracingIntegration.test.ts

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -53,33 +53,32 @@ Object.defineProperty(global, 'history', { value: dom.window.history, writable:
5353
const originalGlobalDocument = WINDOW.document;
5454
const originalGlobalLocation = WINDOW.location;
5555
const originalGlobalHistory = WINDOW.history;
56-
afterAll(() => {
57-
// Clean up JSDom
58-
Object.defineProperty(WINDOW, 'document', { value: originalGlobalDocument });
59-
Object.defineProperty(WINDOW, 'location', { value: originalGlobalLocation });
60-
Object.defineProperty(WINDOW, 'history', { value: originalGlobalHistory });
61-
});
62-
63-
afterEach(() => {
64-
vi.useRealTimers();
65-
performance.clearMarks();
66-
});
6756

6857
describe('browserTracingIntegration', () => {
6958
beforeEach(() => {
59+
vi.useFakeTimers();
7060
getCurrentScope().clear();
7161
getIsolationScope().clear();
7262
getCurrentScope().setClient(undefined);
7363
document.head.innerHTML = '';
64+
65+
const dom = new JSDOM(undefined, { url: 'https://example.com/' });
66+
Object.defineProperty(global, 'location', { value: dom.window.document.location, writable: true });
7467
});
7568

7669
afterEach(() => {
7770
getActiveSpan()?.end();
71+
vi.useRealTimers();
72+
performance.clearMarks();
7873
});
7974

8075
afterAll(() => {
8176
global.window.TextEncoder = oldTextEncoder;
8277
global.window.TextDecoder = oldTextDecoder;
78+
// Clean up JSDom
79+
Object.defineProperty(WINDOW, 'document', { value: originalGlobalDocument });
80+
Object.defineProperty(WINDOW, 'location', { value: originalGlobalLocation });
81+
Object.defineProperty(WINDOW, 'history', { value: originalGlobalHistory });
8382
});
8483

8584
it('works with tracing enabled', () => {
@@ -152,7 +151,7 @@ describe('browserTracingIntegration', () => {
152151
expect(spanIsSampled(span!)).toBe(false);
153152
});
154153

155-
it('starts navigation when URL changes', () => {
154+
it('starts navigation when URL changes after > 300ms', () => {
156155
const client = new BrowserClient(
157156
getDefaultBrowserClientOptions({
158157
tracesSampleRate: 1,
@@ -185,6 +184,7 @@ describe('browserTracingIntegration', () => {
185184
const dom = new JSDOM(undefined, { url: 'https://example.com/test' });
186185
Object.defineProperty(global, 'location', { value: dom.window.document.location, writable: true });
187186

187+
vi.advanceTimersByTime(400);
188188
WINDOW.history.pushState({}, '', '/test');
189189

190190
expect(span!.isRecording()).toBe(false);

packages/core/src/client.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -607,7 +607,10 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
607607
* A hook for browser tracing integrations to trigger a span for a navigation.
608608
* @returns {() => void} A function that, when executed, removes the registered callback.
609609
*/
610-
public on(hook: 'startNavigationSpan', callback: (options: StartSpanOptions) => void): () => void;
610+
public on(
611+
hook: 'startNavigationSpan',
612+
callback: (options: StartSpanOptions, navigationOptions?: { isRedirect?: boolean }) => void,
613+
): () => void;
611614

612615
/**
613616
* A hook for GraphQL client integration to enhance a span with request data.
@@ -782,7 +785,11 @@ export abstract class Client<O extends ClientOptions = ClientOptions> {
782785
/**
783786
* Emit a hook event for browser tracing integrations to trigger a span for a navigation.
784787
*/
785-
public emit(hook: 'startNavigationSpan', options: StartSpanOptions): void;
788+
public emit(
789+
hook: 'startNavigationSpan',
790+
options: StartSpanOptions,
791+
navigationOptions?: { isRedirect?: boolean },
792+
): void;
786793

787794
/**
788795
* Emit a hook event for GraphQL client integration to enhance a span with request data.

0 commit comments

Comments
 (0)