From 29c77b37215c2e9a6d566bf619b3203b3c2434b2 Mon Sep 17 00:00:00 2001 From: s1gr1d <32902192+s1gr1d@users.noreply.github.com> Date: Tue, 25 Aug 2026 10:20:58 +0200 Subject: [PATCH] ref: Replace UI Span OP with `ui.` from `@sentry/conventions/op` --- packages/angular/src/constants.ts | 2 -- packages/angular/src/tracing.ts | 6 ++--- .../browser-utils/src/performance/entries.ts | 6 ++--- packages/browser-utils/src/web-vitals/inp.ts | 4 ++- .../browser-utils/src/web-vitals/spans.ts | 26 ++++++++++++++++--- .../browser/src/integrations/spotlight.ts | 3 ++- .../ember/src/utils/instrumentEmberGlobals.ts | 5 ++-- packages/react/src/profiler.tsx | 11 +++----- packages/svelte/src/performance.ts | 7 +++-- packages/vue/src/tracing.ts | 15 +++++------ 10 files changed, 50 insertions(+), 35 deletions(-) delete mode 100644 packages/angular/src/constants.ts diff --git a/packages/angular/src/constants.ts b/packages/angular/src/constants.ts deleted file mode 100644 index a4a14a33d15b..000000000000 --- a/packages/angular/src/constants.ts +++ /dev/null @@ -1,2 +0,0 @@ -// TODO(v11): Replace with the `ui.mount` constant from `@sentry/conventions/op` once it is registered there. -export const ANGULAR_INIT_OP = 'ui.mount'; diff --git a/packages/angular/src/tracing.ts b/packages/angular/src/tracing.ts index c45c3d7f4185..07e73f29555f 100644 --- a/packages/angular/src/tracing.ts +++ b/packages/angular/src/tracing.ts @@ -34,7 +34,7 @@ import { import type { Observable } from 'rxjs'; import { Subscription } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; -import { ANGULAR_INIT_OP } from './constants'; +import { UI_MOUNT } from '@sentry/conventions/op'; import { IS_DEBUG_BUILD } from './flags'; import { runOutsideAngular } from './zone'; @@ -302,7 +302,7 @@ export class TraceDirective implements OnInit, AfterViewInit { startInactiveSpan({ name: `<${this.componentName}>`, attributes: { - [SENTRY_OP]: ANGULAR_INIT_OP, + [SENTRY_OP]: UI_MOUNT, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_directive', }, }), @@ -353,7 +353,7 @@ export function TraceClass(options?: TraceClassOptions): ClassDecorator { onlyIfParent: true, name: `<${options?.name || 'unnamed'}>`, attributes: { - [SENTRY_OP]: ANGULAR_INIT_OP, + [SENTRY_OP]: UI_MOUNT, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.angular.trace_class_decorator', }, }), diff --git a/packages/browser-utils/src/performance/entries.ts b/packages/browser-utils/src/performance/entries.ts index 99e449d90c86..c4d5b1cfdc4b 100644 --- a/packages/browser-utils/src/performance/entries.ts +++ b/packages/browser-utils/src/performance/entries.ts @@ -10,7 +10,7 @@ import { filterCollectedUrl, } from '@sentry/core'; import { CODE_FILE_PATH, CODE_FUNCTION_NAME, SENTRY_OP, URL_FULL } from '@sentry/conventions/attributes'; -import { BROWSER_PAINT } from '@sentry/conventions/op'; +import { BROWSER_PAINT, UI_LONG_ANIMATION_FRAME, UI_LONG_TASK } from '@sentry/conventions/op'; import { addPerformanceInstrumentationHandler, type PerformanceLongAnimationFrameTiming, @@ -87,7 +87,7 @@ export function startTrackingLongTasks(): void { startAndEndSpan(parent, startTime, startTime + duration, { name: 'Main UI thread blocked', - op: 'ui.long_task', + op: UI_LONG_TASK, attributes: { [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.browser.metrics', }, @@ -149,7 +149,7 @@ export function startTrackingLongAnimationFrames(): void { startAndEndSpan(parent, startTime, startTime + duration, { name: 'Main UI thread blocked', - op: 'ui.long_animation_frame', + op: UI_LONG_ANIMATION_FRAME, attributes, }); } diff --git a/packages/browser-utils/src/web-vitals/inp.ts b/packages/browser-utils/src/web-vitals/inp.ts index 95982eb5e1af..04c6e7d86c44 100644 --- a/packages/browser-utils/src/web-vitals/inp.ts +++ b/packages/browser-utils/src/web-vitals/inp.ts @@ -21,7 +21,9 @@ const ELEMENT_NAME_TIMESTAMP_MAP = new Map(); */ export const MAX_PLAUSIBLE_INP_DURATION = 60; -export const INP_ENTRY_MAP: Record = { +export type InteractionType = 'click' | 'hover' | 'drag' | 'press'; + +export const INP_ENTRY_MAP: Record = { click: 'click', pointerdown: 'click', pointerup: 'click', diff --git a/packages/browser-utils/src/web-vitals/spans.ts b/packages/browser-utils/src/web-vitals/spans.ts index d219db12fe43..456a07701b3c 100644 --- a/packages/browser-utils/src/web-vitals/spans.ts +++ b/packages/browser-utils/src/web-vitals/spans.ts @@ -17,6 +17,7 @@ import { startInactiveSpan } from '@sentry/core/browser'; import { DEBUG_BUILD } from '../debug-build'; import { htmlTreeAsString } from '../htmlTreeAsString'; import { WINDOW } from '../types'; +import type { InteractionType } from './inp'; import { getCachedInteractionContext, INP_ENTRY_MAP, MAX_PLAUSIBLE_INP_DURATION } from './inp'; import type { InstrumentationHandlerCallback } from '../instrumentation/performanceObserver'; import { @@ -30,6 +31,21 @@ import { listenForWebVitalReportEvents } from './reportEvents'; import { getBrowserPerformanceAPI, msToSec, supportsWebVital } from '../performance/utils'; import type { PerformanceEventTiming } from '../instrumentation/performanceObserver'; import { SENTRY_SEGMENT_NAME, SENTRY_TRANSACTION } from '@sentry/conventions/attributes'; +import { + UI_INTERACTION_CLICK, + UI_INTERACTION_DRAG, + UI_INTERACTION_HOVER, + UI_INTERACTION_PRESS, + UI_WEBVITAL_CLS, + UI_WEBVITAL_LCP, +} from '@sentry/conventions/op'; + +const INTERACTION_TYPE_TO_SPAN_OP: Record = { + click: UI_INTERACTION_CLICK, + hover: UI_INTERACTION_HOVER, + drag: UI_INTERACTION_DRAG, + press: UI_INTERACTION_PRESS, +}; // 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 @@ -219,7 +235,7 @@ export function _sendLcpSpan( _emitWebVitalSpan({ name, - op: 'ui.webvital.lcp', + op: UI_WEBVITAL_LCP, origin: 'auto.http.browser.lcp', metricName: 'lcp', value: lcpValue, @@ -281,7 +297,7 @@ export function _sendClsSpan( _emitWebVitalSpan({ name, - op: 'ui.webvital.cls', + op: UI_WEBVITAL_CLS, origin: 'auto.http.browser.cls', metricName: 'cls', value: clsValue, @@ -343,6 +359,10 @@ export function _sendInpSpan(inpValue: number, entry: PerformanceEventTiming, st const duration = msToSec(inpValue); const interactionType = INP_ENTRY_MAP[entry.name]; + if (!interactionType) { + return; + } + const cachedContext = getCachedInteractionContext(entry.interactionId); const activeSpan = getActiveSpan(); const rootSpan = activeSpan ? getRootSpan(activeSpan) : undefined; @@ -352,7 +372,7 @@ export function _sendInpSpan(inpValue: number, entry: PerformanceEventTiming, st _emitWebVitalSpan({ name, - op: `ui.interaction.${interactionType}`, + op: INTERACTION_TYPE_TO_SPAN_OP[interactionType], origin: 'auto.http.browser.inp', metricName: 'inp', value: inpValue, diff --git a/packages/browser/src/integrations/spotlight.ts b/packages/browser/src/integrations/spotlight.ts index ef7d65aa2d7b..b8e069771da4 100644 --- a/packages/browser/src/integrations/spotlight.ts +++ b/packages/browser/src/integrations/spotlight.ts @@ -1,6 +1,7 @@ import type { Client, Envelope, IntegrationFn } from '@sentry/core/browser'; import { debug, defineIntegration, serializeEnvelope } from '@sentry/core/browser'; import { getNativeImplementation } from '@sentry/browser-utils'; +import { UI_INTERACTION_CLICK } from '@sentry/conventions/op'; import { DEBUG_BUILD } from '../debug-build'; import type { WINDOW } from '../helpers'; @@ -14,7 +15,7 @@ export type SpotlightConnectionOptions = { export const INTEGRATION_NAME = 'SpotlightBrowser' as const; -export const SPOTLIGHT_IGNORE_SPANS = [{ op: 'ui.interaction.click', name: '#sentry-spotlight' }]; +export const SPOTLIGHT_IGNORE_SPANS = [{ op: UI_INTERACTION_CLICK, name: '#sentry-spotlight' }]; const _spotlightIntegration = ((options: Partial = {}) => { const sidecarUrl = options.sidecarUrl || 'http://localhost:8969/stream'; diff --git a/packages/ember/src/utils/instrumentEmberGlobals.ts b/packages/ember/src/utils/instrumentEmberGlobals.ts index 8e34d3ea6e7e..6d19479af04c 100644 --- a/packages/ember/src/utils/instrumentEmberGlobals.ts +++ b/packages/ember/src/utils/instrumentEmberGlobals.ts @@ -1,7 +1,7 @@ import { subscribe } from '@ember/instrumentation'; import { scheduleOnce } from '@ember/runloop'; import { SENTRY_OP, UI_COMPONENT_NAME } from '@sentry/conventions/attributes'; -import { UI_RENDER, UI_TASK, FUNCTION } from '@sentry/conventions/op'; +import { UI_MOUNT, UI_RENDER, UI_TASK, FUNCTION } from '@sentry/conventions/op'; import { getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } from '@sentry/browser'; import type { Span } from '@sentry/core'; import { browserPerformanceTimeOrigin, timestampInSeconds } from '@sentry/core'; @@ -237,8 +237,7 @@ function _instrumentInitialLoad(): void { startInactiveSpan({ name: 'init', attributes: { - // TODO(v11): Replace with the `ui.mount` constant from `@sentry/conventions/op` once it is registered there. - [SENTRY_OP]: 'ui.mount', + [SENTRY_OP]: UI_MOUNT, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.ember', }, startTime, diff --git a/packages/react/src/profiler.tsx b/packages/react/src/profiler.tsx index 9624e2be5f24..c4e1960aa90c 100644 --- a/packages/react/src/profiler.tsx +++ b/packages/react/src/profiler.tsx @@ -2,7 +2,7 @@ import { startInactiveSpan } from '@sentry/browser'; import type { Span } from '@sentry/core'; import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, spanToJSON, timestampInSeconds, withActiveSpan } from '@sentry/core'; import { SENTRY_OP } from '@sentry/conventions/attributes'; -import { UI_RENDER } from '@sentry/conventions/op'; +import { UI_MOUNT, UI_RENDER, UI_UPDATE } from '@sentry/conventions/op'; import * as React from 'react'; import { hoistNonReactStatics } from './hoist-non-react-statics'; @@ -51,8 +51,7 @@ class Profiler extends React.Component { name: `<${name}>`, onlyIfParent: true, attributes: { - // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`. - [SENTRY_OP]: 'ui.mount', + [SENTRY_OP]: UI_MOUNT, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler', 'ui.component_name': name, }, @@ -82,8 +81,7 @@ class Profiler extends React.Component { onlyIfParent: true, startTime: now, attributes: { - // TODO(conventions): Replace `'ui.update'` with the `ui.update` span op constant once it is released in `@sentry/conventions`. - [SENTRY_OP]: 'ui.update', + [SENTRY_OP]: UI_UPDATE, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler', 'ui.component_name': this.props.name, 'ui.react.changed_props': changedProps, @@ -198,8 +196,7 @@ function useProfiler( name: `<${name}>`, onlyIfParent: true, attributes: { - // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`. - [SENTRY_OP]: 'ui.mount', + [SENTRY_OP]: UI_MOUNT, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.react.profiler', 'ui.component_name': name, }, diff --git a/packages/svelte/src/performance.ts b/packages/svelte/src/performance.ts index db8ae5056bdf..642458931646 100644 --- a/packages/svelte/src/performance.ts +++ b/packages/svelte/src/performance.ts @@ -3,6 +3,7 @@ import type { Span } from '@sentry/core'; import { debug } from '@sentry/core'; import { startInactiveSpan } from '@sentry/core/browser'; import { SENTRY_OP } from '@sentry/conventions/attributes'; +import { UI_MOUNT, UI_UPDATE } from '@sentry/conventions/op'; import { afterUpdate, beforeUpdate, onMount } from 'svelte'; import { DEBUG_BUILD } from './debug_build'; import type { TrackComponentOptions } from './types'; @@ -53,8 +54,7 @@ function recordInitSpan(componentName: string): void { onlyIfParent: true, name: componentName, attributes: { - // TODO(conventions): Replace `'ui.mount'` with the `ui.mount` span op constant once it is released in `@sentry/conventions`. - [SENTRY_OP]: 'ui.mount', + [SENTRY_OP]: UI_MOUNT, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.svelte', }, }); @@ -71,8 +71,7 @@ function recordUpdateSpans(componentName: string): void { onlyIfParent: true, name: componentName, attributes: { - // TODO(conventions): Replace `'ui.update'` with the `ui.update` span op constant once it is released in `@sentry/conventions`. - [SENTRY_OP]: 'ui.update', + [SENTRY_OP]: UI_UPDATE, [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.ui.svelte', }, }); diff --git a/packages/vue/src/tracing.ts b/packages/vue/src/tracing.ts index 53ccdf9ed31f..71b610a2e0ee 100644 --- a/packages/vue/src/tracing.ts +++ b/packages/vue/src/tracing.ts @@ -2,21 +2,20 @@ import { getActiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startInactiveSpan } fr import type { Span } from '@sentry/core'; import { debug, timestampInSeconds, uniq } from '@sentry/core'; import { SENTRY_OP } from '@sentry/conventions/attributes'; -import { UI_RENDER } from '@sentry/conventions/op'; +import { UI_MOUNT, UI_RENDER, UI_UNMOUNT, UI_UPDATE } from '@sentry/conventions/op'; import { DEFAULT_HOOKS } from './constants'; import { DEBUG_BUILD } from './debug-build'; import type { Hook, Operation, TracingOptions, ViewModel, Vue } from './types'; import { formatComponentName } from './vendor/components'; // Maps each Vue lifecycle operation to a cross-framework span op. -// TODO(conventions): Replace `'ui.mount'`, `'ui.update'` and `'ui.unmount'` with their span op constants once they are released in `@sentry/conventions`. const VUE_OPERATION_TO_SPAN_OP: Record = { - activate: 'ui.mount', - create: 'ui.mount', - mount: 'ui.mount', - update: 'ui.update', - unmount: 'ui.unmount', - destroy: 'ui.unmount', + activate: UI_MOUNT, + create: UI_MOUNT, + mount: UI_MOUNT, + update: UI_UPDATE, + unmount: UI_UNMOUNT, + destroy: UI_UNMOUNT, }; type Mixins = Parameters[0];