Skip to content
Merged
1 change: 0 additions & 1 deletion packages/rum-core/src/boot/rumPublicApi.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,6 @@ const noopStartRum = (): ReturnType<StartRum> => ({
getInternalContext: () => undefined,
lifeCycle: {} as any,
viewHistory: {} as any,
longTaskContexts: {} as any,
session: {} as any,
stopSession: () => undefined,
startDurationVital: () => ({}) as DurationVitalReference,
Expand Down
3 changes: 0 additions & 3 deletions packages/rum-core/src/boot/rumPublicApi.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ import { createCustomVitalsState } from '../domain/vital/vitalCollection'
import { callPluginsMethod } from '../domain/plugins'
import type { Hooks } from '../domain/hooks'
import type { SdkName } from '../domain/contexts/defaultContext'
import type { LongTaskContexts } from '../domain/longTask/longTaskCollection'
import type { ActionOptions } from '../domain/action/trackManualActions'
import type { ResourceOptions, ResourceStopOptions } from '../domain/resource/trackManualResources'
import { createPreStartStrategy } from './preStartRum'
Expand Down Expand Up @@ -528,7 +527,6 @@ export interface ProfilerApi {
configuration: RumConfiguration,
sessionManager: RumSessionManager,
viewHistory: ViewHistory,
longTaskContexts: LongTaskContexts,
createEncoder: (streamId: DeflateEncoderStreamId) => Encoder
) => void
}
Expand Down Expand Up @@ -626,7 +624,6 @@ export function makeRumPublicApi(
configuration,
startRumResult.session,
startRumResult.viewHistory,
startRumResult.longTaskContexts,
createEncoder
)

Expand Down
3 changes: 1 addition & 2 deletions packages/rum-core/src/boot/startRum.ts
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ export function startRumEventCollection(
const resourceCollection = startResourceCollection(lifeCycle, configuration, pageStateHistory)
cleanupTasks.push(resourceCollection.stop)

const { stop: stopLongTaskCollection, longTaskContexts } = startLongTaskCollection(lifeCycle, configuration)
const { stop: stopLongTaskCollection } = startLongTaskCollection(lifeCycle, configuration)
cleanupTasks.push(stopLongTaskCollection)

const { addError } = startErrorCollection(lifeCycle, configuration, bufferedDataObservable)
Expand Down Expand Up @@ -268,7 +268,6 @@ export function startRumEventCollection(
globalContext,
userContext,
accountContext,
longTaskContexts,
stop: () => cleanupTasks.forEach((task) => task()),
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ describe('actionCollection', () => {
events: [event],
})

expect(rawRumEvents[0].startTime).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].rawRumEvent).toEqual({
action: {
error: {
Expand Down Expand Up @@ -116,7 +116,7 @@ describe('actionCollection', () => {
context: { foo: 'bar' },
})

expect(rawRumEvents[0].startTime).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].rawRumEvent).toEqual({
action: {
id: jasmine.any(String),
Expand Down
2 changes: 1 addition & 1 deletion packages/rum-core/src/domain/action/actionCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ function processAction(action: AutoAction | ManualAction): RawRumEventCollectedD
: { context: action.context }),
},
duration: action.duration,
startTime: action.startClocks.relative,
startClocks: action.startClocks,
domainContext: isAuto ? { events: action.events } : { handlingStack: action.handlingStack },
}
}
Expand Down
17 changes: 12 additions & 5 deletions packages/rum-core/src/domain/assembly.spec.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import type { ClocksState, RelativeTime, TimeStamp } from '@datadog/browser-core'
import { ErrorSource, HookNames, ONE_MINUTE, display, startGlobalContext } from '@datadog/browser-core'
import {
ErrorSource,
HookNames,
ONE_MINUTE,
display,
relativeToClocks,
startGlobalContext,
} from '@datadog/browser-core'
import type { Clock } from '@datadog/browser-core/test'
import { registerCleanupTask, mockClock } from '@datadog/browser-core/test'
import {
Expand Down Expand Up @@ -461,7 +468,7 @@ describe('rum assembly', () => {

notifyRawRumEvent(lifeCycle, {
rawRumEvent: createRawRumEvent(RumEventType.ACTION),
startTime: 123 as RelativeTime,
startClocks: relativeToClocks(123 as RelativeTime),
})

expect(sessionManager.findTrackedSession).toHaveBeenCalledWith(123 as RelativeTime)
Expand Down Expand Up @@ -567,11 +574,11 @@ describe('rum assembly', () => {

function notifyRawRumEvent<E extends RawRumEvent>(
lifeCycle: LifeCycle,
partialData: Omit<RawRumEventCollectedData<E>, 'startTime' | 'domainContext'> &
Partial<Pick<RawRumEventCollectedData<E>, 'startTime' | 'domainContext'>>
partialData: Omit<RawRumEventCollectedData<E>, 'startClocks' | 'domainContext'> &
Partial<Pick<RawRumEventCollectedData<E>, 'startClocks' | 'domainContext'>>
) {
const fullData = {
startTime: 0 as RelativeTime,
startClocks: relativeToClocks(0 as RelativeTime),
domainContext: {} as RumEventDomainContext,
...partialData,
}
Expand Down
4 changes: 2 additions & 2 deletions packages/rum-core/src/domain/assembly.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,12 +92,12 @@ export function startRumAssembly(

lifeCycle.subscribe(
LifeCycleEventType.RAW_RUM_EVENT_COLLECTED,
({ startTime, duration, rawRumEvent, domainContext }) => {
({ startClocks, duration, rawRumEvent, domainContext }) => {
const defaultRumEventAttributes = hooks.triggerHook(HookNames.Assemble, {
eventType: rawRumEvent.type,
rawRumEvent,
domainContext,
startTime,
startTime: startClocks.relative,
duration,
} as AssembleHookParams)!

Expand Down
7 changes: 4 additions & 3 deletions packages/rum-core/src/domain/error/errorCollection.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -65,10 +65,11 @@ describe('error collection', () => {
it(`notifies a raw rum error event from ${testCase}`, () => {
setupErrorCollection()

const startClocks = { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp }
addError({
error,
handlingStack: 'Error: handling foo',
startClocks: { relative: 1234 as RelativeTime, timeStamp: 123456789 as TimeStamp },
startClocks,
})

expect(rawRumEvents.length).toBe(1)
Expand All @@ -92,7 +93,7 @@ describe('error collection', () => {
type: RumEventType.ERROR,
context: undefined,
},
startTime: 1234 as RelativeTime,
startClocks,
domainContext: {
error,
handlingStack: 'Error: handling foo',
Expand Down Expand Up @@ -239,7 +240,7 @@ describe('error collection', () => {
},
})

expect(rawRumEvents[0].startTime).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].rawRumEvent).toEqual({
date: jasmine.any(Number),
error: {
Expand Down
2 changes: 1 addition & 1 deletion packages/rum-core/src/domain/error/errorCollection.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ function processError(error: RawError): RawRumEventCollectedData<RawRumErrorEven

return {
rawRumEvent,
startTime: error.startClocks.relative,
startClocks: error.startClocks,
domainContext,
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe('eventCollection', () => {
eventCollection.addEvent(startTime, event, domainContext, duration)

expect(notifySpy).toHaveBeenCalledWith(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {
startTime,
startClocks: { relative: startTime, timeStamp: jasmine.any(Number) },
rawRumEvent: event,
domainContext,
duration,
Expand Down
3 changes: 2 additions & 1 deletion packages/rum-core/src/domain/event/eventCollection.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { relativeToClocks } from '@datadog/browser-core'
import type { Context, Duration, RelativeTime } from '@datadog/browser-core'
import type { RumEventDomainContext } from '../../domainContext.types'
import type { LifeCycle } from '../lifeCycle'
Expand Down Expand Up @@ -43,7 +44,7 @@ export function startEventCollection(lifeCycle: LifeCycle) {
}

lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {
startTime,
startClocks: relativeToClocks(startTime),
rawRumEvent: event,
domainContext,
duration,
Expand Down
4 changes: 2 additions & 2 deletions packages/rum-core/src/domain/lifeCycle.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Context, Duration, PageMayExitEvent, RawError, RelativeTime } from '@datadog/browser-core'
import type { ClocksState, Context, Duration, PageMayExitEvent, RawError } from '@datadog/browser-core'
import { AbstractLifeCycle } from '@datadog/browser-core'
import type { RumEventDomainContext } from '../domainContext.types'
import type { RawRumEvent, AssembledRumEvent } from '../rawRumEvent.types'
Expand Down Expand Up @@ -92,7 +92,7 @@ export interface LifeCycleEventMap {
}

export interface RawRumEventCollectedData<E extends RawRumEvent = RawRumEvent> {
startTime: RelativeTime
startClocks: ClocksState
duration?: Duration
rawRumEvent: E
domainContext: RumEventDomainContext<E['type']>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Duration, RelativeTime, ServerDuration } from '@datadog/browser-core'
import type { RelativeTime, ServerDuration } from '@datadog/browser-core'
import { registerCleanupTask } from '@datadog/browser-core/test'
import {
collectAndValidateRawRumEvents,
Expand All @@ -8,7 +8,7 @@ import {
} from '../../../test'
import type { RumPerformanceEntry } from '../../browser/performanceObservable'
import { RumPerformanceEntryType } from '../../browser/performanceObservable'
import type { RawRumEvent, RawRumLongTaskEvent } from '../../rawRumEvent.types'
import type { RawRumEvent } from '../../rawRumEvent.types'
import { RumEventType, RumLongTaskEntryType } from '../../rawRumEvent.types'
import type { RawRumEventCollectedData } from '../lifeCycle'
import { LifeCycle } from '../lifeCycle'
Expand Down Expand Up @@ -49,7 +49,7 @@ describe('longTaskCollection', () => {

notifyPerformanceEntries([performanceLongAnimationFrameTiming])

expect(rawRumEvents[0].startTime).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].rawRumEvent).toEqual({
date: jasmine.any(Number),
long_task: {
Expand Down Expand Up @@ -98,21 +98,6 @@ describe('longTaskCollection', () => {
expect(rawRumEvents.length).toBe(1)
})

it('should track long animation frame contexts', () => {
const longTaskCollection = setupLongTaskCollection()
const entry = createPerformanceEntry(RumPerformanceEntryType.LONG_ANIMATION_FRAME)
notifyPerformanceEntries([entry])

const longTask = (rawRumEvents[0].rawRumEvent as RawRumLongTaskEvent).long_task
const longTasks = longTaskCollection.longTaskContexts.findLongTasks(1234 as RelativeTime, 100 as Duration)
expect(longTasks).toContain({
id: longTask.id,
startClocks: jasmine.objectContaining({ relative: entry.startTime }),
duration: entry.duration,
entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME,
})
})

it('should not collect when trackLongTasks=false', () => {
setupLongTaskCollection({ trackLongTasks: false })

Expand All @@ -127,7 +112,7 @@ describe('longTaskCollection', () => {
setupLongTaskCollection({ supportedEntryType: RumPerformanceEntryType.LONG_TASK })
notifyPerformanceEntries([createPerformanceEntry(RumPerformanceEntryType.LONG_TASK)])

expect(rawRumEvents[0].startTime).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].startClocks.relative).toBe(1234 as RelativeTime)
expect(rawRumEvents[0].rawRumEvent).toEqual({
date: jasmine.any(Number),
long_task: {
Expand Down Expand Up @@ -158,21 +143,6 @@ describe('longTaskCollection', () => {
expect(rawRumEvents.length).toBe(1)
})

it('should track long tasks contexts', () => {
const longTaskCollection = setupLongTaskCollection({ supportedEntryType: RumPerformanceEntryType.LONG_TASK })
const entry = createPerformanceEntry(RumPerformanceEntryType.LONG_TASK)
notifyPerformanceEntries([entry])

const longTask = (rawRumEvents[0].rawRumEvent as RawRumLongTaskEvent).long_task
const longTasks = longTaskCollection.longTaskContexts.findLongTasks(1234 as RelativeTime, 100 as Duration)
expect(longTasks).toContain({
id: longTask.id,
startClocks: jasmine.objectContaining({ relative: entry.startTime }),
duration: entry.duration,
entryType: RumPerformanceEntryType.LONG_TASK,
})
})

it('should not collect when trackLongTasks=false', () => {
setupLongTaskCollection({ supportedEntryType: RumPerformanceEntryType.LONG_TASK, trackLongTasks: false })

Expand Down
59 changes: 13 additions & 46 deletions packages/rum-core/src/domain/longTask/longTaskCollection.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,5 @@
import type { RelativeTime, ClocksState, Duration } from '@datadog/browser-core'
import {
toServerDuration,
relativeToClocks,
generateUUID,
createValueHistory,
SESSION_TIME_OUT_DELAY,
addDuration,
} from '@datadog/browser-core'
import type { ClocksState } from '@datadog/browser-core'
import { toServerDuration, relativeToClocks, generateUUID } from '@datadog/browser-core'
import type { RawRumLongTaskEvent, RawRumLongAnimationFrameEvent } from '../../rawRumEvent.types'
import { RumEventType, RumLongTaskEntryType } from '../../rawRumEvent.types'
import type { LifeCycle } from '../lifeCycle'
Expand All @@ -23,23 +16,7 @@ import type {
} from '../../browser/performanceObservable'
import type { RumConfiguration } from '../configuration'

export const LONG_TASK_ID_HISTORY_TIME_OUT_DELAY = SESSION_TIME_OUT_DELAY

export interface LongTaskContext {
id: string
startClocks: ClocksState
duration: Duration
entryType: RumPerformanceEntryType.LONG_ANIMATION_FRAME | RumPerformanceEntryType.LONG_TASK
}

export interface LongTaskContexts {
findLongTasks: (startTime: RelativeTime, duration: Duration) => LongTaskContext[]
}

export function startLongTaskCollection(lifeCycle: LifeCycle, configuration: RumConfiguration) {
const history = createValueHistory<LongTaskContext>({
expireDelay: LONG_TASK_ID_HISTORY_TIME_OUT_DELAY,
})
const entryType = supportPerformanceTimingEvent(RumPerformanceEntryType.LONG_ANIMATION_FRAME)
? RumPerformanceEntryType.LONG_ANIMATION_FRAME
: RumPerformanceEntryType.LONG_TASK
Expand All @@ -54,39 +31,29 @@ export function startLongTaskCollection(lifeCycle: LifeCycle, configuration: Rum
}

const startClocks = relativeToClocks(entry.startTime)
const taskId = generateUUID()
const rawRumEvent = processEntry(entry, startClocks, taskId)
const rawRumEvent = processEntry(entry, startClocks)

lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, {
rawRumEvent,
startTime: startClocks.relative,
startClocks,
duration: entry.duration,
domainContext: { performanceEntry: entry },
})

history.add({ id: taskId, startClocks, duration: entry.duration, entryType }, startClocks.relative)
history.closeActive(addDuration(startClocks.relative, entry.duration))
}
})

const longTaskContexts: LongTaskContexts = {
findLongTasks: (startTime: RelativeTime, duration: Duration) => history.findAll(startTime, duration),
}

return {
stop: () => {
subscription.unsubscribe()
history.stop()
},
longTaskContexts,
stop: () => subscription.unsubscribe(),
}
}

function processEntry(
entry: RumPerformanceLongTaskTiming | RumPerformanceLongAnimationFrameTiming,
startClocks: ClocksState,
taskId: string
startClocks: ClocksState
): RawRumLongTaskEvent | RawRumLongAnimationFrameEvent {
const id = generateUUID()
const duration = toServerDuration(entry.duration)

const baseEvent = {
date: startClocks.timeStamp,
type: RumEventType.LONG_TASK,
Expand All @@ -97,19 +64,19 @@ function processEntry(
return {
...baseEvent,
long_task: {
id: taskId,
id,
entry_type: RumLongTaskEntryType.LONG_TASK,
duration: toServerDuration(entry.duration),
duration,
},
}
}

return {
...baseEvent,
long_task: {
id: taskId,
id,
entry_type: RumLongTaskEntryType.LONG_ANIMATION_FRAME,
duration: toServerDuration(entry.duration),
duration,
blocking_duration: toServerDuration(entry.blockingDuration),
first_ui_event_timestamp: toServerDuration(entry.firstUIEventTimestamp),
render_start: toServerDuration(entry.renderStart),
Expand Down
Loading