Skip to content

Commit 562f191

Browse files
committed
Fix action long task correlation
1 parent 866ab07 commit 562f191

File tree

5 files changed

+72
-7
lines changed

5 files changed

+72
-7
lines changed

packages/rum-core/src/domain/action/trackClickActions.spec.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -568,22 +568,21 @@ describe('trackClickActions', () => {
568568
const targetPosition = target.getBoundingClientRect()
569569
const offsetX = targetPosition.width / 2
570570
const offsetY = targetPosition.height / 2
571-
const eventProperties = {
571+
const baseEventProperties = {
572572
target,
573573
clientX: targetPosition.left + offsetX,
574574
clientY: targetPosition.top + offsetY,
575575
offsetX,
576576
offsetY,
577-
timeStamp: timeStampNow(),
578577
isPrimary: true,
579578
...eventProperty,
580579
}
581-
target.dispatchEvent(createNewEvent('pointerdown', eventProperties))
580+
target.dispatchEvent(createNewEvent('pointerdown', { ...baseEventProperties, timeStamp: relativeNow() }))
582581
emulateActivityIfNeeded('pointerdown')
583582
clock!.tick(EMULATED_CLICK_DURATION)
584-
target.dispatchEvent(createNewEvent('pointerup', eventProperties))
583+
target.dispatchEvent(createNewEvent('pointerup', { ...baseEventProperties, timeStamp: relativeNow() }))
585584
emulateActivityIfNeeded('pointerup')
586-
target.dispatchEvent(createNewEvent('click', eventProperties))
585+
target.dispatchEvent(createNewEvent('click', { ...baseEventProperties, timeStamp: relativeNow() }))
587586
emulateActivityIfNeeded('click')
588587

589588
function emulateActivityIfNeeded(event: 'pointerdown' | 'pointerup' | 'click') {

packages/rum-core/src/domain/action/trackClickActions.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import {
55
getRelativeTime,
66
ONE_MINUTE,
77
generateUUID,
8-
clocksNow,
98
elapsed,
109
createValueHistory,
1110
PageExitReason,
11+
relativeToClocks
1212
} from '@datadog/browser-core'
1313
import type { FrustrationType } from '../../rawRumEvent.types'
1414
import { ActionType } from '../../rawRumEvent.types'
@@ -288,7 +288,7 @@ function newClick(
288288
startEvent: MouseEventOnElement
289289
) {
290290
const id = generateUUID()
291-
const startClocks = clocksNow()
291+
const startClocks = relativeToClocks(startEvent.timeStamp)
292292
const historyEntry = history.add(id, startClocks.relative)
293293
const eventCountsSubscription = trackEventCounts({
294294
lifeCycle,

packages/rum-core/src/domain/longTask/longTaskCollection.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import type { LifeCycle } from '../lifeCycle'
55
import { LifeCycleEventType } from '../lifeCycle'
66
import { createPerformanceObservable, RumPerformanceEntryType } from '../../browser/performanceObservable'
77
import type { RumConfiguration } from '../configuration'
8+
89
export function startLongTaskCollection(lifeCycle: LifeCycle, configuration: RumConfiguration) {
910
const performanceLongTaskSubscription = createPerformanceObservable(configuration, {
1011
type: RumPerformanceEntryType.LONG_TASK,

test/e2e/lib/framework/intakeRegistry.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type {
66
RumResourceEvent,
77
RumViewEvent,
88
RumVitalEvent,
9+
RumLongTaskEvent,
910
} from '@datadog/browser-rum'
1011
import type {
1112
TelemetryEvent,
@@ -102,6 +103,10 @@ export class IntakeRegistry {
102103
return this.rumEvents.filter(isRumResourceEvent)
103104
}
104105

106+
get rumLongTaskEvents() {
107+
return this.rumEvents.filter(isRumLongTaskEvent)
108+
}
109+
105110
get rumViewEvents() {
106111
return this.rumEvents.filter(isRumViewEvent)
107112
}
@@ -171,6 +176,10 @@ function isRumActionEvent(event: RumEvent): event is RumActionEvent {
171176
return event.type === 'action'
172177
}
173178

179+
function isRumLongTaskEvent(event: RumEvent): event is RumLongTaskEvent {
180+
return event.type === 'long_task'
181+
}
182+
174183
function isRumViewEvent(event: RumEvent): event is RumViewEvent {
175184
return event.type === 'view'
176185
}

test/e2e/scenario/rum/actions.scenario.ts

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,62 @@ test.describe('action collection', () => {
154154
expect(resourceEvents[0].action!.id).toContain(actionEvents[0].action.id!)
155155
})
156156

157+
158+
159+
createTest('associate a long tasks to its action')
160+
.withRum({ trackUserInteractions: true })
161+
.withBody(html`
162+
<button>click me</button>
163+
<script>
164+
const button = document.querySelector('button')
165+
button.addEventListener('click', () => {
166+
const end = performance.now() + 55
167+
while (performance.now() < end) {} // block the handler for ~55ms to trigger a long task
168+
fetch('/ok') // fire a fetch to extend the action duration
169+
})
170+
</script>
171+
`)
172+
.run(async ({ intakeRegistry, flushEvents, page, browserName }) => {
173+
test.skip(browserName !== 'chromium', 'Non-Chromium browsers do not support long tasks')
174+
175+
const button = page.locator('button')
176+
await button.click()
177+
await waitForServersIdle()
178+
await flushEvents()
179+
const actionEvents = intakeRegistry.rumActionEvents
180+
const longTaskEvents = intakeRegistry.rumLongTaskEvents.filter((event) =>
181+
event.long_task.scripts?.[0]?.invoker?.includes('BUTTON.onclick')
182+
)
183+
184+
expect(actionEvents).toHaveLength(1)
185+
expect(actionEvents[0].action).toEqual({
186+
error: {
187+
count: 0,
188+
},
189+
id: expect.any(String) as unknown as string,
190+
loading_time: expect.any(Number),
191+
long_task: {
192+
count: 1,
193+
},
194+
195+
resource: {
196+
count: expect.any(Number) as unknown as number,
197+
},
198+
target: {
199+
name: 'click me',
200+
},
201+
type: 'click',
202+
frustration: {
203+
type: [],
204+
},
205+
})
206+
207+
expect(longTaskEvents).toHaveLength(1)
208+
// long task action id should contain the collected action id + the discarded rage click id
209+
expect(longTaskEvents[0].action!.id).toHaveLength(2)
210+
expect(longTaskEvents[0].action!.id).toContain(actionEvents[0].action.id!)
211+
})
212+
157213
createTest('increment the view.action.count of the view active when the action started')
158214
.withRum({ trackUserInteractions: true })
159215
.withBody(html`

0 commit comments

Comments
 (0)