Skip to content

Commit d2a9826

Browse files
authored
feat(browser): Add http.response_delivery_type attribute to resource spans (#14056)
Add the `deliveryType` field of a `ResourcePeformanceEntry` to our `op: resource` spans. This [attribute](https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType) can give a definitive answer if a resource was retrieved from the browser cache or if the request was actually made to the resource src.
1 parent a15ce30 commit d2a9826

File tree

4 files changed

+63
-0
lines changed

4 files changed

+63
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
async function run() {
2+
Sentry.startSpan({ name: 'parent_span' }, () => {
3+
Sentry.startSpan({ name: 'child_span', attributes: { someAttribute: '' } }, () => {
4+
// whatever a user would do here
5+
});
6+
});
7+
}
8+
9+
(async () => {
10+
await run();
11+
})();
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
import { expect } from '@playwright/test';
2+
3+
import { sentryTest } from '../../../../utils/fixtures';
4+
import {
5+
envelopeRequestParser,
6+
shouldSkipTracingTest,
7+
waitForTransactionRequestOnUrl,
8+
} from '../../../../utils/helpers';
9+
10+
sentryTest('sends an empty string attribute', async ({ getLocalTestPath, page }) => {
11+
if (shouldSkipTracingTest()) {
12+
sentryTest.skip();
13+
}
14+
15+
const url = await getLocalTestPath({ testDir: __dirname });
16+
const req = await waitForTransactionRequestOnUrl(page, url);
17+
const transaction = envelopeRequestParser(req);
18+
19+
const childSpan = transaction.spans?.[0];
20+
expect(childSpan?.data?.someAttribute).toBe('');
21+
});

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

+5
Original file line numberDiff line numberDiff line change
@@ -513,6 +513,7 @@ export interface ResourceEntry extends Record<string, unknown> {
513513
encodedBodySize?: number;
514514
decodedBodySize?: number;
515515
renderBlockingStatus?: string;
516+
deliveryType?: string;
516517
}
517518

518519
/** Create resource-related spans */
@@ -539,6 +540,10 @@ export function _addResourceSpans(
539540
setResourceEntrySizeData(attributes, entry, 'encodedBodySize', 'http.response_content_length');
540541
setResourceEntrySizeData(attributes, entry, 'decodedBodySize', 'http.decoded_response_content_length');
541542

543+
if (entry.deliveryType != null) {
544+
attributes['http.response_delivery_type'] = entry.deliveryType;
545+
}
546+
542547
if ('renderBlockingStatus' in entry) {
543548
attributes['resource.render_blocking_status'] = entry.renderBlockingStatus;
544549
}

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

+26
Original file line numberDiff line numberDiff line change
@@ -338,6 +338,32 @@ describe('_addResourceSpans', () => {
338338
}),
339339
);
340340
});
341+
342+
// resource delivery types: https://developer.mozilla.org/en-US/docs/Web/API/PerformanceResourceTiming/deliveryType
343+
// i.e. better but not yet widely supported way to check for browser cache hit
344+
it.each(['cache', 'navigational-prefetch', ''])(
345+
'attaches delivery type ("%s") to resource spans if available',
346+
deliveryType => {
347+
const spans: Span[] = [];
348+
349+
getClient()?.on('spanEnd', span => {
350+
spans.push(span);
351+
});
352+
353+
const entry: ResourceEntry = {
354+
initiatorType: 'css',
355+
transferSize: 0,
356+
encodedBodySize: 0,
357+
decodedBodySize: 0,
358+
deliveryType,
359+
};
360+
361+
_addResourceSpans(span, entry, resourceEntryName, 100, 23, 345);
362+
363+
expect(spans).toHaveLength(1);
364+
expect(spanToJSON(spans[0]!).data).toMatchObject({ 'http.response_delivery_type': deliveryType });
365+
},
366+
);
341367
});
342368

343369
const setGlobalLocation = (location: Location) => {

0 commit comments

Comments
 (0)