Skip to content

Commit 69c65ba

Browse files
msonnbclaude
andcommitted
feat(browser)!: Use browser.paint span op for paint entries
`paint` is not a registered op; `browser.paint` is. Only affects tracing spans — Session Replay performance entries are unchanged. Ref: JS-3105 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
1 parent 62b0ee0 commit 69c65ba

4 files changed

Lines changed: 6 additions & 4 deletions

File tree

MIGRATION.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -268,6 +268,7 @@ Span operations (`sentry.op`) were aligned with the values defined in `@sentry/c
268268
- `@sentry/ember`:
269269
- Route hook spans from `instrumentRoutePerformance` now use `function` instead of `ui.ember.route.<hook>`. The hook name is available on the new `code.function.name` and `ember.route.hook` attributes.
270270
- Runloop spans now use `ui.task` instead of `ui.ember.runloop.<queue>`. The queue is available on the new `ember.runloop.queue` attribute.
271+
- Browser SDKs: Paint spans (`first-paint`, `first-contentful-paint`) now use the registered `browser.paint` op instead of `paint`. This does not affect Session Replay, whose performance entries keep their own `paint` type.
271272

272273
If you reference these operations in dashboards, alerts, or `beforeSendSpan`, update them to the new values.
273274

dev-packages/browser-integration-tests/suites/tracing/metrics/web-vitals-fp-fcp/test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ sentryTest('should capture FP vital.', async ({ browserName, getLocalTestUrl, pa
1818
const fpSpan = eventData.spans?.filter(({ description }) => description === 'first-paint')[0];
1919

2020
expect(fpSpan).toBeDefined();
21-
expect(fpSpan?.op).toBe('paint');
21+
expect(fpSpan?.op).toBe('browser.paint');
2222
expect(fpSpan?.parent_span_id).toBe(eventData.contexts?.trace?.span_id);
2323
});
2424

@@ -36,6 +36,6 @@ sentryTest('should capture FCP vital.', async ({ getLocalTestUrl, page }) => {
3636
const fcpSpan = eventData.spans?.filter(({ description }) => description === 'first-contentful-paint')[0];
3737

3838
expect(fcpSpan).toBeDefined();
39-
expect(fcpSpan?.op).toBe('paint');
39+
expect(fcpSpan?.op).toBe('browser.paint');
4040
expect(fcpSpan?.parent_span_id).toBe(eventData.contexts?.trace?.span_id);
4141
});

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import { getNavigationEntry } from './web-vitals/lib/getNavigationEntry';
2929
import { getVisibilityWatcher } from './web-vitals/lib/getVisibilityWatcher';
3030
import { DEBUG_BUILD } from '../debug-build';
3131
import { URL_FULL } from '@sentry/conventions/attributes';
32+
import { BROWSER_BROWSER_PAINT_SPAN_OP } from '@sentry/conventions/op';
3233
interface NavigatorNetworkInformation {
3334
readonly connection?: NetworkInformation;
3435
}
@@ -561,7 +562,7 @@ export function _addMeasureSpans(
561562
if (measureStartTimestamp <= measureEndTimestamp) {
562563
startAndEndSpan(span, measureStartTimestamp, measureEndTimestamp, {
563564
name: entry.name,
564-
op: entry.entryType,
565+
op: entry.entryType === 'paint' ? BROWSER_BROWSER_PAINT_SPAN_OP : entry.entryType,
565566
attributes,
566567
});
567568
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -280,7 +280,7 @@ describe('_addMeasureSpans', () => {
280280
expect.objectContaining({ description: 'measure-pass', op: 'measure' }),
281281
expect.objectContaining({ description: 'mark-pass', op: 'mark' }),
282282
// name matches but type is not (mark|measure) => should not be ignored
283-
expect.objectContaining({ description: 'mark-ignore', op: 'paint' }),
283+
expect.objectContaining({ description: 'mark-ignore', op: 'browser.paint' }),
284284
]),
285285
);
286286
});

0 commit comments

Comments
 (0)