From a16a7e8f5096847ffa2650994118315e298ec782 Mon Sep 17 00:00:00 2001 From: Antoine RICHARD Date: Mon, 30 Sep 2024 16:01:34 +0200 Subject: [PATCH 1/2] =?UTF-8?q?=E2=9C=A8=20Add=20input,=20process=20and=20?= =?UTF-8?q?render=20durations=20to=20INP?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/domain/view/viewCollection.spec.ts | 5 +- .../src/domain/view/viewCollection.ts | 3 ++ .../trackInteractionToNextPaint.spec.ts | 53 ++++++++++++++++--- .../trackInteractionToNextPaint.ts | 16 ++++++ packages/rum-core/src/rawRumEvent.types.ts | 3 ++ packages/rum-core/src/rumEvent.types.ts | 12 +++++ 6 files changed, 85 insertions(+), 7 deletions(-) diff --git a/packages/rum-core/src/domain/view/viewCollection.spec.ts b/packages/rum-core/src/domain/view/viewCollection.spec.ts index a536155d10..75f9f6329b 100644 --- a/packages/rum-core/src/domain/view/viewCollection.spec.ts +++ b/packages/rum-core/src/domain/view/viewCollection.spec.ts @@ -58,7 +58,7 @@ const VIEW: ViewEvent = { commonViewMetrics: { loadingTime: 20 as Duration, cumulativeLayoutShift: { value: 1, time: 100 as Duration }, - interactionToNextPaint: { value: 10 as Duration, time: 100 as Duration }, + interactionToNextPaint: { value: 10 as Duration, time: 100 as Duration, input: 2 as Duration, process: 5 as Duration, render: 3 as Duration }, scroll: { maxDepth: 2000, maxScrollHeight: 3000, @@ -155,6 +155,9 @@ describe('viewCollection', () => { interaction_to_next_paint: (10 * 1e6) as ServerDuration, interaction_to_next_paint_target_selector: undefined, interaction_to_next_paint_time: (100 * 1e6) as ServerDuration, + interaction_to_next_paint_input: (2 * 1e6) as ServerDuration, + interaction_to_next_paint_process: (5 * 1e6) as ServerDuration, + interaction_to_next_paint_render: (3 * 1e6) as ServerDuration, is_active: false, name: undefined, largest_contentful_paint: (10 * 1e6) as ServerDuration, diff --git a/packages/rum-core/src/domain/view/viewCollection.ts b/packages/rum-core/src/domain/view/viewCollection.ts index fc822e8505..4577fb7aa6 100644 --- a/packages/rum-core/src/domain/view/viewCollection.ts +++ b/packages/rum-core/src/domain/view/viewCollection.ts @@ -86,6 +86,9 @@ function processViewUpdate( interaction_to_next_paint: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.value), interaction_to_next_paint_time: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.time), interaction_to_next_paint_target_selector: view.commonViewMetrics.interactionToNextPaint?.targetSelector, + interaction_to_next_paint_input: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.input), + interaction_to_next_paint_process: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.process), + interaction_to_next_paint_render: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.render), is_active: view.isActive, name: view.name, largest_contentful_paint: toServerDuration(view.initialViewMetrics.largestContentfulPaint?.value), diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts b/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts index 83b4cf67c1..606ebbc72b 100644 --- a/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts +++ b/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.spec.ts @@ -81,14 +81,20 @@ describe('trackInteractionToNextPaint', () => { setViewEnd(10 as RelativeTime) newInteraction({ + name: 'pointerup', interactionId: 1, duration: 10 as Duration, startTime: -1 as RelativeTime, + processingStart: 0 as RelativeTime, + processingEnd: 6 as RelativeTime, }) newInteraction({ + name: 'pointerup', interactionId: 2, duration: 10 as Duration, startTime: 11 as RelativeTime, + processingStart: 12 as RelativeTime, + processingEnd: 16 as RelativeTime, }) expect(getInteractionToNextPaint()).toEqual(undefined) }) @@ -98,29 +104,43 @@ describe('trackInteractionToNextPaint', () => { setViewEnd(10 as RelativeTime) newInteraction({ + name: 'pointerup', interactionId: 1, duration: 100 as Duration, startTime: 1 as RelativeTime, + processingStart: 2 as RelativeTime, + processingEnd: 80 as RelativeTime, }) expect(getInteractionToNextPaint()).toEqual({ value: 100 as Duration, targetSelector: undefined, time: 1 as RelativeTime, + type: 'pointerup', + input: 1 as Duration, + process: 78 as Duration, + render: 21 as Duration, }) }) it('should cap INP value', () => { startINPTracking() newInteraction({ + name: 'pointerup', interactionId: 1, duration: (MAX_INP_VALUE + 1) as Duration, - startTime: 1 as RelativeTime, + startTime: 10 as RelativeTime, + processingStart: 15 as RelativeTime, + processingEnd: 80 as RelativeTime, }) expect(getInteractionToNextPaint()).toEqual({ value: MAX_INP_VALUE, targetSelector: undefined, - time: 1 as RelativeTime, + time: 10 as RelativeTime, + type: 'pointerup', + input: 5 as Duration, + process: 65 as Duration, + render: (MAX_INP_VALUE + 10 - 80 + 1) as Duration, }) }) @@ -130,13 +150,20 @@ describe('trackInteractionToNextPaint', () => { newInteraction({ duration: index as Duration, interactionId: index, - startTime: index as RelativeTime, + startTime: 1 as RelativeTime, + name: 'pointerup', + processingStart: 1 as RelativeTime, + processingEnd: index as RelativeTime, }) } expect(getInteractionToNextPaint()).toEqual({ value: 98 as Duration, targetSelector: undefined, - time: 98 as RelativeTime, + time: 1 as RelativeTime, + type: 'pointerup', + input: 0 as RelativeTime, + process: 97 as RelativeTime, + render: 1 as RelativeTime, }) }) @@ -152,11 +179,18 @@ describe('trackInteractionToNextPaint', () => { interactionId: 1, entryType: RumPerformanceEntryType.FIRST_INPUT, startTime: 1 as RelativeTime, + name: 'pointerup', + processingStart: 1 as RelativeTime, + processingEnd: 5 as RelativeTime, }) expect(getInteractionToNextPaint()).toEqual({ value: 40 as Duration, targetSelector: undefined, time: 1 as RelativeTime, + type: 'pointerup', + input: 0 as RelativeTime, + process: 4 as RelativeTime, + render: 36 as RelativeTime, }) }) @@ -166,14 +200,21 @@ describe('trackInteractionToNextPaint', () => { newInteraction({ duration: index as Duration, interactionId: 1, - startTime: index as RelativeTime, + startTime: 1 as RelativeTime, + name: 'pointerup', + processingStart: 1 as RelativeTime, + processingEnd: index as RelativeTime, }) } // the p98 return 100 which shows that the entry has been updated expect(getInteractionToNextPaint()).toEqual({ value: 100 as Duration, targetSelector: undefined, - time: 100 as RelativeTime, + time: 1 as RelativeTime, + type: 'pointerup', + input: 0 as Duration, + process: 99 as Duration, + render: 1 as Duration, }) }) diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.ts b/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.ts index dd0e20299e..f44206c5cd 100644 --- a/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.ts +++ b/packages/rum-core/src/domain/view/viewMetrics/trackInteractionToNextPaint.ts @@ -20,7 +20,11 @@ export const MAX_INP_VALUE = (1 * ONE_MINUTE) as Duration export interface InteractionToNextPaint { value: Duration targetSelector?: string + type?: string time?: Duration + input?: Duration + process?: Duration + render?: Duration } /** * Track the interaction to next paint (INP). @@ -48,7 +52,11 @@ export function trackInteractionToNextPaint( const longestInteractions = trackLongestInteractions(getViewInteractionCount) let interactionToNextPaint = -1 as Duration let interactionToNextPaintTargetSelector: string | undefined + let interactionToNextPaintType: string | undefined let interactionToNextPaintStartTime: Duration | undefined + let interactionToNextPaintInputTime: Duration | undefined + let interactionToNextPaintProcessingTime: Duration | undefined + let interactionToNextPaintRenderTime: Duration | undefined function handleEntries(entries: Array) { for (const entry of entries) { @@ -65,7 +73,11 @@ export function trackInteractionToNextPaint( const newInteraction = longestInteractions.estimateP98Interaction() if (newInteraction && newInteraction.duration !== interactionToNextPaint) { interactionToNextPaint = newInteraction.duration + interactionToNextPaintType = newInteraction.name interactionToNextPaintStartTime = elapsed(viewStart, newInteraction.startTime) + interactionToNextPaintInputTime = elapsed(newInteraction.startTime, newInteraction.processingStart) + interactionToNextPaintProcessingTime = elapsed(newInteraction.processingStart, newInteraction.processingEnd) + interactionToNextPaintRenderTime = elapsed(newInteraction.processingEnd, (newInteraction.startTime + newInteraction.duration) as RelativeTime) if (newInteraction.target && isElementNode(newInteraction.target)) { interactionToNextPaintTargetSelector = getSelectorFromElement( @@ -99,7 +111,11 @@ export function trackInteractionToNextPaint( return { value: Math.min(interactionToNextPaint, MAX_INP_VALUE) as Duration, targetSelector: interactionToNextPaintTargetSelector, + type: interactionToNextPaintType, time: interactionToNextPaintStartTime, + input: interactionToNextPaintInputTime, + process: interactionToNextPaintProcessingTime, + render: interactionToNextPaintRenderTime } } else if (getViewInteractionCount()) { return { diff --git a/packages/rum-core/src/rawRumEvent.types.ts b/packages/rum-core/src/rawRumEvent.types.ts index 482e3d46fe..27753676bb 100644 --- a/packages/rum-core/src/rawRumEvent.types.ts +++ b/packages/rum-core/src/rawRumEvent.types.ts @@ -98,6 +98,9 @@ export interface RawRumViewEvent { first_input_target_selector?: string interaction_to_next_paint?: ServerDuration interaction_to_next_paint_time?: ServerDuration + interaction_to_next_paint_input?: ServerDuration + interaction_to_next_paint_process?: ServerDuration + interaction_to_next_paint_render?: ServerDuration interaction_to_next_paint_target_selector?: string cumulative_layout_shift?: number cumulative_layout_shift_time?: ServerDuration diff --git a/packages/rum-core/src/rumEvent.types.ts b/packages/rum-core/src/rumEvent.types.ts index c9750326a2..568f683b4d 100644 --- a/packages/rum-core/src/rumEvent.types.ts +++ b/packages/rum-core/src/rumEvent.types.ts @@ -843,6 +843,18 @@ export type RumViewEvent = CommonProperties & * Duration in ns between start of the view and start of the INP */ readonly interaction_to_next_paint_time?: number + /** + * Duration in ns between interaction and start of processing + */ + readonly interaction_to_next_paint_input?: number + /** + * Duration in ns between start and end of processing + */ + readonly interaction_to_next_paint_process?: number + /** + * Duration in ns between end of processing and end of the INP + */ + readonly interaction_to_next_paint_render?: number /** * CSS selector path of the interacted element corresponding to INP */ From d1233bb59c6228b6d2081d1fdcf57183f7393e3c Mon Sep 17 00:00:00 2001 From: Antoine RICHARD Date: Mon, 30 Sep 2024 16:14:09 +0200 Subject: [PATCH 2/2] fix: type --- packages/rum-core/src/domain/view/viewCollection.spec.ts | 9 ++++++++- packages/rum-core/src/domain/view/viewCollection.ts | 1 + packages/rum-core/src/rawRumEvent.types.ts | 1 + packages/rum-core/src/rumEvent.types.ts | 4 ++++ 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/packages/rum-core/src/domain/view/viewCollection.spec.ts b/packages/rum-core/src/domain/view/viewCollection.spec.ts index 75f9f6329b..309f249195 100644 --- a/packages/rum-core/src/domain/view/viewCollection.spec.ts +++ b/packages/rum-core/src/domain/view/viewCollection.spec.ts @@ -58,7 +58,13 @@ const VIEW: ViewEvent = { commonViewMetrics: { loadingTime: 20 as Duration, cumulativeLayoutShift: { value: 1, time: 100 as Duration }, - interactionToNextPaint: { value: 10 as Duration, time: 100 as Duration, input: 2 as Duration, process: 5 as Duration, render: 3 as Duration }, + interactionToNextPaint: { + value: 10 as Duration, + time: 100 as Duration, + input: 2 as Duration, + process: 5 as Duration, + render: 3 as Duration, + }, scroll: { maxDepth: 2000, maxScrollHeight: 3000, @@ -154,6 +160,7 @@ describe('viewCollection', () => { first_input_target_selector: undefined, interaction_to_next_paint: (10 * 1e6) as ServerDuration, interaction_to_next_paint_target_selector: undefined, + interaction_to_next_paint_type: undefined, interaction_to_next_paint_time: (100 * 1e6) as ServerDuration, interaction_to_next_paint_input: (2 * 1e6) as ServerDuration, interaction_to_next_paint_process: (5 * 1e6) as ServerDuration, diff --git a/packages/rum-core/src/domain/view/viewCollection.ts b/packages/rum-core/src/domain/view/viewCollection.ts index 4577fb7aa6..8a44b63f57 100644 --- a/packages/rum-core/src/domain/view/viewCollection.ts +++ b/packages/rum-core/src/domain/view/viewCollection.ts @@ -86,6 +86,7 @@ function processViewUpdate( interaction_to_next_paint: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.value), interaction_to_next_paint_time: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.time), interaction_to_next_paint_target_selector: view.commonViewMetrics.interactionToNextPaint?.targetSelector, + interaction_to_next_paint_type: view.commonViewMetrics.interactionToNextPaint?.type, interaction_to_next_paint_input: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.input), interaction_to_next_paint_process: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.process), interaction_to_next_paint_render: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.render), diff --git a/packages/rum-core/src/rawRumEvent.types.ts b/packages/rum-core/src/rawRumEvent.types.ts index 27753676bb..f1fb2ce01a 100644 --- a/packages/rum-core/src/rawRumEvent.types.ts +++ b/packages/rum-core/src/rawRumEvent.types.ts @@ -102,6 +102,7 @@ export interface RawRumViewEvent { interaction_to_next_paint_process?: ServerDuration interaction_to_next_paint_render?: ServerDuration interaction_to_next_paint_target_selector?: string + interaction_to_next_paint_type?: string cumulative_layout_shift?: number cumulative_layout_shift_time?: ServerDuration cumulative_layout_shift_target_selector?: string diff --git a/packages/rum-core/src/rumEvent.types.ts b/packages/rum-core/src/rumEvent.types.ts index 568f683b4d..19611d7dd3 100644 --- a/packages/rum-core/src/rumEvent.types.ts +++ b/packages/rum-core/src/rumEvent.types.ts @@ -859,6 +859,10 @@ export type RumViewEvent = CommonProperties & * CSS selector path of the interacted element corresponding to INP */ readonly interaction_to_next_paint_target_selector?: string + /** + * Interaction type corresponding to INP + */ + readonly interaction_to_next_paint_target_type?: string /** * Total layout shift score that occurred on the view */