diff --git a/packages/rum-core/src/boot/startRum.spec.ts b/packages/rum-core/src/boot/startRum.spec.ts index f489a023f8..83bf80409a 100644 --- a/packages/rum-core/src/boot/startRum.spec.ts +++ b/packages/rum-core/src/boot/startRum.spec.ts @@ -17,7 +17,7 @@ import { deleteEventBridgeStub, } from '@datadog/browser-core/test' import type { RumSessionManagerMock, TestSetupBuilder } from '../../test' -import { createRumSessionManagerMock, noopRecorderApi, setup } from '../../test' +import { createRumSessionManagerMock, noopRecorderApi, noopWebVitalTelemetryDebug, setup } from '../../test' import type { RumPerformanceNavigationTiming, RumPerformanceEntry } from '../browser/performanceCollection' import type { LifeCycle } from '../domain/lifeCycle' import { LifeCycleEventType } from '../domain/lifeCycle' @@ -74,7 +74,7 @@ function startRumStub( startFeatureFlagContexts(lifeCycle), pageStateHistory, noopRecorderApi, - sessionManager + noopWebVitalTelemetryDebug ) startLongTaskCollection(lifeCycle, sessionManager) diff --git a/packages/rum-core/src/boot/startRum.ts b/packages/rum-core/src/boot/startRum.ts index 3f1c571c12..7e31580ca4 100644 --- a/packages/rum-core/src/boot/startRum.ts +++ b/packages/rum-core/src/boot/startRum.ts @@ -36,6 +36,7 @@ import { startCustomerDataTelemetry } from '../domain/startCustomerDataTelemetry import { startPageStateHistory } from '../domain/contexts/pageStateHistory' import type { CommonContext } from '../domain/contexts/commonContext' import { buildCommonContext } from '../domain/contexts/commonContext' +import { startWebVitalTelemetryDebug } from '../domain/rumEventsCollection/view/startWebVitalTelemetryDebug' import type { RecorderApi } from './rumPublicApi' export function startRum( @@ -118,6 +119,8 @@ export function startRum( startLongTaskCollection(lifeCycle, session) startResourceCollection(lifeCycle, configuration, session, pageStateHistory) + + const webVitalTelemetryDebug = startWebVitalTelemetryDebug(configuration, telemetry, recorderApi, session) const { addTiming, startView } = startViewCollection( lifeCycle, configuration, @@ -127,7 +130,7 @@ export function startRum( featureFlagContexts, pageStateHistory, recorderApi, - session, + webVitalTelemetryDebug, initialViewOptions ) const { addError } = startErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) diff --git a/packages/rum-core/src/domain/configuration.ts b/packages/rum-core/src/domain/configuration.ts index 823d6c2b64..a1f9ee6caf 100644 --- a/packages/rum-core/src/domain/configuration.ts +++ b/packages/rum-core/src/domain/configuration.ts @@ -157,7 +157,7 @@ export function validateAndBuildRumConfiguration( defaultPrivacyLevel: objectHasValue(DefaultPrivacyLevel, initConfiguration.defaultPrivacyLevel) ? initConfiguration.defaultPrivacyLevel : DefaultPrivacyLevel.MASK_USER_INPUT, - customerDataTelemetrySampleRate: 1, + customerDataTelemetrySampleRate: 100, }, baseConfiguration ) diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/addWebVitalTelemetryDebug.ts b/packages/rum-core/src/domain/rumEventsCollection/view/addWebVitalTelemetryDebug.ts deleted file mode 100644 index cca55ac917..0000000000 --- a/packages/rum-core/src/domain/rumEventsCollection/view/addWebVitalTelemetryDebug.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { addTelemetryDebug, elapsed, relativeNow, toServerDuration, type RelativeTime } from '@datadog/browser-core' -import type { RecorderApi } from '../../../boot/rumPublicApi' -import type { RumSessionManager } from '../../rumSessionManager' - -export function addWebVitalTelemetryDebug( - recorderApi: RecorderApi, - session: RumSessionManager, - webVitalName: string, - webVitalNode: Node | undefined, - webVitalTime: RelativeTime -) { - const computationTime = relativeNow() - if (!recorderApi.isRecording()) { - recorderApi.recorderStartObservable.subscribe((recordingStartTime) => { - addTelemetryDebug(`${webVitalName} attribution recording delay`, { - computationDelay: toServerDuration(elapsed(webVitalTime, computationTime)), - recordingDelay: toServerDuration(elapsed(webVitalTime, recordingStartTime)), - hasNode: !!webVitalNode, - serializedDomNode: webVitalNode ? recorderApi.getSerializedNodeId(webVitalNode) : undefined, - }) - }) - } - - addTelemetryDebug(`${webVitalName} attribution`, { - computationDelay: toServerDuration(elapsed(webVitalTime, computationTime)), - hasNode: !!webVitalNode, - replayRecording: recorderApi.isRecording(), - replaySampled: session.findTrackedSession()?.sessionReplayAllowed, - serializedDomNode: webVitalNode ? recorderApi.getSerializedNodeId(webVitalNode) : undefined, - }) -} diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/setupViewTest.specHelper.ts b/packages/rum-core/src/domain/rumEventsCollection/view/setupViewTest.specHelper.ts index d81b538b8f..4b68a876e8 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/setupViewTest.specHelper.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/setupViewTest.specHelper.ts @@ -1,4 +1,5 @@ -import { noopRecorderApi, type BuildContext } from '../../../../test' +import { noopWebVitalTelemetryDebug } from '../../../../test' +import { type BuildContext } from '../../../../test' import { LifeCycleEventType } from '../../lifeCycle' import type { ViewEvent, ViewOptions } from './trackViews' import { trackViews } from './trackViews' @@ -6,7 +7,7 @@ import { trackViews } from './trackViews' export type ViewTest = ReturnType export function setupViewTest( - { lifeCycle, location, domMutationObservable, configuration, locationChangeObservable, sessionManager }: BuildContext, + { lifeCycle, location, domMutationObservable, configuration, locationChangeObservable }: BuildContext, initialViewOptions?: ViewOptions ) { const { @@ -33,8 +34,7 @@ export function setupViewTest( configuration, locationChangeObservable, !configuration.trackViewsManually, - noopRecorderApi, - sessionManager, + noopWebVitalTelemetryDebug, initialViewOptions ) return { diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/startWebVitalTelemetryDebug.ts b/packages/rum-core/src/domain/rumEventsCollection/view/startWebVitalTelemetryDebug.ts new file mode 100644 index 0000000000..70dd2fbea4 --- /dev/null +++ b/packages/rum-core/src/domain/rumEventsCollection/view/startWebVitalTelemetryDebug.ts @@ -0,0 +1,45 @@ +import { addTelemetryDebug, elapsed, noop, performDraw, relativeNow, toServerDuration } from '@datadog/browser-core' +import type { Telemetry, RelativeTime } from '@datadog/browser-core' +import type { RecorderApi } from '../../../boot/rumPublicApi' +import type { RumSessionManager } from '../../rumSessionManager' +import type { RumConfiguration } from '../../configuration' + +export type WebVitalTelemetryDebug = ReturnType + +export function startWebVitalTelemetryDebug( + configuration: RumConfiguration, + telemetry: Telemetry, + recorderApi: RecorderApi, + session: RumSessionManager +) { + const webVitalTelemetryEnabled = telemetry.enabled && performDraw(configuration.customerDataTelemetrySampleRate) + + if (!webVitalTelemetryEnabled) { + return { + addWebVitalTelemetryDebug: noop, + } + } + return { + addWebVitalTelemetryDebug(webVitalName: string, webVitalNode: Node | undefined, webVitalTime: RelativeTime) { + const computationTime = relativeNow() + if (!recorderApi.isRecording()) { + recorderApi.recorderStartObservable.subscribe((recordingStartTime) => { + addTelemetryDebug(`${webVitalName} attribution recording delay`, { + computationDelay: toServerDuration(elapsed(webVitalTime, computationTime)), + recordingDelay: toServerDuration(elapsed(webVitalTime, recordingStartTime)), + hasNode: !!webVitalNode, + serializedDomNode: webVitalNode ? recorderApi.getSerializedNodeId(webVitalNode) : undefined, + }) + }) + } + + addTelemetryDebug(`${webVitalName} attribution`, { + computationDelay: toServerDuration(elapsed(webVitalTime, computationTime)), + hasNode: !!webVitalNode, + replayRecording: recorderApi.isRecording(), + replaySampled: session.findTrackedSession()?.sessionReplayAllowed, + serializedDomNode: webVitalNode ? recorderApi.getSerializedNodeId(webVitalNode) : undefined, + }) + }, + } +} diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.spec.ts b/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.spec.ts index f3768c7e1a..2d4e6f3340 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.spec.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.spec.ts @@ -2,7 +2,7 @@ import type { Duration, RelativeTime } from '@datadog/browser-core' import { DOM_EVENT } from '@datadog/browser-core' import { restorePageVisibility, setPageVisibility, createNewEvent } from '@datadog/browser-core/test' import type { TestSetupBuilder } from '../../../../test' -import { createRumSessionManagerMock, noopRecorderApi, setup } from '../../../../test' +import { noopWebVitalTelemetryDebug, setup } from '../../../../test' import type { RumFirstInputTiming, RumLargestContentfulPaintTiming, @@ -10,7 +10,6 @@ import type { RumPerformancePaintTiming, } from '../../../browser/performanceCollection' import { LifeCycleEventType } from '../../lifeCycle' -import type { RumSessionManager } from '../../rumSessionManager' import { resetFirstHidden } from './trackFirstHidden' import type { Timings } from './trackInitialViewTimings' import { @@ -57,18 +56,15 @@ describe('trackInitialViewTimings', () => { let scheduleViewUpdateSpy: jasmine.Spy<() => void> let trackInitialViewTimingsResult: ReturnType let setLoadEventSpy: jasmine.Spy<(loadEvent: Duration) => void> - let sessionManager: RumSessionManager beforeEach(() => { scheduleViewUpdateSpy = jasmine.createSpy() setLoadEventSpy = jasmine.createSpy() - sessionManager = createRumSessionManagerMock() setupBuilder = setup().beforeBuild(({ lifeCycle }) => { trackInitialViewTimingsResult = trackInitialViewTimings( lifeCycle, - noopRecorderApi, - sessionManager, + noopWebVitalTelemetryDebug, setLoadEventSpy, scheduleViewUpdateSpy ) diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.ts b/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.ts index eb7e4e7ce6..8b50b4c1aa 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/trackInitialViewTimings.ts @@ -11,7 +11,6 @@ import { relativeNow, } from '@datadog/browser-core' -import type { RecorderApi } from '../../../boot/rumPublicApi' import type { LifeCycle } from '../../lifeCycle' import { LifeCycleEventType } from '../../lifeCycle' import type { @@ -19,9 +18,8 @@ import type { RumLargestContentfulPaintTiming, RumPerformancePaintTiming, } from '../../../browser/performanceCollection' -import type { RumSessionManager } from '../../rumSessionManager' import { trackFirstHidden } from './trackFirstHidden' -import { addWebVitalTelemetryDebug } from './addWebVitalTelemetryDebug' +import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug' // Discard LCP and FCP timings above a certain delay to avoid incorrect data // It happens in some cases like sleep mode or some browser implementations @@ -49,8 +47,7 @@ export interface Timings { export function trackInitialViewTimings( lifeCycle: LifeCycle, - recorderApi: RecorderApi, - session: RumSessionManager, + webVitalTelemetryDebug: WebVitalTelemetryDebug, setLoadEvent: (loadEnd: Duration) => void, scheduleViewUpdate: () => void ) { @@ -72,7 +69,7 @@ export function trackInitialViewTimings( lifeCycle, window, (largestContentfulPaint, lcpElement) => { - addWebVitalTelemetryDebug(recorderApi, session, 'LCP', lcpElement, largestContentfulPaint) + webVitalTelemetryDebug.addWebVitalTelemetryDebug('LCP', lcpElement, largestContentfulPaint) setTimings({ largestContentfulPaint, @@ -83,7 +80,7 @@ export function trackInitialViewTimings( const { stop: stopFIDTracking } = trackFirstInputTimings( lifeCycle, ({ firstInputDelay, firstInputTime, firstInputTarget }) => { - addWebVitalTelemetryDebug(recorderApi, session, 'FID', firstInputTarget, firstInputTime) + webVitalTelemetryDebug.addWebVitalTelemetryDebug('FID', firstInputTarget, firstInputTime) setTimings({ firstInputDelay, diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/trackViewMetrics.ts b/packages/rum-core/src/domain/rumEventsCollection/view/trackViewMetrics.ts index 24901c9d5e..40805da1a1 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/trackViewMetrics.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/trackViewMetrics.ts @@ -12,7 +12,6 @@ import { throttle, find, } from '@datadog/browser-core' -import type { RecorderApi } from '../../../boot/rumPublicApi' import type { RumLayoutShiftTiming } from '../../../browser/performanceCollection' import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection' import { ViewLoadingType } from '../../../rawRumEvent.types' @@ -23,8 +22,7 @@ import { waitPageActivityEnd } from '../../waitPageActivityEnd' import { getScrollY } from '../../../browser/scroll' import { getViewportDimension } from '../../../browser/viewportObservable' -import type { RumSessionManager } from '../../rumSessionManager' -import { addWebVitalTelemetryDebug } from './addWebVitalTelemetryDebug' +import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug' export interface ScrollMetrics { maxDepth: number @@ -48,8 +46,7 @@ export function trackViewMetrics( scheduleViewUpdate: () => void, loadingType: ViewLoadingType, viewStart: ClocksState, - recorderApi: RecorderApi, - session: RumSessionManager + webVitalTelemetryDebug: WebVitalTelemetryDebug ) { const viewMetrics: ViewMetrics = {} @@ -99,7 +96,7 @@ export function trackViewMetrics( if (!clsAttributionCollected) { clsAttributionCollected = true - addWebVitalTelemetryDebug(recorderApi, session, 'CLS', largestLayoutShiftNode, largestLayoutShiftTime) + webVitalTelemetryDebug.addWebVitalTelemetryDebug('CLS', largestLayoutShiftNode, largestLayoutShiftTime) } scheduleViewUpdate() } diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts b/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts index a6bbfacdb7..d6f9dc5948 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/trackViews.ts @@ -17,7 +17,6 @@ import { clearInterval, } from '@datadog/browser-core' -import type { RecorderApi } from '../../../boot/rumPublicApi' import type { ViewCustomTimings } from '../../../rawRumEvent.types' import { ViewLoadingType } from '../../../rawRumEvent.types' @@ -26,12 +25,12 @@ import { LifeCycleEventType } from '../../lifeCycle' import type { EventCounts } from '../../trackEventCounts' import type { LocationChange } from '../../../browser/locationChangeObservable' import type { RumConfiguration } from '../../configuration' -import type { RumSessionManager } from '../../rumSessionManager' import type { Timings } from './trackInitialViewTimings' import { trackInitialViewTimings } from './trackInitialViewTimings' import type { ScrollMetrics } from './trackViewMetrics' import { trackViewMetrics } from './trackViewMetrics' import { trackViewEventCounts } from './trackViewEventCounts' +import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug' export interface ViewEvent { id: string @@ -81,8 +80,7 @@ export function trackViews( configuration: RumConfiguration, locationChangeObservable: Observable, areViewsTrackedAutomatically: boolean, - recorderApi: RecorderApi, - session: RumSessionManager, + webVitalTelemetryDebug: WebVitalTelemetryDebug, initialViewOptions?: ViewOptions ) { let currentView = startNewView(ViewLoadingType.INITIAL_LOAD, clocksOrigin(), initialViewOptions) @@ -101,8 +99,7 @@ export function trackViews( configuration, location, loadingType, - recorderApi, - session, + webVitalTelemetryDebug, startClocks, viewOptions ) @@ -160,8 +157,7 @@ function newView( configuration: RumConfiguration, initialLocation: Location, loadingType: ViewLoadingType, - recorderApi: RecorderApi, - session: RumSessionManager, + webVitalTelemetryDebug: WebVitalTelemetryDebug, startClocks: ClocksState = clocksNow(), viewOptions?: ViewOptions ) { @@ -211,13 +207,12 @@ function newView( scheduleViewUpdate, loadingType, startClocks, - recorderApi, - session + webVitalTelemetryDebug ) const { scheduleStop: scheduleStopInitialViewTimingsTracking, timings } = loadingType === ViewLoadingType.INITIAL_LOAD - ? trackInitialViewTimings(lifeCycle, recorderApi, session, setLoadEvent, scheduleViewUpdate) + ? trackInitialViewTimings(lifeCycle, webVitalTelemetryDebug, setLoadEvent, scheduleViewUpdate) : { scheduleStop: noop, timings: {} as Timings } const { scheduleStop: scheduleStopEventCountsTracking, eventCounts } = trackViewEventCounts( diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.spec.ts b/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.spec.ts index 32ace5bf5d..c2681d791b 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.spec.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.spec.ts @@ -2,7 +2,7 @@ import type { Duration, RelativeTime, ServerDuration, TimeStamp } from '@datadog import { resetExperimentalFeatures, ExperimentalFeature, addExperimentalFeatures } from '@datadog/browser-core' import type { RecorderApi } from '../../../boot/rumPublicApi' import type { TestSetupBuilder } from '../../../../test' -import { setup, noopRecorderApi } from '../../../../test' +import { setup, noopRecorderApi, noopWebVitalTelemetryDebug } from '../../../../test' import type { RawRumViewEvent } from '../../../rawRumEvent.types' import { RumEventType, ViewLoadingType } from '../../../rawRumEvent.types' import { LifeCycleEventType } from '../../lifeCycle' @@ -72,7 +72,6 @@ describe('viewCollection', () => { domMutationObservable, locationChangeObservable, pageStateHistory, - sessionManager, }) => { getReplayStatsSpy = jasmine.createSpy() startViewCollection( @@ -87,7 +86,7 @@ describe('viewCollection', () => { ...noopRecorderApi, getReplayStats: getReplayStatsSpy, }, - sessionManager + noopWebVitalTelemetryDebug ) } ) diff --git a/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.ts b/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.ts index 77e6ada0ff..808ece1890 100644 --- a/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.ts +++ b/packages/rum-core/src/domain/rumEventsCollection/view/viewCollection.ts @@ -17,9 +17,9 @@ import type { LocationChange } from '../../../browser/locationChangeObservable' import type { RumConfiguration } from '../../configuration' import type { FeatureFlagContexts } from '../../contexts/featureFlagContext' import type { PageStateHistory } from '../../contexts/pageStateHistory' -import type { RumSessionManager } from '../../rumSessionManager' import type { ViewEvent, ViewOptions } from './trackViews' import { trackViews } from './trackViews' +import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug' export function startViewCollection( lifeCycle: LifeCycle, @@ -30,7 +30,7 @@ export function startViewCollection( featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, - session: RumSessionManager, + webVitalTelemetryDebug: WebVitalTelemetryDebug, initialViewOptions?: ViewOptions ) { lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, (view) => @@ -46,8 +46,7 @@ export function startViewCollection( configuration, locationChangeObservable, !configuration.trackViewsManually, - recorderApi, - session, + webVitalTelemetryDebug, initialViewOptions ) diff --git a/packages/rum-core/test/index.ts b/packages/rum-core/test/index.ts index 4c1e6ff93c..1e346416bd 100644 --- a/packages/rum-core/test/index.ts +++ b/packages/rum-core/test/index.ts @@ -6,3 +6,4 @@ export * from './mockCiVisibilityWindowValues' export * from './mockRumSessionManager' export * from './noopRecorderApi' export * from './testSetupBuilder' +export * from './noopWebVitalTelemetryDebug' diff --git a/packages/rum-core/test/noopWebVitalTelemetryDebug.ts b/packages/rum-core/test/noopWebVitalTelemetryDebug.ts new file mode 100644 index 0000000000..579e3006b0 --- /dev/null +++ b/packages/rum-core/test/noopWebVitalTelemetryDebug.ts @@ -0,0 +1,3 @@ +import { noop } from '@datadog/browser-core' + +export const noopWebVitalTelemetryDebug = { addWebVitalTelemetryDebug: noop }