diff --git a/packages/browser-utils/src/index.ts b/packages/browser-utils/src/index.ts index 733129d52f5f..7c3b08c40e3b 100644 --- a/packages/browser-utils/src/index.ts +++ b/packages/browser-utils/src/index.ts @@ -33,8 +33,6 @@ export { userTimingIntegration } from './performance/userTiming'; export { extractNetworkProtocol } from './performance/utils'; -export { BROWSER_NAVIGATION_TYPE_ATTRIBUTE } from './web-vitals/emitSpan'; - export { trackClsAsSpan, trackInpAsSpan, trackLcpAsSpan } from './web-vitals/spans'; export { whenIdleOrHidden } from './web-vitals/utils'; diff --git a/packages/browser-utils/src/web-vitals/emitSpan.ts b/packages/browser-utils/src/web-vitals/emitSpan.ts index b930d628829a..3a32e1eddd3c 100644 --- a/packages/browser-utils/src/web-vitals/emitSpan.ts +++ b/packages/browser-utils/src/web-vitals/emitSpan.ts @@ -10,6 +10,8 @@ import { } from '@sentry/core'; import { startInactiveSpan } from '@sentry/core/browser'; import { + BROWSER_NAVIGATION_ID, + BROWSER_NAVIGATION_TYPE, SENTRY_REPLAY_ID, SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION, @@ -18,11 +20,6 @@ import { import { WINDOW } from '../types'; import type { MetricNavigationType } from '../instrumentation/performanceObserver'; import type { WebVitalReportEvent } from './reportEvents'; -import { SOFT_NAVIGATION_ID_ATTRIBUTE } from './softNavs'; - -// TODO(conventions): replace with `BROWSER_NAVIGATION_TYPE` from `@sentry/conventions/attributes` -// once https://github.com/getsentry/sentry-conventions/pull/600 is released. -export const BROWSER_NAVIGATION_TYPE_ATTRIBUTE = 'browser.navigation.type'; // web-vitals reports a wider set of navigation types than the attribute defines. Only the states // Navigation Timing cannot express keep their own value; every ordinary document navigation folds @@ -133,11 +130,11 @@ export function _emitWebVitalSpan(options: WebVitalSpanOptions): void { } if (softNavigationId != null) { - attributes[SOFT_NAVIGATION_ID_ATTRIBUTE] = softNavigationId; + attributes[BROWSER_NAVIGATION_ID] = softNavigationId; } if (navigationType) { - attributes[BROWSER_NAVIGATION_TYPE_ATTRIBUTE] = toBrowserNavigationType(navigationType); + attributes[BROWSER_NAVIGATION_TYPE] = toBrowserNavigationType(navigationType); } // A standalone span is sent as a plain v2 span without running the `processSpan` hooks (see diff --git a/packages/browser-utils/src/web-vitals/softNavs.ts b/packages/browser-utils/src/web-vitals/softNavs.ts index 2b3ef135f02b..9e397a60d4f6 100644 --- a/packages/browser-utils/src/web-vitals/softNavs.ts +++ b/packages/browser-utils/src/web-vitals/softNavs.ts @@ -1,17 +1,11 @@ import type { Client, Span } from '@sentry/core'; import { debug, LRUMap, SEMANTIC_ATTRIBUTE_SENTRY_OP, spanToJSON } from '@sentry/core'; +import { BROWSER_NAVIGATION_ID } from '@sentry/conventions/attributes'; import { DEBUG_BUILD } from '../debug-build'; import type { PerformanceSoftNavigation } from '../instrumentation/performanceObserver'; import { addPerformanceInstrumentationHandler, isPerformanceEventTiming } from '../instrumentation/performanceObserver'; import { WINDOW } from '../types'; -/** - * The browser's `navigationId` for the soft navigation a span belongs to. Set on the navigation - * span itself as well as on the web vital spans reported for it, so both sides of the correlation - * are visible in the product. - */ -export const SOFT_NAVIGATION_ID_ATTRIBUTE = 'browser.soft_navigation.id'; - /** * A page only ever needs its most recent navigations to still be joinable: web vitals for a soft * navigation are finalized at the next soft navigation or on pagehide, never later than that. @@ -146,7 +140,7 @@ export function startSoftNavigationCorrelation(client: Client): void { _navigationIdToNavigationSpan.set(entry.navigationId, span); // Best effort: the soft navigation entry usually lands well within the navigation span's idle // window, but if the span has already been sent this attribute is dropped. - span.setAttribute(SOFT_NAVIGATION_ID_ATTRIBUTE, entry.navigationId); + span.setAttribute(BROWSER_NAVIGATION_ID, entry.navigationId); } }); } diff --git a/packages/browser-utils/src/web-vitals/spans.ts b/packages/browser-utils/src/web-vitals/spans.ts index 95ef5a14978d..a3b1387f49b6 100644 --- a/packages/browser-utils/src/web-vitals/spans.ts +++ b/packages/browser-utils/src/web-vitals/spans.ts @@ -20,7 +20,8 @@ import { addLcpInstrumentationHandler, } from '../instrumentation/performanceObserver'; import type { LargestContentfulPaint, LayoutShift } from './emitSpan'; -import { BROWSER_NAVIGATION_TYPE_ATTRIBUTE, _emitWebVitalSpan } 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'; @@ -69,7 +70,7 @@ function trackWebVitalPerNavigation( // it has long ended and is no longer what is active. let bfcacheNavigationSpan: Span | undefined; client.on('spanStart', span => { - if (spanToJSON(span).attributes?.[BROWSER_NAVIGATION_TYPE_ATTRIBUTE] === 'bfcache') { + if (spanToJSON(span).attributes?.[BROWSER_NAVIGATION_TYPE] === 'bfcache') { bfcacheNavigationSpan = span; } }); diff --git a/packages/browser-utils/test/web-vitals/softNavs.test.ts b/packages/browser-utils/test/web-vitals/softNavs.test.ts index b329d23ef2f6..8ccc70f89e07 100644 --- a/packages/browser-utils/test/web-vitals/softNavs.test.ts +++ b/packages/browser-utils/test/web-vitals/softNavs.test.ts @@ -1,5 +1,6 @@ import * as SentryCore from '@sentry/core'; import { afterEach, beforeEach, describe, expect, it, vi } from 'vitest'; +import { BROWSER_NAVIGATION_ID } from '@sentry/conventions/attributes'; const windowListeners = vi.hoisted(() => new Map void>()); const performanceHandlers = vi.hoisted(() => new Map void>()); @@ -59,8 +60,7 @@ describe('soft navigation correlation', () => { }); it('correlates a soft navigation to the navigation span its interaction triggered', async () => { - const { getNavigationSpanForMetric, SOFT_NAVIGATION_ID_ATTRIBUTE, startSoftNavigationCorrelation } = - await loadSoftNavs(); + const { getNavigationSpanForMetric, startSoftNavigationCorrelation } = await loadSoftNavs(); const { client, startSpan } = createMockClient(); startSoftNavigationCorrelation(client as never); @@ -72,7 +72,7 @@ describe('soft navigation correlation', () => { performanceHandlers.get('event')?.({ entries: [{ duration: 8, startTime: 1234, interactionId: 42 }] }); performanceHandlers.get('soft-navigation')?.({ entries: [{ navigationId: 7, interactionId: 42 }] }); - expect(navigationSpan.setAttribute).toHaveBeenCalledWith(SOFT_NAVIGATION_ID_ATTRIBUTE, 7); + expect(navigationSpan.setAttribute).toHaveBeenCalledWith(BROWSER_NAVIGATION_ID, 7); expect(getNavigationSpanForMetric({ navigationType: 'soft-navigation', navigationId: 7 })).toBe(navigationSpan); }); diff --git a/packages/browser-utils/test/web-vitals/spans.test.ts b/packages/browser-utils/test/web-vitals/spans.test.ts index 1fd0b5f2e529..f7d15147103e 100644 --- a/packages/browser-utils/test/web-vitals/spans.test.ts +++ b/packages/browser-utils/test/web-vitals/spans.test.ts @@ -850,11 +850,11 @@ describe('soft navigation web vitals', () => { const calls = vi.mocked(SentryCoreBrowser.startInactiveSpan).mock.calls; expect(calls).toHaveLength(2); expect(calls[0]![0].attributes?.['browser.web_vital.lcp.value']).toBe(800); - expect(calls[0]![0].attributes?.['browser.soft_navigation.id']).toBeUndefined(); + expect(calls[0]![0].attributes?.['browser.navigation.id']).toBeUndefined(); expect(calls[0]![0].attributes?.['browser.navigation.type']).toBe('navigate'); expect(calls[0]![0].parentSpan).toBe(pageloadSpan); expect(calls[1]![0].attributes?.['browser.web_vital.lcp.value']).toBe(300); - expect(calls[1]![0].attributes?.['browser.soft_navigation.id']).toBe(2); + expect(calls[1]![0].attributes?.['browser.navigation.id']).toBe(2); expect(calls[1]![0].attributes?.['browser.navigation.type']).toBe('soft-navigation'); expect(calls[1]![0].parentSpan).toBe(navigationSpan); }); @@ -973,7 +973,7 @@ describe('soft navigation web vitals', () => { const call = vi.mocked(SentryCoreBrowser.startInactiveSpan).mock.calls[0]![0]; expect(call.attributes?.['browser.web_vital.cls.value']).toBe(0); - expect(call.attributes?.['browser.soft_navigation.id']).toBe(2); + expect(call.attributes?.['browser.navigation.id']).toBe(2); expect(call.parentSpan).toBe(navigationSpan); }); @@ -999,9 +999,9 @@ describe('soft navigation web vitals', () => { const calls = vi.mocked(SentryCoreBrowser.startInactiveSpan).mock.calls; expect(calls).toHaveLength(2); expect(calls[0]![0].parentSpan).toBe(pageloadSpan); - expect(calls[0]![0].attributes?.['browser.soft_navigation.id']).toBeUndefined(); + expect(calls[0]![0].attributes?.['browser.navigation.id']).toBeUndefined(); expect(calls[1]![0].parentSpan).toBe(navigationSpan); - expect(calls[1]![0].attributes?.['browser.soft_navigation.id']).toBe(2); + expect(calls[1]![0].attributes?.['browser.navigation.id']).toBe(2); }); it('still reports INP when web-vitals has no entry to describe it', () => { @@ -1026,7 +1026,7 @@ describe('soft navigation web vitals', () => { // these fast navigations are not excluded from INP aggregations. expect(call.attributes?.['sentry.op']).toBe('ui.interaction.click'); expect(call.attributes?.['browser.web_vital.inp.value']).toBe(8); - expect(call.attributes?.['browser.soft_navigation.id']).toBe(2); + expect(call.attributes?.['browser.navigation.id']).toBe(2); expect(call.parentSpan).toBe(navigationSpan); }); diff --git a/packages/browser/src/tracing/browserTracingIntegration.ts b/packages/browser/src/tracing/browserTracingIntegration.ts index e6c89ba5c11e..080d4154f609 100644 --- a/packages/browser/src/tracing/browserTracingIntegration.ts +++ b/packages/browser/src/tracing/browserTracingIntegration.ts @@ -28,13 +28,13 @@ import { import { _INTERNAL_ensureBrowserSpanStreaming, startIdleSpan, startInactiveSpan } from '@sentry/core/browser'; import { addHistoryInstrumentationHandler, - BROWSER_NAVIGATION_TYPE_ATTRIBUTE, addPerformanceEntries, getLocationHref, isBotUserAgent, startTrackingLongAnimationFrames, startTrackingLongTasks, } from '@sentry/browser-utils'; +import { BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes'; import { DEBUG_BUILD } from '../debug-build'; import { filterCollectedUrl } from '@sentry/core'; import { getHttpRequestData, WINDOW } from '../helpers'; @@ -723,7 +723,7 @@ export const browserTracingIntegration = ((options: Partial