diff --git a/CHANGELOG.md b/CHANGELOG.md index 68fb27ce580c..38995dbab4e1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,7 @@ Work in this release was contributed by @psh4607, @thijsw, @trinitiwowka, @nehaprasad-dev, @JealousGx, @Jxxunnn, @eddie333016, @davidmurdoch, @yashschandra, @atharv-sys32, @AG0708, @birkskyum, @mkly, @mcbbugu, @suhailopensource, @zkasuran, @mohd-akram, @RealBhupesh, @halillusion, @psang39, @hafzism, @JosephDoUrden, @Tyagiquamar, @Andarist, @msnelling, and @oesnuj. Thank you for your contributions! +- ref(browser)!: LCP and CLS spans no longer set `browser.web_vital.lcp.report_event` and `browser.web_vital.cls.report_event`. With per-navigation web vitals (the default) the attribute was already never set; it is now also gone when `softNavigations` and `bfcacheNavigations` are turned off. When the values are finalized is unchanged. - feat(browser)!: `browser.navigation.type` on web vital and bfcache navigation spans now carries the navigation type exactly as web-vitals reports it. `bfcache` is now `back-forward-cache`, and a back/forward navigation that missed the bfcache (`back-forward`) or a discarded-tab restore (`restore`) is no longer folded into `navigate`. Update any dashboards or alerts filtering on `bfcache`. - feat(core): Add `createFetchIntegration`, the shared implementation behind the global-`fetch` integrations in `@sentry/bun`, `@sentry/cloudflare`, `@sentry/deno` and `@sentry/vercel-edge`. Those four packages carried four copies of it; they now share one. Two changes come out of that: - All four gain a `tracePropagation` option (default `true`). Turn it off to stop injecting `sentry-trace` and `baggage` without also turning off spans. To scope propagation to specific URLs, keep using `tracePropagationTargets` in the client options. diff --git a/MIGRATION.md b/MIGRATION.md index bc8e4e35c9cb..d67500ae912a 100644 --- a/MIGRATION.md +++ b/MIGRATION.md @@ -617,6 +617,14 @@ Sentry.init({ }); ``` +### Web vital spans no longer carry a report event + +Affected SDKs: All SDKs running in the browser. + +LCP and CLS spans no longer set `browser.web_vital.lcp.report_event` and `browser.web_vital.cls.report_event`. The attribute recorded whether the SDK finalized the page load's value on `pagehide` or at the first `navigation`. With per-navigation reporting (the default, see above) `web-vitals` decides when a value is final and the attribute was already never set, so it only remained for setups that turn per-navigation reporting off. + +When the values are finalized is unchanged. If you have searches or dashboards keyed on the attribute, remove the filter. + ### `DOMException.code` is no longer set as a tag Affected SDKs: All SDKs running in the browser. diff --git a/packages/browser-utils/src/web-vitals/emitSpan.ts b/packages/browser-utils/src/web-vitals/emitSpan.ts index 890de057b6a6..7294b5c8d4a5 100644 --- a/packages/browser-utils/src/web-vitals/emitSpan.ts +++ b/packages/browser-utils/src/web-vitals/emitSpan.ts @@ -19,7 +19,6 @@ import { } from '@sentry/conventions/attributes'; import { WINDOW } from '../types'; import type { MetricNavigationType } from '../instrumentation/performanceObserver'; -import type { WebVitalReportEvent } from './reportEvents'; // 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 @@ -48,7 +47,6 @@ interface WebVitalSpanOptions { value: number; attributes?: SpanAttributes; parentSpan?: Span; - reportEvent?: WebVitalReportEvent; startTime: number; endTime?: number; /** Set when the vital was reported for a soft navigation rather than the initial page load. */ @@ -78,7 +76,6 @@ export function _emitWebVitalSpan(options: WebVitalSpanOptions): void { value, attributes: passedAttributes, parentSpan, - reportEvent, startTime, endTime, standalone, @@ -111,10 +108,6 @@ export function _emitWebVitalSpan(options: WebVitalSpanOptions): void { attributes['sentry.pageload.span_id'] = parentSpan.spanContext().spanId; } - if (reportEvent) { - attributes[`browser.web_vital.${metricName}.report_event`] = reportEvent; - } - if (softNavigationId != null) { attributes[BROWSER_NAVIGATION_ID] = softNavigationId; } diff --git a/packages/browser-utils/src/web-vitals/reportEvents.ts b/packages/browser-utils/src/web-vitals/reportEvents.ts index 00ce84bf9a8d..3a1711a81bc1 100644 --- a/packages/browser-utils/src/web-vitals/reportEvents.ts +++ b/packages/browser-utils/src/web-vitals/reportEvents.ts @@ -1,8 +1,6 @@ import type { Client, Span } from '@sentry/core'; import { onHidden } from './utils'; -export type WebVitalReportEvent = 'pagehide' | 'navigation'; - /** * Listens for events on which we want to collect a previously accumulated web vital value. * Currently, this includes: @@ -10,35 +8,30 @@ export type WebVitalReportEvent = 'pagehide' | 'navigation'; * - pagehide (i.e. user minimizes browser window, hides tab, etc) * - soft navigation (we only care about the vital of the initially loaded route) * - * As a "side-effect", this function will also collect the span id of the pageload span. + * As a "side-effect", this function will also collect the pageload span. * - * @param collectorCallback the callback to be called when the first of these events is triggered. Parameters: - * - event: the event that triggered the reporting of the web vital value. - * - pageloadSpanId: the span id of the pageload span. This is used to link the web vital span to the pageload span. - * - pageloadSpan: the pageload span instance. This is used for full access to the pageload span for span streaming. + * @param collectorCallback the callback to be called when the first of these events is triggered. It is passed the + * pageload span, which the web vital span is parented to. */ -export function listenForWebVitalReportEvents( - client: Client, - collectorCallback: (event: WebVitalReportEvent, pageloadSpanId: string, pageloadSpan?: Span) => void, -) { +export function listenForWebVitalReportEvents(client: Client, collectorCallback: (pageloadSpan: Span) => void) { let pageloadSpan: Span | undefined; let collected = false; - function _runCollectorCallbackOnce(event: WebVitalReportEvent) { + function _runCollectorCallbackOnce() { if (!collected && pageloadSpan) { - collectorCallback(event, pageloadSpan.spanContext().spanId, pageloadSpan); + collectorCallback(pageloadSpan); } collected = true; } onHidden(() => { - _runCollectorCallbackOnce('pagehide'); + _runCollectorCallbackOnce(); }); const unsubscribeStartNavigation = client.on('beforeStartNavigationSpan', (_, options) => { // we only want to collect LCP if we actually navigate. Redirects should be ignored. if (!options?.isRedirect) { - _runCollectorCallbackOnce('navigation'); + _runCollectorCallbackOnce(); unsubscribeStartNavigation(); unsubscribeAfterStartPageLoadSpan(); } diff --git a/packages/browser-utils/src/web-vitals/spans.ts b/packages/browser-utils/src/web-vitals/spans.ts index 1996715d51cb..490999a976ee 100644 --- a/packages/browser-utils/src/web-vitals/spans.ts +++ b/packages/browser-utils/src/web-vitals/spans.ts @@ -24,7 +24,6 @@ import type { LargestContentfulPaint, LayoutShift } from './emitSpan'; import { BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes'; import { _emitWebVitalSpan } from './emitSpan'; import { isValidLcpMetric } from './lcp'; -import type { WebVitalReportEvent } from './reportEvents'; import { listenForWebVitalReportEvents } from './reportEvents'; import { getNavigationSpanForMetric } from './softNavs'; import { getBrowserPerformanceAPI, msToSec, supportsWebVital } from '../performance/utils'; @@ -125,7 +124,6 @@ export function trackLcpAsSpan(client: Client, perNavigation = false): void { metric.value, entry, parentSpan, - undefined, softNavigationId, metric.navigationType, metric.navigationStartTime, @@ -151,8 +149,8 @@ export function trackLcpAsSpan(client: Client, perNavigation = false): void { lcpEntry = entry; }, true); - listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => { - _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, reportEvent, undefined, lcpNavigationType); + listenForWebVitalReportEvents(client, pageloadSpan => { + _sendLcpSpan(lcpValue, lcpEntry, pageloadSpan, undefined, lcpNavigationType); cleanupLcpHandler(); }); } @@ -164,7 +162,6 @@ export function _sendLcpSpan( lcpValue: number, entry: LargestContentfulPaint | undefined, pageloadSpan?: Span, - reportEvent?: WebVitalReportEvent, softNavigationId?: number, navigationType?: MetricNavigationType, navigationStartTime?: number, @@ -202,7 +199,6 @@ export function _sendLcpSpan( value: lcpValue, attributes, parentSpan: pageloadSpan, - reportEvent, startTime, endTime, softNavigationId, @@ -225,7 +221,6 @@ export function trackClsAsSpan(client: Client, perNavigation = false): void { metric.value, entry, parentSpan, - undefined, softNavigationId, metric.navigationType, metric.navigationStartTime, @@ -251,8 +246,8 @@ export function trackClsAsSpan(client: Client, perNavigation = false): void { clsEntry = entry; }, true); - listenForWebVitalReportEvents(client, (reportEvent, _, pageloadSpan) => { - _sendClsSpan(clsValue, clsEntry, pageloadSpan, reportEvent, undefined, clsNavigationType); + listenForWebVitalReportEvents(client, pageloadSpan => { + _sendClsSpan(clsValue, clsEntry, pageloadSpan, undefined, clsNavigationType); cleanupClsHandler(); }); } @@ -264,7 +259,6 @@ export function _sendClsSpan( clsValue: number, entry: LayoutShift | undefined, pageloadSpan?: Span, - reportEvent?: WebVitalReportEvent, softNavigationId?: number, navigationType?: MetricNavigationType, navigationStartTime?: number, @@ -295,7 +289,6 @@ export function _sendClsSpan( value: clsValue, attributes, parentSpan: pageloadSpan, - reportEvent, startTime, softNavigationId, navigationType, diff --git a/packages/browser-utils/test/web-vitals/spans.test.ts b/packages/browser-utils/test/web-vitals/spans.test.ts index daad65d7b5cb..bd2b063d6be0 100644 --- a/packages/browser-utils/test/web-vitals/spans.test.ts +++ b/packages/browser-utils/test/web-vitals/spans.test.ts @@ -282,26 +282,6 @@ describe('_emitWebVitalSpan', () => { ); }); - it('includes reportEvent when provided', () => { - _emitWebVitalSpan({ - name: 'Test', - op: 'ui.webvital.cls', - origin: 'auto.http.browser.cls', - metricName: 'cls', - value: 0.1, - reportEvent: 'pagehide', - startTime: 1.0, - }); - - expect(SentryCoreBrowser.startInactiveSpan).toHaveBeenCalledWith( - expect.objectContaining({ - attributes: expect.objectContaining({ - 'browser.web_vital.cls.report_event': 'pagehide', - }), - }), - ); - }); - it('merges additional attributes', () => { _emitWebVitalSpan({ name: 'Test', @@ -421,7 +401,7 @@ describe('_sendLcpSpan', () => { const mockPageloadSpan = createMockPageloadSpan('pageload-123'); - _sendLcpSpan(250, mockEntry, mockPageloadSpan as any, 'pagehide'); + _sendLcpSpan(250, mockEntry, mockPageloadSpan as any); expect(SentryCoreBrowser.startInactiveSpan).toHaveBeenCalledWith( expect.objectContaining({ @@ -437,7 +417,6 @@ describe('_sendLcpSpan', () => { 'browser.web_vital.lcp.load_time': 100, 'browser.web_vital.lcp.render_time': 150, 'browser.web_vital.lcp.size': 50000, - 'browser.web_vital.lcp.report_event': 'pagehide', 'sentry.transaction': 'test-route', 'sentry.segment.name': 'test-route', }), @@ -464,7 +443,7 @@ describe('_sendLcpSpan', () => { it('lasts the reported value when there is no entry to end at', () => { // A soft navigation 2000ms into the page. Ending at the time origin would put the end before // the start. - _sendLcpSpan(250, undefined, undefined, undefined, 2, 'soft-navigation', 2000); + _sendLcpSpan(250, undefined, undefined, 2, 'soft-navigation', 2000); expect(SentryCoreBrowser.startInactiveSpan).toHaveBeenCalledWith(expect.objectContaining({ startTime: 3 })); expect(mockSpan.end).toHaveBeenCalledWith(3.25); @@ -530,7 +509,7 @@ describe('_sendClsSpan', () => { const mockPageloadSpan = createMockPageloadSpan('pageload-789'); - _sendClsSpan(0.1, mockEntry, mockPageloadSpan as any, 'navigation'); + _sendClsSpan(0.1, mockEntry, mockPageloadSpan as any); expect(SentryCoreBrowser.startInactiveSpan).toHaveBeenCalledWith( expect.objectContaining({ @@ -541,7 +520,6 @@ describe('_sendClsSpan', () => { 'sentry.pageload.span_id': 'pageload-789', 'browser.web_vital.cls.source.1': '