diff --git a/CHANGELOG.md b/CHANGELOG.md index 68fb27ce580c..2b8c43f762e6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,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! - 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(browser): The pageload span now carries `browser.navigation.type`, the navigation type web-vitals reported TTFB and FCP for. Those vitals, and FP, are attributes of the pageload span rather than spans of their own, so until now there was no navigation type to read them against. - 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. - Integration options now follow the client. Previously a second `Sentry.init()` in the same process silently reused the options of the first one. diff --git a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts index a16b6839571f..0a5434324908 100644 --- a/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts +++ b/dev-packages/browser-integration-tests/suites/tracing/browserTracingIntegration/pageload-streamed/test.ts @@ -8,6 +8,7 @@ import { SEMANTIC_ATTRIBUTE_SENTRY_SDK_INTEGRATIONS, } from '@sentry/core'; import { + BROWSER_NAVIGATION_TYPE, SENTRY_SEGMENT_NAME_SOURCE, SENTRY_SEGMENT_ID, SENTRY_SEGMENT_NAME, @@ -125,6 +126,10 @@ sentryTest( type: expect.stringMatching(/^(integer)|(double)$/), value: expect.any(Number), }, + [BROWSER_NAVIGATION_TYPE]: { + type: 'string', + value: 'navigate', + }, }), 'sentry.idle_span_finish_reason': { type: 'string', diff --git a/packages/browser-utils/src/web-vitals/tracking.ts b/packages/browser-utils/src/web-vitals/tracking.ts index 4e1af199884c..a8dc27fde867 100644 --- a/packages/browser-utils/src/web-vitals/tracking.ts +++ b/packages/browser-utils/src/web-vitals/tracking.ts @@ -1,8 +1,9 @@ import type { Client, Measurements, Span } from '@sentry/core'; import { browserPerformanceTimeOrigin, debug, setMeasurement, spanToJSON } from '@sentry/core'; -import { SENTRY_OP } from '@sentry/conventions/attributes'; +import { BROWSER_NAVIGATION_TYPE, SENTRY_OP } from '@sentry/conventions/attributes'; import { DEBUG_BUILD } from '../debug-build'; import { htmlTreeAsString } from '../htmlTreeAsString'; +import type { MetricNavigationType } from '../instrumentation/performanceObserver'; import { addClsInstrumentationHandler, addFcpInstrumentationHandler, @@ -17,6 +18,7 @@ import { getActivationStart, getNavigationEntry, getVisibilityWatcher } from './ let _measurements: Measurements = {}; let _lcpEntry: LargestContentfulPaint | undefined; let _clsEntry: LayoutShift | undefined; +let _navigationType: MetricNavigationType | undefined; interface StartTrackingWebVitalsOptions { trackCls: boolean; @@ -83,6 +85,8 @@ function _trackLCP(): () => void { function _trackTtfb(): () => void { return addTtfbInstrumentationHandler(({ metric }) => { + _navigationType = metric.navigationType; + const entry = metric.entries[metric.entries.length - 1]; if (!entry) { return; @@ -95,6 +99,7 @@ function _trackTtfb(): () => void { /** Starts tracking the First Contentful Paint on the current page. */ function _trackFcp(): () => void { return addFcpInstrumentationHandler(({ metric }) => { + _navigationType = metric.navigationType; _measurements['fcp'] = { value: metric.value, unit: 'millisecond' }; }); } @@ -201,6 +206,12 @@ export function addWebVitalsToSpan(span: Span, options: AddWebVitalsToSpanOption _setWebVitalAttributes(span, options); } + // TTFB, FP and FCP are attributes of this span rather than spans of their own, so the navigation + // type they were measured on is reported here for them to be read against. + if (_navigationType) { + span.setAttribute(BROWSER_NAVIGATION_TYPE, _navigationType); + } + // Set timeOrigin which denotes the timestamp which to base the LCP/FCP/FP/TTFB measurements on span.setAttribute(spanStreamingEnabled ? 'browser.performance.time_origin' : 'performance.timeOrigin', timeOrigin); @@ -222,6 +233,7 @@ export function addWebVitalsToSpan(span: Span, options: AddWebVitalsToSpanOption function resetWebVitalState(): void { _lcpEntry = undefined; _clsEntry = undefined; + _navigationType = undefined; _measurements = {}; } diff --git a/packages/browser-utils/test/web-vitals/tracking-fp-fcp-prerender.test.ts b/packages/browser-utils/test/web-vitals/tracking-fp-fcp-prerender.test.ts index f3dcddc02997..40a4e24416f8 100644 --- a/packages/browser-utils/test/web-vitals/tracking-fp-fcp-prerender.test.ts +++ b/packages/browser-utils/test/web-vitals/tracking-fp-fcp-prerender.test.ts @@ -124,5 +124,6 @@ describe('startTrackingWebVitals', () => { expect(spanToJSON(pageloadSpan).attributes['browser.web_vital.fp.value']).toBe(12); expect(spanToJSON(pageloadSpan).attributes['browser.web_vital.fcp.value']).toBe(18); + expect(spanToJSON(pageloadSpan).attributes['browser.navigation.type']).toBe('prerender'); }); }); diff --git a/packages/browser-utils/test/web-vitals/tracking-fp-fcp.test.ts b/packages/browser-utils/test/web-vitals/tracking-fp-fcp.test.ts index 3b64b031f67c..3a8c43c601a2 100644 --- a/packages/browser-utils/test/web-vitals/tracking-fp-fcp.test.ts +++ b/packages/browser-utils/test/web-vitals/tracking-fp-fcp.test.ts @@ -90,5 +90,6 @@ describe('startTrackingWebVitals', () => { expect(spanToJSON(pageloadSpan).attributes['browser.web_vital.fp.value']).toBe(12); expect(spanToJSON(pageloadSpan).attributes['browser.web_vital.fcp.value']).toBe(18); + expect(spanToJSON(pageloadSpan).attributes['browser.navigation.type']).toBe('navigate'); }); });