diff --git a/packages/core/src/tools/experimentalFeatures.ts b/packages/core/src/tools/experimentalFeatures.ts index 799a210e61..80831c87ce 100644 --- a/packages/core/src/tools/experimentalFeatures.ts +++ b/packages/core/src/tools/experimentalFeatures.ts @@ -16,7 +16,6 @@ export enum ExperimentalFeature { RESOURCE_PAGE_STATES = 'resource_page_states', COLLECT_FLUSH_REASON = 'collect_flush_reason', ZERO_LCP_TELEMETRY = 'zero_lcp_telemetry', - SCROLLMAP = 'scrollmap', DISABLE_REPLAY_INLINE_CSS = 'disable_replay_inline_css', } diff --git a/packages/rum-core/src/browser/performanceCollection.ts b/packages/rum-core/src/browser/performanceCollection.ts index 740cd58c44..e7f2d7167d 100644 --- a/packages/rum-core/src/browser/performanceCollection.ts +++ b/packages/rum-core/src/browser/performanceCollection.ts @@ -96,7 +96,7 @@ export interface RumLargestContentfulPaintTiming { startTime: RelativeTime size: number element?: Element - toJSON(): Omit + toJSON(): Omit } export interface RumFirstInputTiming { diff --git a/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.ts b/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.ts index 4c902e4c1c..0e1dec97ef 100644 --- a/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.ts +++ b/packages/rum-core/src/domain/view/viewMetrics/trackLargestContentfulPaint.ts @@ -26,8 +26,10 @@ export interface LargestContentfulPaint { targetSelector?: string } -let zeroLcpReported = false -let previousNonZeroLcp: Omit | undefined +type SerializableLCP = Omit + +let wrongLcpReported = false +let previousLcp: SerializableLCP /** * Track the largest contentful paint (LCP) occurring during the initial View. This can yield @@ -75,7 +77,13 @@ export function trackLargestContentfulPaint( } if (isExperimentalFeatureEnabled(ExperimentalFeature.ZERO_LCP_TELEMETRY)) { - monitorZeroLcpEntry(lcpEntry) + monitorLcpEntries( + lcpEntry, + entries.filter( + (entry): entry is RumLargestContentfulPaintTiming => + entry.entryType === RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT + ) + ) } callback({ @@ -94,24 +102,39 @@ export function trackLargestContentfulPaint( } } -function monitorZeroLcpEntry(lcpEntry: RumLargestContentfulPaintTiming) { - if (!zeroLcpReported && lcpEntry.startTime !== 0) { - previousNonZeroLcp = lcpEntry.toJSON() +function monitorLcpEntries(lcpEntry: RumLargestContentfulPaintTiming, lcpEntries: RumLargestContentfulPaintTiming[]) { + if (wrongLcpReported) { + return } - if (!zeroLcpReported && lcpEntry.startTime === 0) { - zeroLcpReported = true + const wrongLcpDetected = + lcpEntry.startTime === 0 + ? 'LCP with startTime = 0' + : previousLcp !== undefined && lcpEntry.startTime < previousLcp.startTime + ? 'LCP with startTime < previous LCP' + : previousLcp !== undefined && lcpEntry.size < previousLcp.size + ? 'LCP with size < previous LCP' + : undefined + + if (wrongLcpDetected) { + wrongLcpReported = true - addTelemetryDebug('LCP with startTime = 0', { + addTelemetryDebug(wrongLcpDetected, { debug: { - entry: lcpEntry.toJSON(), - previousNonZeroLcp, - navigationStart: performance.timing.navigationStart, + entry: toSerializableLCP(lcpEntry), + previousLcp, timeOrigin: performance.timeOrigin, now: relativeNow(), - visibilityState: document.visibilityState, - prerendering: (document as any).prerendering, + lcpEntries: lcpEntries.map(toSerializableLCP), }, }) } + + previousLcp = toSerializableLCP(lcpEntry) +} + +function toSerializableLCP(entry: RumLargestContentfulPaintTiming): SerializableLCP { + const jsonEntry = entry.toJSON() + delete jsonEntry.element + return jsonEntry }