Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ sentryTest('captures CLS as a streamed span with source attributes', async ({ ge
expect(clsSpan.attributes?.['sentry.exclusive_time']).toEqual({ type: 'integer', value: 0 });
expect(clsSpan.attributes?.['user_agent.original']?.value).toEqual(expect.stringContaining('Chrome'));

// Check the CLS span carries the transaction/segment name it belongs to
expect(clsSpan.attributes?.['sentry.transaction']).toEqual({ type: 'string', value: '/index.html' });
expect(clsSpan.attributes?.['sentry.segment.name']).toEqual({ type: 'string', value: '/index.html' });

// Check browser.web_vital.cls.source attributes
expect(clsSpan.attributes?.['browser.web_vital.cls.source.1']?.value).toEqual(
expect.stringContaining('body > div#content > p'),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ sentryTest('captures INP click as a streamed span', async ({ getLocalTestUrl, pa
expect(inpSpan.attributes?.['sentry.origin']).toEqual({ type: 'string', value: 'auto.http.browser.inp' });
expect(inpSpan.attributes?.['user_agent.original']?.value).toEqual(expect.stringContaining('Chrome'));

// Check the INP span carries the transaction/segment name it belongs to
expect(inpSpan.attributes?.['sentry.transaction']).toEqual({ type: 'string', value: '/index.html' });
expect(inpSpan.attributes?.['sentry.segment.name']).toEqual({ type: 'string', value: '/index.html' });

const inpValue = inpSpan.attributes?.['browser.web_vital.inp.value']?.value as number;
expect(inpValue).toBeGreaterThan(0);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ sentryTest('captures LCP as a streamed span with element attributes', async ({ g
expect(lcpSpan.attributes?.['sentry.exclusive_time']).toEqual({ type: 'integer', value: 0 });
expect(lcpSpan.attributes?.['user_agent.original']?.value).toEqual(expect.stringContaining('Chrome'));

// Check the LCP span carries the transaction/segment name it belongs to
expect(lcpSpan.attributes?.['sentry.transaction']).toEqual({ type: 'string', value: '/index.html' });
expect(lcpSpan.attributes?.['sentry.segment.name']).toEqual({ type: 'string', value: '/index.html' });

// Check browser.web_vital.lcp.* attributes
expect(lcpSpan.attributes?.['browser.web_vital.lcp.element']?.value).toEqual(expect.stringContaining('body > img'));
expect(lcpSpan.attributes?.['browser.web_vital.lcp.url']?.value).toBe(
Expand Down
3 changes: 2 additions & 1 deletion packages/browser-utils/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@
"access": "public"
},
"dependencies": {
"@sentry/core": "10.64.0"
"@sentry/core": "10.64.0",
"@sentry/conventions": "^0.15.1"
},
"scripts": {
"build": "run-p build:transpile build:types",
Expand Down
9 changes: 7 additions & 2 deletions packages/browser-utils/src/metrics/webVitalSpans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { isValidLcpMetric } from './lcp';
import type { WebVitalReportEvent } from './utils';
import { getBrowserPerformanceAPI, listenForWebVitalReportEvents, msToSec, supportsWebVital } from './utils';
import type { PerformanceEventTiming } from './instrument';
import { SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION } from '@sentry/conventions/attributes';

// Locally-defined interfaces to avoid leaking bare global type references into the
// generated .d.ts. The `declare global` augmentations in web-vitals/types.ts make these
Expand Down Expand Up @@ -79,7 +80,9 @@ export function _emitWebVitalSpan(options: WebVitalSpanOptions): void {
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: op,
[SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: 0,
[`browser.web_vital.${metricName}.value`]: value,
'sentry.transaction': routeName,
// oxlint-disable-next-line typescript-eslint/no-deprecated
[SENTRY_TRANSACTION]: routeName,
[SENTRY_SEGMENT_NAME]: routeName,
// Web vital score calculation relies on the user agent
'user_agent.original': WINDOW.navigator?.userAgent,
...passedAttributes,
Expand Down Expand Up @@ -304,7 +307,9 @@ export function _sendInpSpan(inpValue: number, entry: PerformanceEventTiming): v
value: inpValue,
attributes: {
[SEMANTIC_ATTRIBUTE_EXCLUSIVE_TIME]: entry.duration,
'sentry.transaction': routeName,
// oxlint-disable-next-line typescript-eslint/no-deprecated
[SENTRY_TRANSACTION]: routeName,
[SENTRY_SEGMENT_NAME]: routeName,
Comment thread
Lms24 marked this conversation as resolved.
},
startTime,
endTime: startTime + duration,
Expand Down
5 changes: 5 additions & 0 deletions packages/browser-utils/test/metrics/webVitalSpans.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ describe('_emitWebVitalSpan', () => {
'sentry.exclusive_time': 0,
'browser.web_vital.lcp.value': 100,
'sentry.transaction': 'test-transaction',
'sentry.segment.name': 'test-transaction',
'user_agent.original': 'test-user-agent',
},
startTime: 1.5,
Expand Down Expand Up @@ -256,6 +257,7 @@ describe('_sendLcpSpan', () => {
'browser.web_vital.lcp.size': 50000,
'browser.web_vital.lcp.report_event': 'pagehide',
'sentry.transaction': 'test-route',
'sentry.segment.name': 'test-route',
}),
startTime: 1, // timeOrigin: 1000 / 1000
parentSpan: mockPageloadSpan,
Expand Down Expand Up @@ -348,6 +350,7 @@ describe('_sendClsSpan', () => {
'browser.web_vital.cls.source.2': '<span>',
'browser.web_vital.cls.report_event': 'navigation',
'sentry.transaction': 'test-route',
'sentry.segment.name': 'test-route',
}),
parentSpan: mockPageloadSpan,
}),
Expand Down Expand Up @@ -414,6 +417,7 @@ describe('_sendInpSpan', () => {
'sentry.op': 'ui.interaction.click',
'sentry.exclusive_time': 120,
'sentry.transaction': 'test-route',
'sentry.segment.name': 'test-route',
}),
}),
);
Expand Down Expand Up @@ -472,6 +476,7 @@ describe('_sendInpSpan', () => {
name: 'body > CachedButton',
attributes: expect.objectContaining({
'sentry.transaction': 'cached-route',
'sentry.segment.name': 'cached-route',
}),
parentSpan: mockRootSpan,
}),
Expand Down
Loading