Skip to content

Commit f42b945

Browse files
committed
feat(browser): option to ignore certain resource types
1 parent 76b7f3a commit f42b945

File tree

5 files changed

+107
-3
lines changed

5 files changed

+107
-3
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
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+
ignoreResourceSpans: ['resource.script']
10+
}),
11+
],
12+
tracesSampleRate: 1,
13+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import type { Route } from '@playwright/test';
2+
import { expect } from '@playwright/test';
3+
import type { Event } from '@sentry/core';
4+
import { sentryTest } from '../../../../utils/fixtures';
5+
import { getFirstSentryEnvelopeRequest } from '../../../../utils/helpers';
6+
7+
sentryTest(
8+
'should allow specific types of resource spans to be ignored.',
9+
async ({ getLocalTestUrl, page }) => {
10+
await page.route('**/path/to/script.js', (route: Route) =>
11+
route.fulfill({ path: `${__dirname}/assets/script.js` }),
12+
);
13+
14+
const url = await getLocalTestUrl({ testDir: __dirname });
15+
16+
const eventData = await getFirstSentryEnvelopeRequest<Event>(page, url);
17+
const uiSpans = eventData.spans?.filter(({ op }) => op?.startsWith('resource.script'));
18+
19+
expect(uiSpans?.length).toBe(0);
20+
},
21+
);

packages/browser-utils/src/metrics/browserMetrics.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -300,6 +300,13 @@ interface AddPerformanceEntriesOptions {
300300
* sent as a standalone span instead.
301301
*/
302302
recordClsOnPageloadSpan: boolean;
303+
304+
/**
305+
* Resource spans matching strings in the array will not be emitted.
306+
*
307+
* Default: []
308+
*/
309+
ignoreResourceSpans: Array<string>;
303310
}
304311

305312
/** Add performance related spans to a transaction */
@@ -355,7 +362,7 @@ export function addPerformanceEntries(span: Span, options: AddPerformanceEntries
355362
break;
356363
}
357364
case 'resource': {
358-
_addResourceSpans(span, entry as PerformanceResourceTiming, entry.name, startTime, duration, timeOrigin);
365+
_addResourceSpans(span, entry as PerformanceResourceTiming, entry.name, startTime, duration, timeOrigin, options.ignoreResourceSpans);
359366
break;
360367
}
361368
// Ignore other entry types.
@@ -568,13 +575,19 @@ export function _addResourceSpans(
568575
startTime: number,
569576
duration: number,
570577
timeOrigin: number,
578+
ignoreResourceSpans?: Array<string>
571579
): void {
572580
// we already instrument based on fetch and xhr, so we don't need to
573581
// duplicate spans here.
574582
if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {
575583
return;
576584
}
577585

586+
const op = entry.initiatorType ? `resource.${entry.initiatorType}` : 'resource.other';
587+
if (ignoreResourceSpans?.includes(op)) {
588+
return;
589+
}
590+
578591
const parsedUrl = parseUrl(resourceUrl);
579592

580593
const attributes: SpanAttributes = {
@@ -616,7 +629,7 @@ export function _addResourceSpans(
616629

617630
startAndEndSpan(span, startTimestamp, endTimestamp, {
618631
name: resourceUrl.replace(WINDOW.location.origin, ''),
619-
op: entry.initiatorType ? `resource.${entry.initiatorType}` : 'resource.other',
632+
op,
620633
attributes,
621634
});
622635
}

packages/browser-utils/test/browser/browserMetrics.test.ts

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -271,6 +271,54 @@ describe('_addResourceSpans', () => {
271271
}
272272
});
273273

274+
it('allows resource spans to be ignored via ignoreResourceSpans', () => {
275+
const spans: Span[] = [];
276+
const ignoredResourceSpans = [
277+
'resource.other',
278+
'resource.script'
279+
];
280+
281+
getClient()?.on('spanEnd', span => {
282+
spans.push(span);
283+
});
284+
285+
const table = [
286+
{
287+
initiatorType: undefined,
288+
op: 'resource.other',
289+
},
290+
{
291+
initiatorType: 'css',
292+
op: 'resource.css',
293+
},
294+
{
295+
initiatorType: 'css',
296+
op: 'resource.css',
297+
},
298+
{
299+
initiatorType: 'image',
300+
op: 'resource.image',
301+
},
302+
{
303+
initiatorType: 'script',
304+
op: 'resource.script',
305+
},
306+
];
307+
for (const row of table) {
308+
const { initiatorType } = row;
309+
const entry = mockPerformanceResourceTiming({
310+
initiatorType,
311+
nextHopProtocol: 'http/1.1',
312+
});
313+
_addResourceSpans(span, entry, 'https://example.com/assets/to/me', 123, 234, 465, ignoredResourceSpans);
314+
}
315+
expect(spans).toHaveLength(table.length - ignoredResourceSpans.length);
316+
const spanOps = new Set(spans.map((s) => {
317+
return spanToJSON(s).op;
318+
}));
319+
expect(spanOps).toEqual(new Set(['resource.css', 'resource.image']));
320+
});
321+
274322
it('allows for enter size of 0', () => {
275323
const spans: Span[] = [];
276324

packages/browser/src/tracing/browserTracingIntegration.ts

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,13 @@ export interface BrowserTracingOptions {
144144
*/
145145
enableHTTPTimings: boolean;
146146

147+
/**
148+
* Resource spans matching strings in the array will not be emitted.
149+
*
150+
* Default: []
151+
*/
152+
ignoreResourceSpans: Array<string>;
153+
147154
/**
148155
* Link the currently started trace to a previous trace (e.g. a prior pageload, navigation or
149156
* manually started span). When enabled, this option will allow you to navigate between traces
@@ -226,6 +233,7 @@ const DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {
226233
enableLongTask: true,
227234
enableLongAnimationFrame: true,
228235
enableInp: true,
236+
ignoreResourceSpans: [],
229237
linkPreviousTrace: 'in-memory',
230238
consistentTraceSampling: false,
231239
_experiments: {},
@@ -268,6 +276,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
268276
trackFetchStreamPerformance,
269277
shouldCreateSpanForRequest,
270278
enableHTTPTimings,
279+
ignoreResourceSpans,
271280
instrumentPageLoad,
272281
instrumentNavigation,
273282
linkPreviousTrace,
@@ -310,7 +319,7 @@ export const browserTracingIntegration = ((_options: Partial<BrowserTracingOptio
310319
// This will generally always be defined here, because it is set in `setup()` of the integration
311320
// but technically, it is optional, so we guard here to be extra safe
312321
_collectWebVitals?.();
313-
addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans });
322+
addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans, ignoreResourceSpans });
314323
setActiveIdleSpan(client, undefined);
315324

316325
// A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.

0 commit comments

Comments
 (0)