Socket
Socket
Sign inDemoInstall

@datadog/browser-rum-core

Package Overview
Dependencies
Maintainers
1
Versions
177
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@datadog/browser-rum-core - npm Package Compare versions

Comparing version 4.49.0 to 4.50.0

cjs/domain/getSelectorFromElement.d.ts

4

cjs/boot/rumPublicApi.d.ts

@@ -1,2 +0,2 @@

import type { Context, InitConfiguration, RelativeTime, User, Observable } from '@datadog/browser-core';
import type { Context, InitConfiguration, User } from '@datadog/browser-core';
import type { LifeCycle } from '../domain/lifeCycle';

@@ -18,4 +18,2 @@ import type { ViewContexts } from '../domain/contexts/viewContexts';

getSessionReplayLink: (configuration: RumConfiguration, sessionManager: RumSessionManager, viewContexts: ViewContexts) => string | undefined;
getSerializedNodeId: (node: Node) => number | undefined;
recorderStartObservable: Observable<RelativeTime>;
}

@@ -22,0 +20,0 @@ interface RumPublicApiOptions {

@@ -27,3 +27,2 @@ "use strict";

var commonContext_1 = require("../domain/contexts/commonContext");
var startWebVitalTelemetryDebug_1 = require("../domain/view/startWebVitalTelemetryDebug");
var displayContext_1 = require("../domain/contexts/displayContext");

@@ -78,4 +77,3 @@ function startRum(initConfiguration, configuration, recorderApi, globalContextManager, userContextManager, initialViewOptions) {

(0, resourceCollection_1.startResourceCollection)(lifeCycle, configuration, session, pageStateHistory);
var webVitalTelemetryDebug = (0, startWebVitalTelemetryDebug_1.startWebVitalTelemetryDebug)(configuration, telemetry, recorderApi, session);
var _b = (0, viewCollection_1.startViewCollection)(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, webVitalTelemetryDebug, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView, stopViewCollection = _b.stop;
var _b = (0, viewCollection_1.startViewCollection)(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView, stopViewCollection = _b.stop;
cleanupTasks.push(stopViewCollection);

@@ -82,0 +80,0 @@ var addError = (0, errorCollection_1.startErrorCollection)(lifeCycle, configuration, pageStateHistory, featureFlagContexts).addError;

@@ -17,4 +17,14 @@ import type { Duration, RelativeTime } from '@datadog/browser-core';

}
export declare enum RumPerformanceEntryType {
EVENT = "event",
FIRST_INPUT = "first-input",
LARGEST_CONTENTFUL_PAINT = "largest-contentful-paint",
LAYOUT_SHIFT = "layout-shift",
LONG_TASK = "longtask",
NAVIGATION = "navigation",
PAINT = "paint",
RESOURCE = "resource"
}
export interface RumPerformanceResourceTiming {
entryType: 'resource';
entryType: RumPerformanceEntryType.RESOURCE;
initiatorType: string;

@@ -37,5 +47,6 @@ name: string;

traceId?: string;
toJSON(): PerformanceEntryRepresentation;
}
export interface RumPerformanceLongTaskTiming {
entryType: 'longtask';
entryType: RumPerformanceEntryType.LONG_TASK;
startTime: RelativeTime;

@@ -46,3 +57,3 @@ duration: Duration;

export interface RumPerformancePaintTiming {
entryType: 'paint';
entryType: RumPerformanceEntryType.PAINT;
name: 'first-paint' | 'first-contentful-paint';

@@ -52,3 +63,3 @@ startTime: RelativeTime;

export interface RumPerformanceNavigationTiming {
entryType: 'navigation';
entryType: RumPerformanceEntryType.NAVIGATION;
domComplete: RelativeTime;

@@ -61,3 +72,3 @@ domContentLoadedEventEnd: RelativeTime;

export interface RumLargestContentfulPaintTiming {
entryType: 'largest-contentful-paint';
entryType: RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT;
startTime: RelativeTime;

@@ -68,3 +79,3 @@ size: number;

export interface RumFirstInputTiming {
entryType: 'first-input';
entryType: RumPerformanceEntryType.FIRST_INPUT;
startTime: RelativeTime;

@@ -77,9 +88,10 @@ processingStart: RelativeTime;

export interface RumPerformanceEventTiming {
entryType: 'event';
entryType: RumPerformanceEntryType.EVENT;
startTime: RelativeTime;
duration: Duration;
interactionId?: number;
target?: Node;
}
export interface RumLayoutShiftTiming {
entryType: 'layout-shift';
entryType: RumPerformanceEntryType.LAYOUT_SHIFT;
startTime: RelativeTime;

@@ -93,3 +105,3 @@ value: number;

export type RumPerformanceEntry = RumPerformanceResourceTiming | RumPerformanceLongTaskTiming | RumPerformancePaintTiming | RumPerformanceNavigationTiming | RumLargestContentfulPaintTiming | RumFirstInputTiming | RumPerformanceEventTiming | RumLayoutShiftTiming;
export declare function supportPerformanceTimingEvent(entryType: string): boolean;
export declare function supportPerformanceTimingEvent(entryType: RumPerformanceEntryType): boolean;
export declare function startPerformanceCollection(lifeCycle: LifeCycle, configuration: RumConfiguration): void;

@@ -96,0 +108,0 @@ export declare function retrieveInitialDocumentResourceTiming(configuration: RumConfiguration, callback: (timing: RumPerformanceResourceTiming) => void): void;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.retrieveInitialDocumentResourceTiming = exports.startPerformanceCollection = exports.supportPerformanceTimingEvent = void 0;
exports.retrieveInitialDocumentResourceTiming = exports.startPerformanceCollection = exports.supportPerformanceTimingEvent = exports.RumPerformanceEntryType = void 0;
var browser_core_1 = require("@datadog/browser-core");
var resourceUtils_1 = require("../domain/resource/resourceUtils");
var getDocumentTraceId_1 = require("../domain/tracing/getDocumentTraceId");
// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary
// string is an expected performance entry
// eslint-disable-next-line no-restricted-syntax
var RumPerformanceEntryType;
(function (RumPerformanceEntryType) {
RumPerformanceEntryType["EVENT"] = "event";
RumPerformanceEntryType["FIRST_INPUT"] = "first-input";
RumPerformanceEntryType["LARGEST_CONTENTFUL_PAINT"] = "largest-contentful-paint";
RumPerformanceEntryType["LAYOUT_SHIFT"] = "layout-shift";
RumPerformanceEntryType["LONG_TASK"] = "longtask";
RumPerformanceEntryType["NAVIGATION"] = "navigation";
RumPerformanceEntryType["PAINT"] = "paint";
RumPerformanceEntryType["RESOURCE"] = "resource";
})(RumPerformanceEntryType || (exports.RumPerformanceEntryType = RumPerformanceEntryType = {}));
function supportPerformanceObject() {

@@ -30,4 +44,14 @@ return window.performance !== undefined && 'getEntries' in performance;

});
var mainEntries = ['resource', 'navigation', 'longtask', 'paint'];
var experimentalEntries = ['largest-contentful-paint', 'first-input', 'layout-shift', 'event'];
var mainEntries = [
RumPerformanceEntryType.RESOURCE,
RumPerformanceEntryType.NAVIGATION,
RumPerformanceEntryType.LONG_TASK,
RumPerformanceEntryType.PAINT,
];
var experimentalEntries = [
RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT,
RumPerformanceEntryType.FIRST_INPUT,
RumPerformanceEntryType.LAYOUT_SHIFT,
RumPerformanceEntryType.EVENT,
];
try {

@@ -62,3 +86,3 @@ // Experimental entries are not retrieved by performance.getEntries()

}
if (!supportPerformanceTimingEvent('navigation')) {
if (!supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION)) {
retrieveNavigationTiming(configuration, function (timing) {

@@ -68,3 +92,3 @@ handleRumPerformanceEntries(lifeCycle, configuration, [timing]);

}
if (!supportPerformanceTimingEvent('first-input')) {
if (!supportPerformanceTimingEvent(RumPerformanceEntryType.FIRST_INPUT)) {
retrieveFirstInputTiming(configuration, function (timing) {

@@ -80,8 +104,10 @@ handleRumPerformanceEntries(lifeCycle, configuration, [timing]);

var forcedAttributes = {
entryType: 'resource',
entryType: RumPerformanceEntryType.RESOURCE,
initiatorType: resourceUtils_1.FAKE_INITIAL_DOCUMENT,
traceId: (0, getDocumentTraceId_1.getDocumentTraceId)(document),
toJSON: function () { return (0, browser_core_1.assign)({}, timing, { toJSON: undefined }); },
};
if (supportPerformanceTimingEvent('navigation') && performance.getEntriesByType('navigation').length > 0) {
var navigationEntry = performance.getEntriesByType('navigation')[0];
if (supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION) &&
performance.getEntriesByType(RumPerformanceEntryType.NAVIGATION).length > 0) {
var navigationEntry = performance.getEntriesByType(RumPerformanceEntryType.NAVIGATION)[0];
timing = (0, browser_core_1.assign)(navigationEntry.toJSON(), forcedAttributes);

@@ -105,3 +131,3 @@ }

callback((0, browser_core_1.assign)(computeRelativePerformanceTiming(), {
entryType: 'navigation',
entryType: RumPerformanceEntryType.NAVIGATION,
}));

@@ -130,3 +156,3 @@ }

var timing = {
entryType: 'first-input',
entryType: RumPerformanceEntryType.FIRST_INPUT,
processingStart: (0, browser_core_1.relativeNow)(),

@@ -186,10 +212,3 @@ startTime: evt.timeStamp,

var rumPerformanceEntries = entries.filter(function (entry) {
return entry.entryType === 'resource' ||
entry.entryType === 'navigation' ||
entry.entryType === 'paint' ||
entry.entryType === 'longtask' ||
entry.entryType === 'largest-contentful-paint' ||
entry.entryType === 'first-input' ||
entry.entryType === 'layout-shift' ||
entry.entryType === 'event';
return (0, browser_core_1.objectHasValue)(RumPerformanceEntryType, entry.entryType);
});

@@ -202,7 +221,7 @@ var rumAllowedPerformanceEntries = rumPerformanceEntries.filter(function (entry) { return !isIncompleteNavigation(entry) && !isForbiddenResource(configuration, entry); });

function isIncompleteNavigation(entry) {
return entry.entryType === 'navigation' && entry.loadEventEnd <= 0;
return entry.entryType === RumPerformanceEntryType.NAVIGATION && entry.loadEventEnd <= 0;
}
function isForbiddenResource(configuration, entry) {
return entry.entryType === 'resource' && !(0, resourceUtils_1.isAllowedRequestUrl)(configuration, entry.name);
return entry.entryType === RumPerformanceEntryType.RESOURCE && !(0, resourceUtils_1.isAllowedRequestUrl)(configuration, entry.name);
}
//# sourceMappingURL=performanceCollection.js.map

@@ -7,5 +7,5 @@ "use strict";

var waitPageActivityEnd_1 = require("../waitPageActivityEnd");
var getSelectorFromElement_1 = require("../getSelectorFromElement");
var clickChain_1 = require("./clickChain");
var getActionNameFromElement_1 = require("./getActionNameFromElement");
var getSelectorFromElement_1 = require("./getSelectorFromElement");
var listenActionEvents_1 = require("./listenActionEvents");

@@ -12,0 +12,0 @@ var computeFrustration_1 = require("./computeFrustration");

@@ -60,3 +60,3 @@ "use strict";

},
browser_sdk_version: (0, browser_core_1.canUseEventBridge)() ? "4.49.0" : undefined,
browser_sdk_version: (0, browser_core_1.canUseEventBridge)() ? "4.50.0" : undefined,
},

@@ -63,0 +63,0 @@ application: {

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var performanceCollection_1 = require("../../browser/performanceCollection");
function startLongTaskCollection(lifeCycle, sessionManager) {

@@ -10,3 +11,3 @@ lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {

var entry = entries_1[_i];
if (entry.entryType !== 'longtask') {
if (entry.entryType !== performanceCollection_1.RumPerformanceEntryType.LONG_TASK) {
break;

@@ -13,0 +14,0 @@ }

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var performanceCollection_1 = require("../../browser/performanceCollection");
var matchRequestTiming_1 = require("./matchRequestTiming");

@@ -15,3 +16,3 @@ var resourceUtils_1 = require("./resourceUtils");

var entry = entries_1[_i];
if (entry.entryType === 'resource' && !(0, resourceUtils_1.isRequestKind)(entry)) {
if (entry.entryType === performanceCollection_1.RumPerformanceEntryType.RESOURCE && !(0, resourceUtils_1.isRequestKind)(entry)) {
lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processResourceEntry(entry, configuration, sessionManager, pageStateHistory));

@@ -18,0 +19,0 @@ }

@@ -9,3 +9,2 @@ import type { Duration, ClocksState, TimeStamp, RelativeTime } from '@datadog/browser-core';

import type { RumConfiguration } from '../configuration';
import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug';
import type { InitialViewMetrics } from './viewMetrics/trackInitialViewMetrics';

@@ -48,3 +47,3 @@ import type { CommonViewMetrics } from './viewMetrics/trackCommonViewMetrics';

}
export declare function trackViews(location: Location, lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, locationChangeObservable: Observable<LocationChange>, areViewsTrackedAutomatically: boolean, webVitalTelemetryDebug: WebVitalTelemetryDebug, initialViewOptions?: ViewOptions): {
export declare function trackViews(location: Location, lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, locationChangeObservable: Observable<LocationChange>, areViewsTrackedAutomatically: boolean, initialViewOptions?: ViewOptions): {
addTiming: (name: string, time?: RelativeTime | TimeStamp) => void;

@@ -51,0 +50,0 @@ startView: (options?: ViewOptions, startClocks?: ClocksState) => void;

@@ -17,3 +17,3 @@ "use strict";

exports.KEEP_TRACKING_AFTER_VIEW_DELAY = 5 * browser_core_1.ONE_MINUTE;
function trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, areViewsTrackedAutomatically, webVitalTelemetryDebug, initialViewOptions) {
function trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, areViewsTrackedAutomatically, initialViewOptions) {
var activeViews = new Set();

@@ -27,3 +27,3 @@ var currentView = startNewView("initial_load" /* ViewLoadingType.INITIAL_LOAD */, (0, browser_core_1.clocksOrigin)(), initialViewOptions);

function startNewView(loadingType, startClocks, viewOptions) {
var newlyCreatedView = newView(lifeCycle, domMutationObservable, configuration, location, loadingType, webVitalTelemetryDebug, startClocks, viewOptions);
var newlyCreatedView = newView(lifeCycle, domMutationObservable, configuration, location, loadingType, startClocks, viewOptions);
activeViews.add(newlyCreatedView);

@@ -80,3 +80,3 @@ newlyCreatedView.stopObservable.subscribe(function () {

exports.trackViews = trackViews;
function newView(lifeCycle, domMutationObservable, configuration, initialLocation, loadingType, webVitalTelemetryDebug, startClocks, viewOptions) {
function newView(lifeCycle, domMutationObservable, configuration, initialLocation, loadingType, startClocks, viewOptions) {
if (startClocks === void 0) { startClocks = (0, browser_core_1.clocksNow)(); }

@@ -110,5 +110,5 @@ // Setup initial values

}), scheduleViewUpdate = _a.throttled, cancelScheduleViewUpdate = _a.cancel;
var _b = (0, trackCommonViewMetrics_1.trackCommonViewMetrics)(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks, webVitalTelemetryDebug), setLoadEvent = _b.setLoadEvent, stopCommonViewMetricsTracking = _b.stop, getCommonViewMetrics = _b.getCommonViewMetrics;
var _b = (0, trackCommonViewMetrics_1.trackCommonViewMetrics)(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks), setLoadEvent = _b.setLoadEvent, stopCommonViewMetricsTracking = _b.stop, getCommonViewMetrics = _b.getCommonViewMetrics;
var _c = loadingType === "initial_load" /* ViewLoadingType.INITIAL_LOAD */
? (0, trackInitialViewMetrics_1.trackInitialViewMetrics)(lifeCycle, configuration, webVitalTelemetryDebug, setLoadEvent, scheduleViewUpdate)
? (0, trackInitialViewMetrics_1.trackInitialViewMetrics)(lifeCycle, configuration, setLoadEvent, scheduleViewUpdate)
: { stop: browser_core_1.noop, initialViewMetrics: {} }, stopInitialViewMetricsTracking = _c.stop, initialViewMetrics = _c.initialViewMetrics;

@@ -115,0 +115,0 @@ var _d = (0, trackViewEventCounts_1.trackViewEventCounts)(lifeCycle, id, scheduleViewUpdate), stopEventCountsTracking = _d.stop, eventCounts = _d.eventCounts;

@@ -9,4 +9,3 @@ import type { Observable } from '@datadog/browser-core';

import type { ViewOptions } from './trackViews';
import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug';
export declare function startViewCollection(lifeCycle: LifeCycle, configuration: RumConfiguration, location: Location, domMutationObservable: Observable<void>, locationChangeObservable: Observable<LocationChange>, featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, webVitalTelemetryDebug: WebVitalTelemetryDebug, initialViewOptions?: ViewOptions): {
export declare function startViewCollection(lifeCycle: LifeCycle, configuration: RumConfiguration, location: Location, domMutationObservable: Observable<void>, locationChangeObservable: Observable<LocationChange>, featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, initialViewOptions?: ViewOptions): {
addTiming: (name: string, time?: import("@datadog/browser-core").TimeStamp | import("@datadog/browser-core").RelativeTime) => void;

@@ -13,0 +12,0 @@ startView: (options?: ViewOptions | undefined, startClocks?: import("@datadog/browser-core").ClocksState | undefined) => void;

@@ -7,10 +7,11 @@ "use strict";

var trackViews_1 = require("./trackViews");
function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, webVitalTelemetryDebug, initialViewOptions) {
function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions) {
lifeCycle.subscribe(3 /* LifeCycleEventType.VIEW_UPDATED */, function (view) {
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory));
});
return (0, trackViews_1.trackViews)(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, !configuration.trackViewsManually, webVitalTelemetryDebug, initialViewOptions);
return (0, trackViews_1.trackViews)(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, !configuration.trackViewsManually, initialViewOptions);
}
exports.startViewCollection = startViewCollection;
function processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
var replayStats = recorderApi.getReplayStats(view.id);

@@ -35,7 +36,8 @@ var featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(view.startClocks.relative);

},
cumulative_layout_shift: view.commonViewMetrics.cumulativeLayoutShift,
first_byte: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.firstByte),
dom_complete: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.domComplete),
dom_content_loaded: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.domContentLoaded),
dom_interactive: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.domInteractive),
cumulative_layout_shift: (_a = view.commonViewMetrics.cumulativeLayoutShift) === null || _a === void 0 ? void 0 : _a.value,
cumulative_layout_shift_target_selector: (_b = view.commonViewMetrics.cumulativeLayoutShift) === null || _b === void 0 ? void 0 : _b.targetSelector,
first_byte: (0, browser_core_1.toServerDuration)((_c = view.initialViewMetrics.navigationTimings) === null || _c === void 0 ? void 0 : _c.firstByte),
dom_complete: (0, browser_core_1.toServerDuration)((_d = view.initialViewMetrics.navigationTimings) === null || _d === void 0 ? void 0 : _d.domComplete),
dom_content_loaded: (0, browser_core_1.toServerDuration)((_e = view.initialViewMetrics.navigationTimings) === null || _e === void 0 ? void 0 : _e.domContentLoaded),
dom_interactive: (0, browser_core_1.toServerDuration)((_f = view.initialViewMetrics.navigationTimings) === null || _f === void 0 ? void 0 : _f.domInteractive),
error: {

@@ -45,9 +47,12 @@ count: view.eventCounts.errorCount,

first_contentful_paint: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.firstContentfulPaint),
first_input_delay: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.firstInputDelay),
first_input_time: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.firstInputTime),
interaction_to_next_paint: (0, browser_core_1.toServerDuration)(view.commonViewMetrics.interactionToNextPaint),
first_input_delay: (0, browser_core_1.toServerDuration)((_g = view.initialViewMetrics.firstInput) === null || _g === void 0 ? void 0 : _g.delay),
first_input_time: (0, browser_core_1.toServerDuration)((_h = view.initialViewMetrics.firstInput) === null || _h === void 0 ? void 0 : _h.time),
first_input_target_selector: (_j = view.initialViewMetrics.firstInput) === null || _j === void 0 ? void 0 : _j.targetSelector,
interaction_to_next_paint: (0, browser_core_1.toServerDuration)((_k = view.commonViewMetrics.interactionToNextPaint) === null || _k === void 0 ? void 0 : _k.value),
interaction_to_next_paint_target_selector: (_l = view.commonViewMetrics.interactionToNextPaint) === null || _l === void 0 ? void 0 : _l.targetSelector,
is_active: view.isActive,
name: view.name,
largest_contentful_paint: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.largestContentfulPaint),
load_event: (0, browser_core_1.toServerDuration)(view.initialViewMetrics.loadEvent),
largest_contentful_paint: (0, browser_core_1.toServerDuration)((_m = view.initialViewMetrics.largestContentfulPaint) === null || _m === void 0 ? void 0 : _m.value),
largest_contentful_paint_target_selector: (_o = view.initialViewMetrics.largestContentfulPaint) === null || _o === void 0 ? void 0 : _o.targetSelector,
load_event: (0, browser_core_1.toServerDuration)((_p = view.initialViewMetrics.navigationTimings) === null || _p === void 0 ? void 0 : _p.loadEvent),
loading_time: discardNegativeDuration((0, browser_core_1.toServerDuration)(view.commonViewMetrics.loadingTime)),

@@ -69,5 +74,5 @@ loading_type: view.loadingType,

max_depth: view.commonViewMetrics.scroll.maxDepth,
max_depth_scroll_height: view.commonViewMetrics.scroll.maxDepthScrollHeight,
max_depth_scroll_top: view.commonViewMetrics.scroll.maxDepthScrollTop,
max_depth_time: (0, browser_core_1.toServerDuration)(view.commonViewMetrics.scroll.maxDepthTime),
max_scroll_height: view.commonViewMetrics.scroll.maxScrollHeight,
max_scroll_height_time: (0, browser_core_1.toServerDuration)(view.commonViewMetrics.scroll.maxScrollHeightTime),
},

@@ -74,0 +79,0 @@ }

@@ -5,11 +5,12 @@ import type { ClocksState, Duration, Observable } from '@datadog/browser-core';

import type { LifeCycle } from '../../lifeCycle';
import type { WebVitalTelemetryDebug } from '../startWebVitalTelemetryDebug';
import type { CumulativeLayoutShift } from './trackCumulativeLayoutShift';
import type { InteractionToNextPaint } from './trackInteractionToNextPaint';
import type { ScrollMetrics } from './trackScrollMetrics';
export interface CommonViewMetrics {
loadingTime?: Duration;
cumulativeLayoutShift?: number;
interactionToNextPaint?: Duration;
cumulativeLayoutShift?: CumulativeLayoutShift;
interactionToNextPaint?: InteractionToNextPaint;
scroll?: ScrollMetrics;
}
export declare function trackCommonViewMetrics(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, scheduleViewUpdate: () => void, loadingType: ViewLoadingType, viewStart: ClocksState, webVitalTelemetryDebug: WebVitalTelemetryDebug): {
export declare function trackCommonViewMetrics(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, scheduleViewUpdate: () => void, loadingType: ViewLoadingType, viewStart: ClocksState): {
stop: () => void;

@@ -16,0 +17,0 @@ setLoadEvent: (loadEvent: Duration) => void;

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.trackCommonViewMetrics = void 0;
var browser_core_1 = require("@datadog/browser-core");
var trackScrollMetrics_1 = require("./trackScrollMetrics");
var trackLoadingTime_1 = require("./trackLoadingTime");
var trackCumulativeLayoutShift_1 = require("./trackCumulativeLayoutShift");
var trackInteractionToNextPaint_1 = require("./trackInteractionToNextPaint");
function trackCommonViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, viewStart, webVitalTelemetryDebug) {
var trackLoadingTime_1 = require("./trackLoadingTime");
var trackScrollMetrics_1 = require("./trackScrollMetrics");
function trackCommonViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, viewStart) {
var commonViewMetrics = {};
var _a = (0, trackLoadingTime_1.trackLoadingTime)(lifeCycle, domMutationObservable, configuration, loadingType, viewStart, function (newLoadingTime) {
commonViewMetrics.loadingTime = newLoadingTime;
// We compute scroll metrics at loading time to ensure we have scroll data when loading the view initially
// This is to ensure that we have the depth data even if the user didn't scroll or if the view is not scrollable.
var _a = (0, trackScrollMetrics_1.computeScrollValues)(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop;
commonViewMetrics.scroll = {
maxDepth: scrollDepth,
maxDepthScrollHeight: scrollHeight,
maxDepthTime: newLoadingTime,
maxDepthScrollTop: scrollTop,
};
scheduleViewUpdate();

@@ -26,20 +16,8 @@ }), stopLoadingTimeTracking = _a.stop, setLoadEvent = _a.setLoadEvent;

commonViewMetrics.scroll = newScrollMetrics;
}, trackScrollMetrics_1.computeScrollValues).stop;
var stopCLSTracking;
var clsAttributionCollected = false;
if ((0, trackCumulativeLayoutShift_1.isLayoutShiftSupported)()) {
commonViewMetrics.cumulativeLayoutShift = 0;
(stopCLSTracking = (0, trackCumulativeLayoutShift_1.trackCumulativeLayoutShift)(lifeCycle, function (cumulativeLayoutShift, largestLayoutShiftNode, largestLayoutShiftTime) {
commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift;
if (!clsAttributionCollected) {
clsAttributionCollected = true;
webVitalTelemetryDebug.addWebVitalTelemetryDebug('CLS', largestLayoutShiftNode, largestLayoutShiftTime);
}
scheduleViewUpdate();
}).stop);
}
else {
stopCLSTracking = browser_core_1.noop;
}
var _b = (0, trackInteractionToNextPaint_1.trackInteractionToNextPaint)(loadingType, lifeCycle), stopINPTracking = _b.stop, getInteractionToNextPaint = _b.getInteractionToNextPaint;
}).stop;
var stopCLSTracking = (0, trackCumulativeLayoutShift_1.trackCumulativeLayoutShift)(configuration, lifeCycle, function (cumulativeLayoutShift) {
commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift;
scheduleViewUpdate();
}).stop;
var _b = (0, trackInteractionToNextPaint_1.trackInteractionToNextPaint)(configuration, loadingType, lifeCycle), stopINPTracking = _b.stop, getInteractionToNextPaint = _b.getInteractionToNextPaint;
return {

@@ -46,0 +24,0 @@ stop: function () {

@@ -1,3 +0,8 @@

import { type RelativeTime } from '@datadog/browser-core';
import { noop } from '@datadog/browser-core';
import type { LifeCycle } from '../../lifeCycle';
import type { RumConfiguration } from '../../configuration';
export interface CumulativeLayoutShift {
value: number;
targetSelector?: string;
}
/**

@@ -20,4 +25,4 @@ * Track the cumulative layout shifts (CLS).

*/
export declare function trackCumulativeLayoutShift(lifeCycle: LifeCycle, callback: (layoutShift: number, largestShiftNode: Node | undefined, largestShiftTime: RelativeTime) => void): {
stop: () => void;
export declare function trackCumulativeLayoutShift(configuration: RumConfiguration, lifeCycle: LifeCycle, callback: (cumulativeLayoutShift: CumulativeLayoutShift) => void): {
stop: typeof noop;
};

@@ -24,0 +29,0 @@ /**

@@ -5,3 +5,5 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var htmlDomUtils_1 = require("../../../browser/htmlDomUtils");
var performanceCollection_1 = require("../../../browser/performanceCollection");
var getSelectorFromElement_1 = require("../../getSelectorFromElement");
/**

@@ -24,4 +26,13 @@ * Track the cumulative layout shifts (CLS).

*/
function trackCumulativeLayoutShift(lifeCycle, callback) {
function trackCumulativeLayoutShift(configuration, lifeCycle, callback) {
if (!isLayoutShiftSupported()) {
return {
stop: browser_core_1.noop,
};
}
var maxClsValue = 0;
// if no layout shift happen the value should be reported as 0
callback({
value: 0,
});
var window = slidingSessionWindow();

@@ -31,7 +42,16 @@ var stop = lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {

var entry = entries_1[_i];
if (entry.entryType === 'layout-shift' && !entry.hadRecentInput) {
if (entry.entryType === performanceCollection_1.RumPerformanceEntryType.LAYOUT_SHIFT && !entry.hadRecentInput) {
window.update(entry);
if (window.value() > maxClsValue) {
maxClsValue = window.value();
callback((0, browser_core_1.round)(maxClsValue, 4), window.largestLayoutShiftNode(), window.largestLayoutShiftTime());
var cls = (0, browser_core_1.round)(maxClsValue, 4);
var clsTarget = window.largestLayoutShiftTarget();
var cslTargetSelector = void 0;
if ((0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.WEB_VITALS_ATTRIBUTION) && clsTarget) {
cslTargetSelector = (0, getSelectorFromElement_1.getSelectorFromElement)(clsTarget, configuration.actionNameAttribute);
}
callback({
value: cls,
targetSelector: cslTargetSelector,
});
}

@@ -51,7 +71,7 @@ }

var largestLayoutShift = 0;
var largestLayoutShiftNode;
var largestLayoutShiftTarget;
var largestLayoutShiftTime;
return {
update: function (entry) {
var _a;
var _a, _b;
var shouldCreateNewWindow = startTime === undefined ||

@@ -64,3 +84,3 @@ entry.startTime - endTime >= browser_core_1.ONE_SECOND ||

largestLayoutShift = 0;
largestLayoutShiftNode = undefined;
largestLayoutShiftTarget = undefined;
}

@@ -75,7 +95,6 @@ else {

if ((_a = entry.sources) === null || _a === void 0 ? void 0 : _a.length) {
var largestLayoutShiftSource = (0, browser_core_1.find)(entry.sources, function (s) { var _a; return ((_a = s.node) === null || _a === void 0 ? void 0 : _a.nodeType) === 1; }) || entry.sources[0];
largestLayoutShiftNode = largestLayoutShiftSource.node;
largestLayoutShiftTarget = (_b = (0, browser_core_1.find)(entry.sources, function (s) { return !!s.node && (0, htmlDomUtils_1.isElementNode)(s.node); })) === null || _b === void 0 ? void 0 : _b.node;
}
else {
largestLayoutShiftNode = undefined;
largestLayoutShiftTarget = undefined;
}

@@ -85,3 +104,3 @@ }

value: function () { return value; },
largestLayoutShiftNode: function () { return largestLayoutShiftNode; },
largestLayoutShiftTarget: function () { return largestLayoutShiftTarget; },
largestLayoutShiftTime: function () { return largestLayoutShiftTime; },

@@ -94,5 +113,5 @@ };

function isLayoutShiftSupported() {
return (0, performanceCollection_1.supportPerformanceTimingEvent)('layout-shift');
return (0, performanceCollection_1.supportPerformanceTimingEvent)(performanceCollection_1.RumPerformanceEntryType.LAYOUT_SHIFT);
}
exports.isLayoutShiftSupported = isLayoutShiftSupported;
//# sourceMappingURL=trackCumulativeLayoutShift.js.map

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var performanceCollection_1 = require("../../../browser/performanceCollection");
// Discard FCP timings above a certain delay to avoid incorrect data

@@ -12,3 +13,3 @@ // It happens in some cases like sleep mode or some browser implementations

var fcpEntry = (0, browser_core_1.find)(entries, function (entry) {
return entry.entryType === 'paint' &&
return entry.entryType === performanceCollection_1.RumPerformanceEntryType.PAINT &&
entry.name === 'first-contentful-paint' &&

@@ -15,0 +16,0 @@ entry.startTime < firstHidden.timeStamp &&

import type { Duration } from '@datadog/browser-core';
import type { RumConfiguration } from '../../configuration';
import type { LifeCycle } from '../../lifeCycle';
import type { WebVitalTelemetryDebug } from '../startWebVitalTelemetryDebug';
import type { FirstInput } from './trackFirstInput';
import type { NavigationTimings } from './trackNavigationTimings';
import type { LargestContentfulPaint } from './trackLargestContentfulPaint';
export interface InitialViewMetrics {
firstContentfulPaint?: Duration;
firstByte?: Duration;
domInteractive?: Duration;
domContentLoaded?: Duration;
domComplete?: Duration;
loadEvent?: Duration;
largestContentfulPaint?: Duration;
firstInputDelay?: Duration;
firstInputTime?: Duration;
navigationTimings?: NavigationTimings;
largestContentfulPaint?: LargestContentfulPaint;
firstInput?: FirstInput;
}
export declare function trackInitialViewMetrics(lifeCycle: LifeCycle, configuration: RumConfiguration, webVitalTelemetryDebug: WebVitalTelemetryDebug, setLoadEvent: (loadEnd: Duration) => void, scheduleViewUpdate: () => void): {
export declare function trackInitialViewMetrics(lifeCycle: LifeCycle, configuration: RumConfiguration, setLoadEvent: (loadEnd: Duration) => void, scheduleViewUpdate: () => void): {
stop: () => void;
initialViewMetrics: InitialViewMetrics;
};
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.trackInitialViewMetrics = void 0;
var browser_core_1 = require("@datadog/browser-core");
var trackFirstContentfulPaint_1 = require("./trackFirstContentfulPaint");
var trackFirstInputTimings_1 = require("./trackFirstInputTimings");
var trackFirstInput_1 = require("./trackFirstInput");
var trackNavigationTimings_1 = require("./trackNavigationTimings");
var trackLargestContentfulPaint_1 = require("./trackLargestContentfulPaint");
var trackFirstHidden_1 = require("./trackFirstHidden");
function trackInitialViewMetrics(lifeCycle, configuration, webVitalTelemetryDebug, setLoadEvent, scheduleViewUpdate) {
function trackInitialViewMetrics(lifeCycle, configuration, setLoadEvent, scheduleViewUpdate) {
var initialViewMetrics = {};
function setMetrics(newMetrics) {
(0, browser_core_1.assign)(initialViewMetrics, newMetrics);
scheduleViewUpdate();
}
var stopNavigationTracking = (0, trackNavigationTimings_1.trackNavigationTimings)(lifeCycle, function (navigationTimings) {
setLoadEvent(navigationTimings.loadEvent);
setMetrics(navigationTimings);
initialViewMetrics.navigationTimings = navigationTimings;
scheduleViewUpdate();
}).stop;
var firstHidden = (0, trackFirstHidden_1.trackFirstHidden)(configuration);
var stopFCPTracking = (0, trackFirstContentfulPaint_1.trackFirstContentfulPaint)(lifeCycle, firstHidden, function (firstContentfulPaint) {
return setMetrics({ firstContentfulPaint: firstContentfulPaint });
initialViewMetrics.firstContentfulPaint = firstContentfulPaint;
scheduleViewUpdate();
}).stop;
var stopLCPTracking = (0, trackLargestContentfulPaint_1.trackLargestContentfulPaint)(lifeCycle, configuration, firstHidden, window, function (largestContentfulPaint, lcpElement) {
webVitalTelemetryDebug.addWebVitalTelemetryDebug('LCP', lcpElement, largestContentfulPaint);
setMetrics({
largestContentfulPaint: largestContentfulPaint,
});
var stopLCPTracking = (0, trackLargestContentfulPaint_1.trackLargestContentfulPaint)(lifeCycle, configuration, firstHidden, window, function (largestContentfulPaint) {
initialViewMetrics.largestContentfulPaint = largestContentfulPaint;
scheduleViewUpdate();
}).stop;
var stopFIDTracking = (0, trackFirstInputTimings_1.trackFirstInputTimings)(lifeCycle, firstHidden, function (_a) {
var firstInputDelay = _a.firstInputDelay, firstInputTime = _a.firstInputTime, firstInputTarget = _a.firstInputTarget;
webVitalTelemetryDebug.addWebVitalTelemetryDebug('FID', firstInputTarget, firstInputTime);
setMetrics({
firstInputDelay: firstInputDelay,
firstInputTime: firstInputTime,
});
var stopFIDTracking = (0, trackFirstInput_1.trackFirstInput)(lifeCycle, configuration, firstHidden, function (firstInput) {
initialViewMetrics.firstInput = firstInput;
scheduleViewUpdate();
}).stop;

@@ -38,0 +29,0 @@ function stop() {

import type { Duration } from '@datadog/browser-core';
import { type LifeCycle } from '../../lifeCycle';
import type { LifeCycle } from '../../lifeCycle';
import { ViewLoadingType } from '../../../rawRumEvent.types';
import type { RumConfiguration } from '../../configuration';
export interface InteractionToNextPaint {
value: Duration;
targetSelector?: string;
}
/**

@@ -10,4 +15,4 @@ * Track the interaction to next paint (INP).

*/
export declare function trackInteractionToNextPaint(viewLoadingType: ViewLoadingType, lifeCycle: LifeCycle): {
getInteractionToNextPaint: () => Duration | undefined;
export declare function trackInteractionToNextPaint(configuration: RumConfiguration, viewLoadingType: ViewLoadingType, lifeCycle: LifeCycle): {
getInteractionToNextPaint: () => InteractionToNextPaint | undefined;
stop: () => void;

@@ -14,0 +19,0 @@ };

@@ -6,2 +6,4 @@ "use strict";

var performanceCollection_1 = require("../../../browser/performanceCollection");
var getSelectorFromElement_1 = require("../../getSelectorFromElement");
var htmlDomUtils_1 = require("../../../browser/htmlDomUtils");
var interactionCountPolyfill_1 = require("./interactionCountPolyfill");

@@ -16,3 +18,3 @@ // Arbitrary value to prevent unnecessary memory usage on views with lots of interactions.

*/
function trackInteractionToNextPaint(viewLoadingType, lifeCycle) {
function trackInteractionToNextPaint(configuration, viewLoadingType, lifeCycle) {
if (!isInteractionToNextPaintSupported() ||

@@ -27,13 +29,24 @@ !(0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.INTERACTION_TO_NEXT_PAINT)) {

var longestInteractions = trackLongestInteractions(getViewInteractionCount);
var inpDuration = -1;
var interactionToNextPaint = -1;
var interactionToNextPaintTargetSelector;
var stop = lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
var entry = entries_1[_i];
if ((entry.entryType === 'event' || entry.entryType === 'first-input') && entry.interactionId) {
if ((entry.entryType === performanceCollection_1.RumPerformanceEntryType.EVENT ||
entry.entryType === performanceCollection_1.RumPerformanceEntryType.FIRST_INPUT) &&
entry.interactionId) {
longestInteractions.process(entry);
}
}
var newInpDuration = longestInteractions.estimateP98Duration();
if (newInpDuration) {
inpDuration = newInpDuration;
var newInteraction = longestInteractions.estimateP98Interaction();
if (newInteraction) {
interactionToNextPaint = newInteraction.duration;
if ((0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.WEB_VITALS_ATTRIBUTION) &&
newInteraction.target &&
(0, htmlDomUtils_1.isElementNode)(newInteraction.target)) {
interactionToNextPaintTargetSelector = (0, getSelectorFromElement_1.getSelectorFromElement)(newInteraction.target, configuration.actionNameAttribute);
}
else {
interactionToNextPaintTargetSelector = undefined;
}
}

@@ -45,7 +58,12 @@ }).unsubscribe;

// but the view interaction count > 0 then report 0
if (inpDuration >= 0) {
return inpDuration;
if (interactionToNextPaint >= 0) {
return {
value: interactionToNextPaint,
targetSelector: interactionToNextPaintTargetSelector,
};
}
else if (getViewInteractionCount()) {
return 0;
return {
value: 0,
};
}

@@ -87,6 +105,5 @@ },

*/
estimateP98Duration: function () {
var _a;
estimateP98Interaction: function () {
var interactionIndex = Math.min(longestInteractions.length - 1, Math.floor(getViewInteractionCount() / 50));
return (_a = longestInteractions[interactionIndex]) === null || _a === void 0 ? void 0 : _a.duration;
return longestInteractions[interactionIndex];
},

@@ -104,3 +121,3 @@ };

function isInteractionToNextPaintSupported() {
return ((0, performanceCollection_1.supportPerformanceTimingEvent)('event') &&
return ((0, performanceCollection_1.supportPerformanceTimingEvent)(performanceCollection_1.RumPerformanceEntryType.EVENT) &&
window.PerformanceEventTiming &&

@@ -107,0 +124,0 @@ 'interactionId' in PerformanceEventTiming.prototype);

import type { RelativeTime } from '@datadog/browser-core';
import { type LifeCycle } from '../../lifeCycle';
import type { LifeCycle } from '../../lifeCycle';
import type { RumConfiguration } from '../../configuration';
import type { FirstHidden } from './trackFirstHidden';
export declare const LCP_MAXIMUM_DELAY: number;
export interface LargestContentfulPaint {
value: RelativeTime;
targetSelector?: string;
}
/**

@@ -10,6 +14,6 @@ * Track the largest contentful paint (LCP) occurring during the initial View. This can yield

* Documentation: https://web.dev/lcp/
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getLCP.ts
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/onLCP.ts
*/
export declare function trackLargestContentfulPaint(lifeCycle: LifeCycle, configuration: RumConfiguration, firstHidden: FirstHidden, eventTarget: Window, callback: (lcpTiming: RelativeTime, lcpElement?: Element) => void): {
export declare function trackLargestContentfulPaint(lifeCycle: LifeCycle, configuration: RumConfiguration, firstHidden: FirstHidden, eventTarget: Window, callback: (largestContentfulPaint: LargestContentfulPaint) => void): {
stop: () => void;
};

@@ -5,2 +5,4 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var performanceCollection_1 = require("../../../browser/performanceCollection");
var getSelectorFromElement_1 = require("../../getSelectorFromElement");
// Discard LCP timings above a certain delay to avoid incorrect data

@@ -13,3 +15,3 @@ // It happens in some cases like sleep mode or some browser implementations

* Documentation: https://web.dev/lcp/
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getLCP.ts
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/onLCP.ts
*/

@@ -26,3 +28,3 @@ function trackLargestContentfulPaint(lifeCycle, configuration, firstHidden, eventTarget, callback) {

var lcpEntry = (0, browser_core_1.findLast)(entries, function (entry) {
return entry.entryType === 'largest-contentful-paint' &&
return entry.entryType === performanceCollection_1.RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT &&
entry.startTime < firstInteractionTimestamp &&

@@ -33,3 +35,10 @@ entry.startTime < firstHidden.timeStamp &&

if (lcpEntry) {
callback(lcpEntry.startTime, lcpEntry.element);
var lcpTargetSelector = void 0;
if ((0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.WEB_VITALS_ATTRIBUTION) && lcpEntry.element) {
lcpTargetSelector = (0, getSelectorFromElement_1.getSelectorFromElement)(lcpEntry.element, configuration.actionNameAttribute);
}
callback({
value: lcpEntry.startTime,
targetSelector: lcpTargetSelector,
});
}

@@ -36,0 +45,0 @@ }).unsubscribe;

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var performanceCollection_1 = require("../../../browser/performanceCollection");
function trackNavigationTimings(lifeCycle, callback) {

@@ -10,3 +11,3 @@ var stop = lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {

var entry = entries_1[_i];
if (entry.entryType === 'navigation') {
if (entry.entryType === performanceCollection_1.RumPerformanceEntryType.NAVIGATION) {
callback({

@@ -13,0 +14,0 @@ domComplete: entry.domComplete,

import type { ClocksState, Duration } from '@datadog/browser-core';
import { Observable } from '@datadog/browser-core';
import type { RumConfiguration } from '../../configuration';

@@ -7,9 +8,14 @@ /** Arbitrary scroll throttle duration */

maxDepth: number;
maxDepthScrollHeight: number;
maxScrollHeight: number;
maxDepthScrollTop: number;
maxDepthTime: Duration;
maxScrollHeightTime: Duration;
}
export declare function trackScrollMetrics(configuration: RumConfiguration, viewStart: ClocksState, callback: (scrollMetrics: ScrollMetrics) => void, getScrollValues?: typeof computeScrollValues): {
export declare function trackScrollMetrics(configuration: RumConfiguration, viewStart: ClocksState, callback: (scrollMetrics: ScrollMetrics) => void, scrollValues?: Observable<ScrollValues>): {
stop: () => void;
};
export interface ScrollValues {
scrollDepth: number;
scrollTop: number;
scrollHeight: number;
}
export declare function computeScrollValues(): {

@@ -20,1 +26,2 @@ scrollHeight: number;

};
export declare function createScrollValuesObservable(configuration: RumConfiguration, throttleDuration?: number): Observable<ScrollValues>;
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.computeScrollValues = exports.trackScrollMetrics = exports.THROTTLE_SCROLL_DURATION = void 0;
exports.createScrollValuesObservable = exports.computeScrollValues = exports.trackScrollMetrics = exports.THROTTLE_SCROLL_DURATION = void 0;
var browser_core_1 = require("@datadog/browser-core");

@@ -9,27 +9,31 @@ var scroll_1 = require("../../../browser/scroll");

exports.THROTTLE_SCROLL_DURATION = browser_core_1.ONE_SECOND;
function trackScrollMetrics(configuration, viewStart, callback, getScrollValues) {
if (getScrollValues === void 0) { getScrollValues = computeScrollValues; }
var maxDepth = 0;
var handleScrollEvent = (0, browser_core_1.throttle)(function () {
var _a = getScrollValues(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop;
if (scrollDepth > maxDepth) {
function trackScrollMetrics(configuration, viewStart, callback, scrollValues) {
if (scrollValues === void 0) { scrollValues = createScrollValuesObservable(configuration); }
var maxScrollDepth = 0;
var maxScrollHeight = 0;
var maxScrollHeightTime = 0;
var subscription = scrollValues.subscribe(function (_a) {
var scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop, scrollHeight = _a.scrollHeight;
var shouldUpdate = false;
if (scrollDepth > maxScrollDepth) {
maxScrollDepth = scrollDepth;
shouldUpdate = true;
}
if (scrollHeight > maxScrollHeight) {
maxScrollHeight = scrollHeight;
var now = (0, browser_core_1.relativeNow)();
var maxDepthTime = (0, browser_core_1.elapsed)(viewStart.relative, now);
maxDepth = scrollDepth;
maxScrollHeightTime = (0, browser_core_1.elapsed)(viewStart.relative, now);
shouldUpdate = true;
}
if (shouldUpdate) {
callback({
maxDepth: maxDepth,
maxDepthScrollHeight: scrollHeight,
maxDepthTime: maxDepthTime,
maxDepth: Math.min(maxScrollDepth, maxScrollHeight),
maxDepthScrollTop: scrollTop,
maxScrollHeight: maxScrollHeight,
maxScrollHeightTime: maxScrollHeightTime,
});
}
}, exports.THROTTLE_SCROLL_DURATION, { leading: false, trailing: true });
var stop = (0, browser_core_1.addEventListener)(configuration, window, "scroll" /* DOM_EVENT.SCROLL */, handleScrollEvent.throttled, {
passive: true,
}).stop;
});
return {
stop: function () {
handleScrollEvent.cancel();
stop();
},
stop: function () { return subscription.unsubscribe(); },
};

@@ -50,2 +54,29 @@ }

exports.computeScrollValues = computeScrollValues;
function createScrollValuesObservable(configuration, throttleDuration) {
if (throttleDuration === void 0) { throttleDuration = exports.THROTTLE_SCROLL_DURATION; }
var observable = new browser_core_1.Observable(function () {
function notify() {
observable.notify(computeScrollValues());
}
if (window.ResizeObserver) {
var throttledNotify_1 = (0, browser_core_1.throttle)(notify, throttleDuration, {
leading: false,
trailing: true,
});
var observerTarget_1 = document.scrollingElement || document.documentElement;
var resizeObserver_1 = new ResizeObserver((0, browser_core_1.monitor)(throttledNotify_1.throttled));
resizeObserver_1.observe(observerTarget_1);
var eventListener_1 = (0, browser_core_1.addEventListener)(configuration, window, "scroll" /* DOM_EVENT.SCROLL */, throttledNotify_1.throttled, {
passive: true,
});
return function () {
throttledNotify_1.cancel();
resizeObserver_1.unobserve(observerTarget_1);
eventListener_1.stop();
};
}
});
return observable;
}
exports.createScrollValuesObservable = createScrollValuesObservable;
//# sourceMappingURL=trackScrollMetrics.js.map

@@ -5,2 +5,3 @@ "use strict";

var browser_core_1 = require("@datadog/browser-core");
var performanceCollection_1 = require("../browser/performanceCollection");
// Delay to wait for a page activity to validate the tracking process

@@ -84,3 +85,3 @@ exports.PAGE_ACTIVITY_VALIDATION_DELAY = 100;

subscriptions.push(domMutationObservable.subscribe(notifyPageActivity), lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {
if (entries.some(function (entry) { return entry.entryType === 'resource' && !isExcludedUrl(configuration, entry.name); })) {
if (entries.some(function (entry) { return entry.entryType === performanceCollection_1.RumPerformanceEntryType.RESOURCE && !isExcludedUrl(configuration, entry.name); })) {
notifyPageActivity();

@@ -87,0 +88,0 @@ }

@@ -15,4 +15,4 @@ export { RumPublicApi, makeRumPublicApi, RecorderApi, StartRum } from './boot/rumPublicApi';

export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/action/getActionNameFromElement';
export { STABLE_ATTRIBUTES } from './domain/action/getSelectorFromElement';
export { STABLE_ATTRIBUTES } from './domain/getSelectorFromElement';
export * from './browser/htmlDomUtils';
export { getSessionReplayUrl } from './domain/getSessionReplayUrl';

@@ -34,3 +34,3 @@ "use strict";

Object.defineProperty(exports, "DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE", { enumerable: true, get: function () { return getActionNameFromElement_1.DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE; } });
var getSelectorFromElement_1 = require("./domain/action/getSelectorFromElement");
var getSelectorFromElement_1 = require("./domain/getSelectorFromElement");
Object.defineProperty(exports, "STABLE_ATTRIBUTES", { enumerable: true, get: function () { return getSelectorFromElement_1.STABLE_ATTRIBUTES; } });

@@ -37,0 +37,0 @@ __exportStar(require("./browser/htmlDomUtils"), exports);

@@ -70,4 +70,7 @@ import type { Context, Duration, ErrorSource, ErrorHandling, ResourceType, ServerDuration, TimeStamp, RawErrorCause, DefaultPrivacyLevel } from '@datadog/browser-core';

first_input_time?: ServerDuration;
first_input_target_selector?: string;
interaction_to_next_paint?: ServerDuration;
interaction_to_next_paint_target_selector?: string;
cumulative_layout_shift?: number;
cumulative_layout_shift_target_selector?: string;
custom_timings?: {

@@ -77,2 +80,3 @@ [key: string]: ServerDuration;

largest_contentful_paint?: ServerDuration;
largest_contentful_paint_target_selector?: string;
dom_interactive?: ServerDuration;

@@ -111,5 +115,5 @@ dom_content_loaded?: ServerDuration;

max_depth?: number;
max_depth_scroll_height?: number;
max_depth_scroll_top?: number;
max_depth_time?: ServerDuration;
max_scroll_height?: number;
max_scroll_height_time?: ServerDuration;
};

@@ -116,0 +120,0 @@ }

@@ -460,2 +460,24 @@ /**

};
/**
* GraphQL requests parameters
*/
readonly graphql?: {
/**
* Type of the GraphQL operation
*/
readonly operationType: 'query' | 'mutation' | 'subscription';
/**
* Name of the GraphQL operation
*/
readonly operationName?: string;
/**
* Content of the GraphQL operation
*/
payload?: string;
/**
* String representation of the operation variables
*/
variables?: string;
[k: string]: unknown;
};
[k: string]: unknown;

@@ -520,2 +542,6 @@ };

/**
* CSS selector path of the largest contentful paint element
*/
readonly largest_contentful_paint_target_selector?: string;
/**
* Duration in ns of the first input event delay

@@ -529,2 +555,6 @@ */

/**
* CSS selector path of the first input target element
*/
readonly first_input_target_selector?: string;
/**
* Longest duration in ns between an interaction and the next paint

@@ -534,2 +564,6 @@ */

/**
* CSS selector path of the interacted element corresponding to INP
*/
readonly interaction_to_next_paint_target_selector?: string;
/**
* Total layout shift score that occurred on the view

@@ -539,2 +573,6 @@ */

/**
* CSS selector path of the first element (in document order) of the largest layout shift contributing to CLS
*/
readonly cumulative_layout_shift_target_selector?: string;
/**
* Duration in ns to the complete parsing and loading of the document and its sub resources

@@ -784,6 +822,2 @@ */

/**
* Page scroll height (total height) when the maximum scroll depth was reached for this view (in pixels)
*/
readonly max_depth_scroll_height: number;
/**
* Page scroll top (scrolled distance) when the maximum scroll depth was reached for this view (in pixels)

@@ -793,5 +827,9 @@ */

/**
* Duration between the view start and the scroll event that reached the maximum scroll depth for this view (in nanoseconds)
* Maximum page scroll height (total height) for this view (in pixels)
*/
readonly max_depth_time: number;
readonly max_scroll_height: number;
/**
* Duration between the view start and the time the max scroll height was reached for this view (in nanoseconds)
*/
readonly max_scroll_height_time: number;
[k: string]: unknown;

@@ -830,2 +868,6 @@ };

/**
* The build version for this application
*/
readonly build_version?: string;
/**
* Session properties

@@ -832,0 +874,0 @@ */

@@ -1,2 +0,2 @@

import type { Context, InitConfiguration, RelativeTime, User, Observable } from '@datadog/browser-core';
import type { Context, InitConfiguration, User } from '@datadog/browser-core';
import type { LifeCycle } from '../domain/lifeCycle';

@@ -18,4 +18,2 @@ import type { ViewContexts } from '../domain/contexts/viewContexts';

getSessionReplayLink: (configuration: RumConfiguration, sessionManager: RumSessionManager, viewContexts: ViewContexts) => string | undefined;
getSerializedNodeId: (node: Node) => number | undefined;
recorderStartObservable: Observable<RelativeTime>;
}

@@ -22,0 +20,0 @@ interface RumPublicApiOptions {

@@ -24,3 +24,2 @@ import { sendToExtension, createPageExitObservable, addTelemetryConfiguration, startTelemetry, canUseEventBridge, getEventBridge, addTelemetryDebug, } from '@datadog/browser-core';

import { buildCommonContext } from '../domain/contexts/commonContext';
import { startWebVitalTelemetryDebug } from '../domain/view/startWebVitalTelemetryDebug';
import { startDisplayContext } from '../domain/contexts/displayContext';

@@ -75,4 +74,3 @@ export function startRum(initConfiguration, configuration, recorderApi, globalContextManager, userContextManager, initialViewOptions) {

startResourceCollection(lifeCycle, configuration, session, pageStateHistory);
var webVitalTelemetryDebug = startWebVitalTelemetryDebug(configuration, telemetry, recorderApi, session);
var _b = startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, webVitalTelemetryDebug, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView, stopViewCollection = _b.stop;
var _b = startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView, stopViewCollection = _b.stop;
cleanupTasks.push(stopViewCollection);

@@ -79,0 +77,0 @@ var addError = startErrorCollection(lifeCycle, configuration, pageStateHistory, featureFlagContexts).addError;

@@ -17,4 +17,14 @@ import type { Duration, RelativeTime } from '@datadog/browser-core';

}
export declare enum RumPerformanceEntryType {
EVENT = "event",
FIRST_INPUT = "first-input",
LARGEST_CONTENTFUL_PAINT = "largest-contentful-paint",
LAYOUT_SHIFT = "layout-shift",
LONG_TASK = "longtask",
NAVIGATION = "navigation",
PAINT = "paint",
RESOURCE = "resource"
}
export interface RumPerformanceResourceTiming {
entryType: 'resource';
entryType: RumPerformanceEntryType.RESOURCE;
initiatorType: string;

@@ -37,5 +47,6 @@ name: string;

traceId?: string;
toJSON(): PerformanceEntryRepresentation;
}
export interface RumPerformanceLongTaskTiming {
entryType: 'longtask';
entryType: RumPerformanceEntryType.LONG_TASK;
startTime: RelativeTime;

@@ -46,3 +57,3 @@ duration: Duration;

export interface RumPerformancePaintTiming {
entryType: 'paint';
entryType: RumPerformanceEntryType.PAINT;
name: 'first-paint' | 'first-contentful-paint';

@@ -52,3 +63,3 @@ startTime: RelativeTime;

export interface RumPerformanceNavigationTiming {
entryType: 'navigation';
entryType: RumPerformanceEntryType.NAVIGATION;
domComplete: RelativeTime;

@@ -61,3 +72,3 @@ domContentLoadedEventEnd: RelativeTime;

export interface RumLargestContentfulPaintTiming {
entryType: 'largest-contentful-paint';
entryType: RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT;
startTime: RelativeTime;

@@ -68,3 +79,3 @@ size: number;

export interface RumFirstInputTiming {
entryType: 'first-input';
entryType: RumPerformanceEntryType.FIRST_INPUT;
startTime: RelativeTime;

@@ -77,9 +88,10 @@ processingStart: RelativeTime;

export interface RumPerformanceEventTiming {
entryType: 'event';
entryType: RumPerformanceEntryType.EVENT;
startTime: RelativeTime;
duration: Duration;
interactionId?: number;
target?: Node;
}
export interface RumLayoutShiftTiming {
entryType: 'layout-shift';
entryType: RumPerformanceEntryType.LAYOUT_SHIFT;
startTime: RelativeTime;

@@ -93,3 +105,3 @@ value: number;

export type RumPerformanceEntry = RumPerformanceResourceTiming | RumPerformanceLongTaskTiming | RumPerformancePaintTiming | RumPerformanceNavigationTiming | RumLargestContentfulPaintTiming | RumFirstInputTiming | RumPerformanceEventTiming | RumLayoutShiftTiming;
export declare function supportPerformanceTimingEvent(entryType: string): boolean;
export declare function supportPerformanceTimingEvent(entryType: RumPerformanceEntryType): boolean;
export declare function startPerformanceCollection(lifeCycle: LifeCycle, configuration: RumConfiguration): void;

@@ -96,0 +108,0 @@ export declare function retrieveInitialDocumentResourceTiming(configuration: RumConfiguration, callback: (timing: RumPerformanceResourceTiming) => void): void;

@@ -1,4 +0,18 @@

import { dateNow, assign, addEventListeners, getRelativeTime, isNumber, monitor, setTimeout, relativeNow, runOnReadyState, addEventListener, } from '@datadog/browser-core';
import { dateNow, assign, addEventListeners, getRelativeTime, isNumber, monitor, setTimeout, relativeNow, runOnReadyState, addEventListener, objectHasValue, } from '@datadog/browser-core';
import { FAKE_INITIAL_DOCUMENT, isAllowedRequestUrl } from '../domain/resource/resourceUtils';
import { getDocumentTraceId } from '../domain/tracing/getDocumentTraceId';
// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary
// string is an expected performance entry
// eslint-disable-next-line no-restricted-syntax
export var RumPerformanceEntryType;
(function (RumPerformanceEntryType) {
RumPerformanceEntryType["EVENT"] = "event";
RumPerformanceEntryType["FIRST_INPUT"] = "first-input";
RumPerformanceEntryType["LARGEST_CONTENTFUL_PAINT"] = "largest-contentful-paint";
RumPerformanceEntryType["LAYOUT_SHIFT"] = "layout-shift";
RumPerformanceEntryType["LONG_TASK"] = "longtask";
RumPerformanceEntryType["NAVIGATION"] = "navigation";
RumPerformanceEntryType["PAINT"] = "paint";
RumPerformanceEntryType["RESOURCE"] = "resource";
})(RumPerformanceEntryType || (RumPerformanceEntryType = {}));
function supportPerformanceObject() {

@@ -26,4 +40,14 @@ return window.performance !== undefined && 'getEntries' in performance;

});
var mainEntries = ['resource', 'navigation', 'longtask', 'paint'];
var experimentalEntries = ['largest-contentful-paint', 'first-input', 'layout-shift', 'event'];
var mainEntries = [
RumPerformanceEntryType.RESOURCE,
RumPerformanceEntryType.NAVIGATION,
RumPerformanceEntryType.LONG_TASK,
RumPerformanceEntryType.PAINT,
];
var experimentalEntries = [
RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT,
RumPerformanceEntryType.FIRST_INPUT,
RumPerformanceEntryType.LAYOUT_SHIFT,
RumPerformanceEntryType.EVENT,
];
try {

@@ -58,3 +82,3 @@ // Experimental entries are not retrieved by performance.getEntries()

}
if (!supportPerformanceTimingEvent('navigation')) {
if (!supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION)) {
retrieveNavigationTiming(configuration, function (timing) {

@@ -64,3 +88,3 @@ handleRumPerformanceEntries(lifeCycle, configuration, [timing]);

}
if (!supportPerformanceTimingEvent('first-input')) {
if (!supportPerformanceTimingEvent(RumPerformanceEntryType.FIRST_INPUT)) {
retrieveFirstInputTiming(configuration, function (timing) {

@@ -75,8 +99,10 @@ handleRumPerformanceEntries(lifeCycle, configuration, [timing]);

var forcedAttributes = {
entryType: 'resource',
entryType: RumPerformanceEntryType.RESOURCE,
initiatorType: FAKE_INITIAL_DOCUMENT,
traceId: getDocumentTraceId(document),
toJSON: function () { return assign({}, timing, { toJSON: undefined }); },
};
if (supportPerformanceTimingEvent('navigation') && performance.getEntriesByType('navigation').length > 0) {
var navigationEntry = performance.getEntriesByType('navigation')[0];
if (supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION) &&
performance.getEntriesByType(RumPerformanceEntryType.NAVIGATION).length > 0) {
var navigationEntry = performance.getEntriesByType(RumPerformanceEntryType.NAVIGATION)[0];
timing = assign(navigationEntry.toJSON(), forcedAttributes);

@@ -99,3 +125,3 @@ }

callback(assign(computeRelativePerformanceTiming(), {
entryType: 'navigation',
entryType: RumPerformanceEntryType.NAVIGATION,
}));

@@ -124,3 +150,3 @@ }

var timing = {
entryType: 'first-input',
entryType: RumPerformanceEntryType.FIRST_INPUT,
processingStart: relativeNow(),

@@ -180,10 +206,3 @@ startTime: evt.timeStamp,

var rumPerformanceEntries = entries.filter(function (entry) {
return entry.entryType === 'resource' ||
entry.entryType === 'navigation' ||
entry.entryType === 'paint' ||
entry.entryType === 'longtask' ||
entry.entryType === 'largest-contentful-paint' ||
entry.entryType === 'first-input' ||
entry.entryType === 'layout-shift' ||
entry.entryType === 'event';
return objectHasValue(RumPerformanceEntryType, entry.entryType);
});

@@ -196,7 +215,7 @@ var rumAllowedPerformanceEntries = rumPerformanceEntries.filter(function (entry) { return !isIncompleteNavigation(entry) && !isForbiddenResource(configuration, entry); });

function isIncompleteNavigation(entry) {
return entry.entryType === 'navigation' && entry.loadEventEnd <= 0;
return entry.entryType === RumPerformanceEntryType.NAVIGATION && entry.loadEventEnd <= 0;
}
function isForbiddenResource(configuration, entry) {
return entry.entryType === 'resource' && !isAllowedRequestUrl(configuration, entry.name);
return entry.entryType === RumPerformanceEntryType.RESOURCE && !isAllowedRequestUrl(configuration, entry.name);
}
//# sourceMappingURL=performanceCollection.js.map
import { includes, timeStampNow, Observable, assign, getRelativeTime, ONE_MINUTE, ValueHistory, generateUUID, clocksNow, ONE_SECOND, elapsed, } from '@datadog/browser-core';
import { trackEventCounts } from '../trackEventCounts';
import { PAGE_ACTIVITY_VALIDATION_DELAY, waitPageActivityEnd } from '../waitPageActivityEnd';
import { getSelectorFromElement } from '../getSelectorFromElement';
import { createClickChain } from './clickChain';
import { getActionNameFromElement } from './getActionNameFromElement';
import { getSelectorFromElement } from './getSelectorFromElement';
import { listenActionEvents } from './listenActionEvents';

@@ -8,0 +8,0 @@ import { computeFrustration } from './computeFrustration';

@@ -57,3 +57,3 @@ import { combine, isEmptyObject, timeStampNow, currentDrift, display, createEventRateLimiter, canUseEventBridge, assign, round, } from '@datadog/browser-core';

},
browser_sdk_version: canUseEventBridge() ? "4.49.0" : undefined,
browser_sdk_version: canUseEventBridge() ? "4.50.0" : undefined,
},

@@ -60,0 +60,0 @@ application: {

import { toServerDuration, relativeToClocks, generateUUID } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../browser/performanceCollection';
export function startLongTaskCollection(lifeCycle, sessionManager) {

@@ -6,3 +7,3 @@ lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {

var entry = entries_1[_i];
if (entry.entryType !== 'longtask') {
if (entry.entryType !== RumPerformanceEntryType.LONG_TASK) {
break;

@@ -9,0 +10,0 @@ }

import { combine, generateUUID, toServerDuration, relativeToClocks, assign, isNumber, isExperimentalFeatureEnabled, ExperimentalFeature, } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../browser/performanceCollection';
import { matchRequestTiming } from './matchRequestTiming';

@@ -11,3 +12,3 @@ import { computePerformanceResourceDetails, computePerformanceResourceDuration, computeResourceKind, computeSize, isRequestKind, } from './resourceUtils';

var entry = entries_1[_i];
if (entry.entryType === 'resource' && !isRequestKind(entry)) {
if (entry.entryType === RumPerformanceEntryType.RESOURCE && !isRequestKind(entry)) {
lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processResourceEntry(entry, configuration, sessionManager, pageStateHistory));

@@ -14,0 +15,0 @@ }

@@ -9,3 +9,2 @@ import type { Duration, ClocksState, TimeStamp, RelativeTime } from '@datadog/browser-core';

import type { RumConfiguration } from '../configuration';
import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug';
import type { InitialViewMetrics } from './viewMetrics/trackInitialViewMetrics';

@@ -48,3 +47,3 @@ import type { CommonViewMetrics } from './viewMetrics/trackCommonViewMetrics';

}
export declare function trackViews(location: Location, lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, locationChangeObservable: Observable<LocationChange>, areViewsTrackedAutomatically: boolean, webVitalTelemetryDebug: WebVitalTelemetryDebug, initialViewOptions?: ViewOptions): {
export declare function trackViews(location: Location, lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, locationChangeObservable: Observable<LocationChange>, areViewsTrackedAutomatically: boolean, initialViewOptions?: ViewOptions): {
addTiming: (name: string, time?: RelativeTime | TimeStamp) => void;

@@ -51,0 +50,0 @@ startView: (options?: ViewOptions, startClocks?: ClocksState) => void;

@@ -14,3 +14,3 @@ import { noop, PageExitReason, shallowClone, elapsed, generateUUID, ONE_MINUTE, throttle, clocksNow, clocksOrigin, timeStampNow, display, looksLikeRelativeTime, setInterval, clearInterval, setTimeout, Observable, } from '@datadog/browser-core';

export var KEEP_TRACKING_AFTER_VIEW_DELAY = 5 * ONE_MINUTE;
export function trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, areViewsTrackedAutomatically, webVitalTelemetryDebug, initialViewOptions) {
export function trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, areViewsTrackedAutomatically, initialViewOptions) {
var activeViews = new Set();

@@ -24,3 +24,3 @@ var currentView = startNewView("initial_load" /* ViewLoadingType.INITIAL_LOAD */, clocksOrigin(), initialViewOptions);

function startNewView(loadingType, startClocks, viewOptions) {
var newlyCreatedView = newView(lifeCycle, domMutationObservable, configuration, location, loadingType, webVitalTelemetryDebug, startClocks, viewOptions);
var newlyCreatedView = newView(lifeCycle, domMutationObservable, configuration, location, loadingType, startClocks, viewOptions);
activeViews.add(newlyCreatedView);

@@ -76,3 +76,3 @@ newlyCreatedView.stopObservable.subscribe(function () {

}
function newView(lifeCycle, domMutationObservable, configuration, initialLocation, loadingType, webVitalTelemetryDebug, startClocks, viewOptions) {
function newView(lifeCycle, domMutationObservable, configuration, initialLocation, loadingType, startClocks, viewOptions) {
if (startClocks === void 0) { startClocks = clocksNow(); }

@@ -106,5 +106,5 @@ // Setup initial values

}), scheduleViewUpdate = _a.throttled, cancelScheduleViewUpdate = _a.cancel;
var _b = trackCommonViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks, webVitalTelemetryDebug), setLoadEvent = _b.setLoadEvent, stopCommonViewMetricsTracking = _b.stop, getCommonViewMetrics = _b.getCommonViewMetrics;
var _b = trackCommonViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks), setLoadEvent = _b.setLoadEvent, stopCommonViewMetricsTracking = _b.stop, getCommonViewMetrics = _b.getCommonViewMetrics;
var _c = loadingType === "initial_load" /* ViewLoadingType.INITIAL_LOAD */
? trackInitialViewMetrics(lifeCycle, configuration, webVitalTelemetryDebug, setLoadEvent, scheduleViewUpdate)
? trackInitialViewMetrics(lifeCycle, configuration, setLoadEvent, scheduleViewUpdate)
: { stop: noop, initialViewMetrics: {} }, stopInitialViewMetricsTracking = _c.stop, initialViewMetrics = _c.initialViewMetrics;

@@ -111,0 +111,0 @@ var _d = trackViewEventCounts(lifeCycle, id, scheduleViewUpdate), stopEventCountsTracking = _d.stop, eventCounts = _d.eventCounts;

@@ -9,4 +9,3 @@ import type { Observable } from '@datadog/browser-core';

import type { ViewOptions } from './trackViews';
import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug';
export declare function startViewCollection(lifeCycle: LifeCycle, configuration: RumConfiguration, location: Location, domMutationObservable: Observable<void>, locationChangeObservable: Observable<LocationChange>, featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, webVitalTelemetryDebug: WebVitalTelemetryDebug, initialViewOptions?: ViewOptions): {
export declare function startViewCollection(lifeCycle: LifeCycle, configuration: RumConfiguration, location: Location, domMutationObservable: Observable<void>, locationChangeObservable: Observable<LocationChange>, featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, initialViewOptions?: ViewOptions): {
addTiming: (name: string, time?: import("@datadog/browser-core").TimeStamp | import("@datadog/browser-core").RelativeTime) => void;

@@ -13,0 +12,0 @@ startView: (options?: ViewOptions | undefined, startClocks?: import("@datadog/browser-core").ClocksState | undefined) => void;

import { isExperimentalFeatureEnabled, ExperimentalFeature, isEmptyObject, mapValues, toServerDuration, isNumber, } from '@datadog/browser-core';
import { mapToForegroundPeriods } from '../contexts/foregroundContexts';
import { trackViews } from './trackViews';
export function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, webVitalTelemetryDebug, initialViewOptions) {
export function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions) {
lifeCycle.subscribe(3 /* LifeCycleEventType.VIEW_UPDATED */, function (view) {
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory));
});
return trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, !configuration.trackViewsManually, webVitalTelemetryDebug, initialViewOptions);
return trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, !configuration.trackViewsManually, initialViewOptions);
}
function processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory) {
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
var replayStats = recorderApi.getReplayStats(view.id);

@@ -30,7 +31,8 @@ var featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(view.startClocks.relative);

},
cumulative_layout_shift: view.commonViewMetrics.cumulativeLayoutShift,
first_byte: toServerDuration(view.initialViewMetrics.firstByte),
dom_complete: toServerDuration(view.initialViewMetrics.domComplete),
dom_content_loaded: toServerDuration(view.initialViewMetrics.domContentLoaded),
dom_interactive: toServerDuration(view.initialViewMetrics.domInteractive),
cumulative_layout_shift: (_a = view.commonViewMetrics.cumulativeLayoutShift) === null || _a === void 0 ? void 0 : _a.value,
cumulative_layout_shift_target_selector: (_b = view.commonViewMetrics.cumulativeLayoutShift) === null || _b === void 0 ? void 0 : _b.targetSelector,
first_byte: toServerDuration((_c = view.initialViewMetrics.navigationTimings) === null || _c === void 0 ? void 0 : _c.firstByte),
dom_complete: toServerDuration((_d = view.initialViewMetrics.navigationTimings) === null || _d === void 0 ? void 0 : _d.domComplete),
dom_content_loaded: toServerDuration((_e = view.initialViewMetrics.navigationTimings) === null || _e === void 0 ? void 0 : _e.domContentLoaded),
dom_interactive: toServerDuration((_f = view.initialViewMetrics.navigationTimings) === null || _f === void 0 ? void 0 : _f.domInteractive),
error: {

@@ -40,9 +42,12 @@ count: view.eventCounts.errorCount,

first_contentful_paint: toServerDuration(view.initialViewMetrics.firstContentfulPaint),
first_input_delay: toServerDuration(view.initialViewMetrics.firstInputDelay),
first_input_time: toServerDuration(view.initialViewMetrics.firstInputTime),
interaction_to_next_paint: toServerDuration(view.commonViewMetrics.interactionToNextPaint),
first_input_delay: toServerDuration((_g = view.initialViewMetrics.firstInput) === null || _g === void 0 ? void 0 : _g.delay),
first_input_time: toServerDuration((_h = view.initialViewMetrics.firstInput) === null || _h === void 0 ? void 0 : _h.time),
first_input_target_selector: (_j = view.initialViewMetrics.firstInput) === null || _j === void 0 ? void 0 : _j.targetSelector,
interaction_to_next_paint: toServerDuration((_k = view.commonViewMetrics.interactionToNextPaint) === null || _k === void 0 ? void 0 : _k.value),
interaction_to_next_paint_target_selector: (_l = view.commonViewMetrics.interactionToNextPaint) === null || _l === void 0 ? void 0 : _l.targetSelector,
is_active: view.isActive,
name: view.name,
largest_contentful_paint: toServerDuration(view.initialViewMetrics.largestContentfulPaint),
load_event: toServerDuration(view.initialViewMetrics.loadEvent),
largest_contentful_paint: toServerDuration((_m = view.initialViewMetrics.largestContentfulPaint) === null || _m === void 0 ? void 0 : _m.value),
largest_contentful_paint_target_selector: (_o = view.initialViewMetrics.largestContentfulPaint) === null || _o === void 0 ? void 0 : _o.targetSelector,
load_event: toServerDuration((_p = view.initialViewMetrics.navigationTimings) === null || _p === void 0 ? void 0 : _p.loadEvent),
loading_time: discardNegativeDuration(toServerDuration(view.commonViewMetrics.loadingTime)),

@@ -64,5 +69,5 @@ loading_type: view.loadingType,

max_depth: view.commonViewMetrics.scroll.maxDepth,
max_depth_scroll_height: view.commonViewMetrics.scroll.maxDepthScrollHeight,
max_depth_scroll_top: view.commonViewMetrics.scroll.maxDepthScrollTop,
max_depth_time: toServerDuration(view.commonViewMetrics.scroll.maxDepthTime),
max_scroll_height: view.commonViewMetrics.scroll.maxScrollHeight,
max_scroll_height_time: toServerDuration(view.commonViewMetrics.scroll.maxScrollHeightTime),
},

@@ -69,0 +74,0 @@ }

@@ -5,11 +5,12 @@ import type { ClocksState, Duration, Observable } from '@datadog/browser-core';

import type { LifeCycle } from '../../lifeCycle';
import type { WebVitalTelemetryDebug } from '../startWebVitalTelemetryDebug';
import type { CumulativeLayoutShift } from './trackCumulativeLayoutShift';
import type { InteractionToNextPaint } from './trackInteractionToNextPaint';
import type { ScrollMetrics } from './trackScrollMetrics';
export interface CommonViewMetrics {
loadingTime?: Duration;
cumulativeLayoutShift?: number;
interactionToNextPaint?: Duration;
cumulativeLayoutShift?: CumulativeLayoutShift;
interactionToNextPaint?: InteractionToNextPaint;
scroll?: ScrollMetrics;
}
export declare function trackCommonViewMetrics(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, scheduleViewUpdate: () => void, loadingType: ViewLoadingType, viewStart: ClocksState, webVitalTelemetryDebug: WebVitalTelemetryDebug): {
export declare function trackCommonViewMetrics(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, scheduleViewUpdate: () => void, loadingType: ViewLoadingType, viewStart: ClocksState): {
stop: () => void;

@@ -16,0 +17,0 @@ setLoadEvent: (loadEvent: Duration) => void;

@@ -1,19 +0,9 @@

import { noop } from '@datadog/browser-core';
import { computeScrollValues, trackScrollMetrics } from './trackScrollMetrics';
import { trackCumulativeLayoutShift } from './trackCumulativeLayoutShift';
import { trackInteractionToNextPaint } from './trackInteractionToNextPaint';
import { trackLoadingTime } from './trackLoadingTime';
import { isLayoutShiftSupported, trackCumulativeLayoutShift } from './trackCumulativeLayoutShift';
import { trackInteractionToNextPaint } from './trackInteractionToNextPaint';
export function trackCommonViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, viewStart, webVitalTelemetryDebug) {
import { trackScrollMetrics } from './trackScrollMetrics';
export function trackCommonViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, viewStart) {
var commonViewMetrics = {};
var _a = trackLoadingTime(lifeCycle, domMutationObservable, configuration, loadingType, viewStart, function (newLoadingTime) {
commonViewMetrics.loadingTime = newLoadingTime;
// We compute scroll metrics at loading time to ensure we have scroll data when loading the view initially
// This is to ensure that we have the depth data even if the user didn't scroll or if the view is not scrollable.
var _a = computeScrollValues(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop;
commonViewMetrics.scroll = {
maxDepth: scrollDepth,
maxDepthScrollHeight: scrollHeight,
maxDepthTime: newLoadingTime,
maxDepthScrollTop: scrollTop,
};
scheduleViewUpdate();

@@ -23,20 +13,8 @@ }), stopLoadingTimeTracking = _a.stop, setLoadEvent = _a.setLoadEvent;

commonViewMetrics.scroll = newScrollMetrics;
}, computeScrollValues).stop;
var stopCLSTracking;
var clsAttributionCollected = false;
if (isLayoutShiftSupported()) {
commonViewMetrics.cumulativeLayoutShift = 0;
(stopCLSTracking = trackCumulativeLayoutShift(lifeCycle, function (cumulativeLayoutShift, largestLayoutShiftNode, largestLayoutShiftTime) {
commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift;
if (!clsAttributionCollected) {
clsAttributionCollected = true;
webVitalTelemetryDebug.addWebVitalTelemetryDebug('CLS', largestLayoutShiftNode, largestLayoutShiftTime);
}
scheduleViewUpdate();
}).stop);
}
else {
stopCLSTracking = noop;
}
var _b = trackInteractionToNextPaint(loadingType, lifeCycle), stopINPTracking = _b.stop, getInteractionToNextPaint = _b.getInteractionToNextPaint;
}).stop;
var stopCLSTracking = trackCumulativeLayoutShift(configuration, lifeCycle, function (cumulativeLayoutShift) {
commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift;
scheduleViewUpdate();
}).stop;
var _b = trackInteractionToNextPaint(configuration, loadingType, lifeCycle), stopINPTracking = _b.stop, getInteractionToNextPaint = _b.getInteractionToNextPaint;
return {

@@ -43,0 +21,0 @@ stop: function () {

@@ -1,3 +0,8 @@

import { type RelativeTime } from '@datadog/browser-core';
import { noop } from '@datadog/browser-core';
import type { LifeCycle } from '../../lifeCycle';
import type { RumConfiguration } from '../../configuration';
export interface CumulativeLayoutShift {
value: number;
targetSelector?: string;
}
/**

@@ -20,4 +25,4 @@ * Track the cumulative layout shifts (CLS).

*/
export declare function trackCumulativeLayoutShift(lifeCycle: LifeCycle, callback: (layoutShift: number, largestShiftNode: Node | undefined, largestShiftTime: RelativeTime) => void): {
stop: () => void;
export declare function trackCumulativeLayoutShift(configuration: RumConfiguration, lifeCycle: LifeCycle, callback: (cumulativeLayoutShift: CumulativeLayoutShift) => void): {
stop: typeof noop;
};

@@ -24,0 +29,0 @@ /**

@@ -1,3 +0,5 @@

import { round, find, ONE_SECOND } from '@datadog/browser-core';
import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection';
import { round, find, ONE_SECOND, isExperimentalFeatureEnabled, ExperimentalFeature, noop, } from '@datadog/browser-core';
import { isElementNode } from '../../../browser/htmlDomUtils';
import { supportPerformanceTimingEvent, RumPerformanceEntryType } from '../../../browser/performanceCollection';
import { getSelectorFromElement } from '../../getSelectorFromElement';
/**

@@ -20,4 +22,13 @@ * Track the cumulative layout shifts (CLS).

*/
export function trackCumulativeLayoutShift(lifeCycle, callback) {
export function trackCumulativeLayoutShift(configuration, lifeCycle, callback) {
if (!isLayoutShiftSupported()) {
return {
stop: noop,
};
}
var maxClsValue = 0;
// if no layout shift happen the value should be reported as 0
callback({
value: 0,
});
var window = slidingSessionWindow();

@@ -27,7 +38,16 @@ var stop = lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {

var entry = entries_1[_i];
if (entry.entryType === 'layout-shift' && !entry.hadRecentInput) {
if (entry.entryType === RumPerformanceEntryType.LAYOUT_SHIFT && !entry.hadRecentInput) {
window.update(entry);
if (window.value() > maxClsValue) {
maxClsValue = window.value();
callback(round(maxClsValue, 4), window.largestLayoutShiftNode(), window.largestLayoutShiftTime());
var cls = round(maxClsValue, 4);
var clsTarget = window.largestLayoutShiftTarget();
var cslTargetSelector = void 0;
if (isExperimentalFeatureEnabled(ExperimentalFeature.WEB_VITALS_ATTRIBUTION) && clsTarget) {
cslTargetSelector = getSelectorFromElement(clsTarget, configuration.actionNameAttribute);
}
callback({
value: cls,
targetSelector: cslTargetSelector,
});
}

@@ -46,7 +66,7 @@ }

var largestLayoutShift = 0;
var largestLayoutShiftNode;
var largestLayoutShiftTarget;
var largestLayoutShiftTime;
return {
update: function (entry) {
var _a;
var _a, _b;
var shouldCreateNewWindow = startTime === undefined ||

@@ -59,3 +79,3 @@ entry.startTime - endTime >= ONE_SECOND ||

largestLayoutShift = 0;
largestLayoutShiftNode = undefined;
largestLayoutShiftTarget = undefined;
}

@@ -70,7 +90,6 @@ else {

if ((_a = entry.sources) === null || _a === void 0 ? void 0 : _a.length) {
var largestLayoutShiftSource = find(entry.sources, function (s) { var _a; return ((_a = s.node) === null || _a === void 0 ? void 0 : _a.nodeType) === 1; }) || entry.sources[0];
largestLayoutShiftNode = largestLayoutShiftSource.node;
largestLayoutShiftTarget = (_b = find(entry.sources, function (s) { return !!s.node && isElementNode(s.node); })) === null || _b === void 0 ? void 0 : _b.node;
}
else {
largestLayoutShiftNode = undefined;
largestLayoutShiftTarget = undefined;
}

@@ -80,3 +99,3 @@ }

value: function () { return value; },
largestLayoutShiftNode: function () { return largestLayoutShiftNode; },
largestLayoutShiftTarget: function () { return largestLayoutShiftTarget; },
largestLayoutShiftTime: function () { return largestLayoutShiftTime; },

@@ -89,4 +108,4 @@ };

export function isLayoutShiftSupported() {
return supportPerformanceTimingEvent('layout-shift');
return supportPerformanceTimingEvent(RumPerformanceEntryType.LAYOUT_SHIFT);
}
//# sourceMappingURL=trackCumulativeLayoutShift.js.map
import { ONE_MINUTE, find } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../../browser/performanceCollection';
// Discard FCP timings above a certain delay to avoid incorrect data

@@ -8,3 +9,3 @@ // It happens in some cases like sleep mode or some browser implementations

var fcpEntry = find(entries, function (entry) {
return entry.entryType === 'paint' &&
return entry.entryType === RumPerformanceEntryType.PAINT &&
entry.name === 'first-contentful-paint' &&

@@ -11,0 +12,0 @@ entry.startTime < firstHidden.timeStamp &&

import type { Duration } from '@datadog/browser-core';
import type { RumConfiguration } from '../../configuration';
import type { LifeCycle } from '../../lifeCycle';
import type { WebVitalTelemetryDebug } from '../startWebVitalTelemetryDebug';
import type { FirstInput } from './trackFirstInput';
import type { NavigationTimings } from './trackNavigationTimings';
import type { LargestContentfulPaint } from './trackLargestContentfulPaint';
export interface InitialViewMetrics {
firstContentfulPaint?: Duration;
firstByte?: Duration;
domInteractive?: Duration;
domContentLoaded?: Duration;
domComplete?: Duration;
loadEvent?: Duration;
largestContentfulPaint?: Duration;
firstInputDelay?: Duration;
firstInputTime?: Duration;
navigationTimings?: NavigationTimings;
largestContentfulPaint?: LargestContentfulPaint;
firstInput?: FirstInput;
}
export declare function trackInitialViewMetrics(lifeCycle: LifeCycle, configuration: RumConfiguration, webVitalTelemetryDebug: WebVitalTelemetryDebug, setLoadEvent: (loadEnd: Duration) => void, scheduleViewUpdate: () => void): {
export declare function trackInitialViewMetrics(lifeCycle: LifeCycle, configuration: RumConfiguration, setLoadEvent: (loadEnd: Duration) => void, scheduleViewUpdate: () => void): {
stop: () => void;
initialViewMetrics: InitialViewMetrics;
};

@@ -1,34 +0,25 @@

import { assign } from '@datadog/browser-core';
import { trackFirstContentfulPaint } from './trackFirstContentfulPaint';
import { trackFirstInputTimings } from './trackFirstInputTimings';
import { trackFirstInput } from './trackFirstInput';
import { trackNavigationTimings } from './trackNavigationTimings';
import { trackLargestContentfulPaint } from './trackLargestContentfulPaint';
import { trackFirstHidden } from './trackFirstHidden';
export function trackInitialViewMetrics(lifeCycle, configuration, webVitalTelemetryDebug, setLoadEvent, scheduleViewUpdate) {
export function trackInitialViewMetrics(lifeCycle, configuration, setLoadEvent, scheduleViewUpdate) {
var initialViewMetrics = {};
function setMetrics(newMetrics) {
assign(initialViewMetrics, newMetrics);
scheduleViewUpdate();
}
var stopNavigationTracking = trackNavigationTimings(lifeCycle, function (navigationTimings) {
setLoadEvent(navigationTimings.loadEvent);
setMetrics(navigationTimings);
initialViewMetrics.navigationTimings = navigationTimings;
scheduleViewUpdate();
}).stop;
var firstHidden = trackFirstHidden(configuration);
var stopFCPTracking = trackFirstContentfulPaint(lifeCycle, firstHidden, function (firstContentfulPaint) {
return setMetrics({ firstContentfulPaint: firstContentfulPaint });
initialViewMetrics.firstContentfulPaint = firstContentfulPaint;
scheduleViewUpdate();
}).stop;
var stopLCPTracking = trackLargestContentfulPaint(lifeCycle, configuration, firstHidden, window, function (largestContentfulPaint, lcpElement) {
webVitalTelemetryDebug.addWebVitalTelemetryDebug('LCP', lcpElement, largestContentfulPaint);
setMetrics({
largestContentfulPaint: largestContentfulPaint,
});
var stopLCPTracking = trackLargestContentfulPaint(lifeCycle, configuration, firstHidden, window, function (largestContentfulPaint) {
initialViewMetrics.largestContentfulPaint = largestContentfulPaint;
scheduleViewUpdate();
}).stop;
var stopFIDTracking = trackFirstInputTimings(lifeCycle, firstHidden, function (_a) {
var firstInputDelay = _a.firstInputDelay, firstInputTime = _a.firstInputTime, firstInputTarget = _a.firstInputTarget;
webVitalTelemetryDebug.addWebVitalTelemetryDebug('FID', firstInputTarget, firstInputTime);
setMetrics({
firstInputDelay: firstInputDelay,
firstInputTime: firstInputTime,
});
var stopFIDTracking = trackFirstInput(lifeCycle, configuration, firstHidden, function (firstInput) {
initialViewMetrics.firstInput = firstInput;
scheduleViewUpdate();
}).stop;

@@ -35,0 +26,0 @@ function stop() {

import type { Duration } from '@datadog/browser-core';
import { type LifeCycle } from '../../lifeCycle';
import type { LifeCycle } from '../../lifeCycle';
import { ViewLoadingType } from '../../../rawRumEvent.types';
import type { RumConfiguration } from '../../configuration';
export interface InteractionToNextPaint {
value: Duration;
targetSelector?: string;
}
/**

@@ -10,4 +15,4 @@ * Track the interaction to next paint (INP).

*/
export declare function trackInteractionToNextPaint(viewLoadingType: ViewLoadingType, lifeCycle: LifeCycle): {
getInteractionToNextPaint: () => Duration | undefined;
export declare function trackInteractionToNextPaint(configuration: RumConfiguration, viewLoadingType: ViewLoadingType, lifeCycle: LifeCycle): {
getInteractionToNextPaint: () => InteractionToNextPaint | undefined;
stop: () => void;

@@ -14,0 +19,0 @@ };

import { noop, isExperimentalFeatureEnabled, ExperimentalFeature } from '@datadog/browser-core';
import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection';
import { RumPerformanceEntryType, supportPerformanceTimingEvent } from '../../../browser/performanceCollection';
import { getSelectorFromElement } from '../../getSelectorFromElement';
import { isElementNode } from '../../../browser/htmlDomUtils';
import { getInteractionCount, initInteractionCountPolyfill } from './interactionCountPolyfill';

@@ -12,3 +14,3 @@ // Arbitrary value to prevent unnecessary memory usage on views with lots of interactions.

*/
export function trackInteractionToNextPaint(viewLoadingType, lifeCycle) {
export function trackInteractionToNextPaint(configuration, viewLoadingType, lifeCycle) {
if (!isInteractionToNextPaintSupported() ||

@@ -23,13 +25,24 @@ !isExperimentalFeatureEnabled(ExperimentalFeature.INTERACTION_TO_NEXT_PAINT)) {

var longestInteractions = trackLongestInteractions(getViewInteractionCount);
var inpDuration = -1;
var interactionToNextPaint = -1;
var interactionToNextPaintTargetSelector;
var stop = lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {
for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
var entry = entries_1[_i];
if ((entry.entryType === 'event' || entry.entryType === 'first-input') && entry.interactionId) {
if ((entry.entryType === RumPerformanceEntryType.EVENT ||
entry.entryType === RumPerformanceEntryType.FIRST_INPUT) &&
entry.interactionId) {
longestInteractions.process(entry);
}
}
var newInpDuration = longestInteractions.estimateP98Duration();
if (newInpDuration) {
inpDuration = newInpDuration;
var newInteraction = longestInteractions.estimateP98Interaction();
if (newInteraction) {
interactionToNextPaint = newInteraction.duration;
if (isExperimentalFeatureEnabled(ExperimentalFeature.WEB_VITALS_ATTRIBUTION) &&
newInteraction.target &&
isElementNode(newInteraction.target)) {
interactionToNextPaintTargetSelector = getSelectorFromElement(newInteraction.target, configuration.actionNameAttribute);
}
else {
interactionToNextPaintTargetSelector = undefined;
}
}

@@ -41,7 +54,12 @@ }).unsubscribe;

// but the view interaction count > 0 then report 0
if (inpDuration >= 0) {
return inpDuration;
if (interactionToNextPaint >= 0) {
return {
value: interactionToNextPaint,
targetSelector: interactionToNextPaintTargetSelector,
};
}
else if (getViewInteractionCount()) {
return 0;
return {
value: 0,
};
}

@@ -82,6 +100,5 @@ },

*/
estimateP98Duration: function () {
var _a;
estimateP98Interaction: function () {
var interactionIndex = Math.min(longestInteractions.length - 1, Math.floor(getViewInteractionCount() / 50));
return (_a = longestInteractions[interactionIndex]) === null || _a === void 0 ? void 0 : _a.duration;
return longestInteractions[interactionIndex];
},

@@ -98,3 +115,3 @@ };

export function isInteractionToNextPaintSupported() {
return (supportPerformanceTimingEvent('event') &&
return (supportPerformanceTimingEvent(RumPerformanceEntryType.EVENT) &&
window.PerformanceEventTiming &&

@@ -101,0 +118,0 @@ 'interactionId' in PerformanceEventTiming.prototype);

import type { RelativeTime } from '@datadog/browser-core';
import { type LifeCycle } from '../../lifeCycle';
import type { LifeCycle } from '../../lifeCycle';
import type { RumConfiguration } from '../../configuration';
import type { FirstHidden } from './trackFirstHidden';
export declare const LCP_MAXIMUM_DELAY: number;
export interface LargestContentfulPaint {
value: RelativeTime;
targetSelector?: string;
}
/**

@@ -10,6 +14,6 @@ * Track the largest contentful paint (LCP) occurring during the initial View. This can yield

* Documentation: https://web.dev/lcp/
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getLCP.ts
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/onLCP.ts
*/
export declare function trackLargestContentfulPaint(lifeCycle: LifeCycle, configuration: RumConfiguration, firstHidden: FirstHidden, eventTarget: Window, callback: (lcpTiming: RelativeTime, lcpElement?: Element) => void): {
export declare function trackLargestContentfulPaint(lifeCycle: LifeCycle, configuration: RumConfiguration, firstHidden: FirstHidden, eventTarget: Window, callback: (largestContentfulPaint: LargestContentfulPaint) => void): {
stop: () => void;
};

@@ -1,2 +0,4 @@

import { ONE_MINUTE, addEventListeners, findLast } from '@datadog/browser-core';
import { ExperimentalFeature, ONE_MINUTE, addEventListeners, findLast, isExperimentalFeatureEnabled, } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../../browser/performanceCollection';
import { getSelectorFromElement } from '../../getSelectorFromElement';
// Discard LCP timings above a certain delay to avoid incorrect data

@@ -9,3 +11,3 @@ // It happens in some cases like sleep mode or some browser implementations

* Documentation: https://web.dev/lcp/
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getLCP.ts
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/onLCP.ts
*/

@@ -22,3 +24,3 @@ export function trackLargestContentfulPaint(lifeCycle, configuration, firstHidden, eventTarget, callback) {

var lcpEntry = findLast(entries, function (entry) {
return entry.entryType === 'largest-contentful-paint' &&
return entry.entryType === RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT &&
entry.startTime < firstInteractionTimestamp &&

@@ -29,3 +31,10 @@ entry.startTime < firstHidden.timeStamp &&

if (lcpEntry) {
callback(lcpEntry.startTime, lcpEntry.element);
var lcpTargetSelector = void 0;
if (isExperimentalFeatureEnabled(ExperimentalFeature.WEB_VITALS_ATTRIBUTION) && lcpEntry.element) {
lcpTargetSelector = getSelectorFromElement(lcpEntry.element, configuration.actionNameAttribute);
}
callback({
value: lcpEntry.startTime,
targetSelector: lcpTargetSelector,
});
}

@@ -32,0 +41,0 @@ }).unsubscribe;

import { relativeNow } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../../../browser/performanceCollection';
export function trackNavigationTimings(lifeCycle, callback) {

@@ -6,3 +7,3 @@ var stop = lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {

var entry = entries_1[_i];
if (entry.entryType === 'navigation') {
if (entry.entryType === RumPerformanceEntryType.NAVIGATION) {
callback({

@@ -9,0 +10,0 @@ domComplete: entry.domComplete,

import type { ClocksState, Duration } from '@datadog/browser-core';
import { Observable } from '@datadog/browser-core';
import type { RumConfiguration } from '../../configuration';

@@ -7,9 +8,14 @@ /** Arbitrary scroll throttle duration */

maxDepth: number;
maxDepthScrollHeight: number;
maxScrollHeight: number;
maxDepthScrollTop: number;
maxDepthTime: Duration;
maxScrollHeightTime: Duration;
}
export declare function trackScrollMetrics(configuration: RumConfiguration, viewStart: ClocksState, callback: (scrollMetrics: ScrollMetrics) => void, getScrollValues?: typeof computeScrollValues): {
export declare function trackScrollMetrics(configuration: RumConfiguration, viewStart: ClocksState, callback: (scrollMetrics: ScrollMetrics) => void, scrollValues?: Observable<ScrollValues>): {
stop: () => void;
};
export interface ScrollValues {
scrollDepth: number;
scrollTop: number;
scrollHeight: number;
}
export declare function computeScrollValues(): {

@@ -20,1 +26,2 @@ scrollHeight: number;

};
export declare function createScrollValuesObservable(configuration: RumConfiguration, throttleDuration?: number): Observable<ScrollValues>;

@@ -1,2 +0,2 @@

import { ONE_SECOND, elapsed, relativeNow, throttle, addEventListener } from '@datadog/browser-core';
import { Observable, ONE_SECOND, elapsed, relativeNow, throttle, addEventListener, monitor, } from '@datadog/browser-core';
import { getScrollY } from '../../../browser/scroll';

@@ -6,27 +6,31 @@ import { getViewportDimension } from '../../../browser/viewportObservable';

export var THROTTLE_SCROLL_DURATION = ONE_SECOND;
export function trackScrollMetrics(configuration, viewStart, callback, getScrollValues) {
if (getScrollValues === void 0) { getScrollValues = computeScrollValues; }
var maxDepth = 0;
var handleScrollEvent = throttle(function () {
var _a = getScrollValues(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop;
if (scrollDepth > maxDepth) {
export function trackScrollMetrics(configuration, viewStart, callback, scrollValues) {
if (scrollValues === void 0) { scrollValues = createScrollValuesObservable(configuration); }
var maxScrollDepth = 0;
var maxScrollHeight = 0;
var maxScrollHeightTime = 0;
var subscription = scrollValues.subscribe(function (_a) {
var scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop, scrollHeight = _a.scrollHeight;
var shouldUpdate = false;
if (scrollDepth > maxScrollDepth) {
maxScrollDepth = scrollDepth;
shouldUpdate = true;
}
if (scrollHeight > maxScrollHeight) {
maxScrollHeight = scrollHeight;
var now = relativeNow();
var maxDepthTime = elapsed(viewStart.relative, now);
maxDepth = scrollDepth;
maxScrollHeightTime = elapsed(viewStart.relative, now);
shouldUpdate = true;
}
if (shouldUpdate) {
callback({
maxDepth: maxDepth,
maxDepthScrollHeight: scrollHeight,
maxDepthTime: maxDepthTime,
maxDepth: Math.min(maxScrollDepth, maxScrollHeight),
maxDepthScrollTop: scrollTop,
maxScrollHeight: maxScrollHeight,
maxScrollHeightTime: maxScrollHeightTime,
});
}
}, THROTTLE_SCROLL_DURATION, { leading: false, trailing: true });
var stop = addEventListener(configuration, window, "scroll" /* DOM_EVENT.SCROLL */, handleScrollEvent.throttled, {
passive: true,
}).stop;
});
return {
stop: function () {
handleScrollEvent.cancel();
stop();
},
stop: function () { return subscription.unsubscribe(); },
};

@@ -45,2 +49,28 @@ }

}
export function createScrollValuesObservable(configuration, throttleDuration) {
if (throttleDuration === void 0) { throttleDuration = THROTTLE_SCROLL_DURATION; }
var observable = new Observable(function () {
function notify() {
observable.notify(computeScrollValues());
}
if (window.ResizeObserver) {
var throttledNotify_1 = throttle(notify, throttleDuration, {
leading: false,
trailing: true,
});
var observerTarget_1 = document.scrollingElement || document.documentElement;
var resizeObserver_1 = new ResizeObserver(monitor(throttledNotify_1.throttled));
resizeObserver_1.observe(observerTarget_1);
var eventListener_1 = addEventListener(configuration, window, "scroll" /* DOM_EVENT.SCROLL */, throttledNotify_1.throttled, {
passive: true,
});
return function () {
throttledNotify_1.cancel();
resizeObserver_1.unobserve(observerTarget_1);
eventListener_1.stop();
};
}
});
return observable;
}
//# sourceMappingURL=trackScrollMetrics.js.map
import { instrumentMethodAndCallOriginal, matchList, monitor, Observable, timeStampNow, setTimeout, clearTimeout, } from '@datadog/browser-core';
import { RumPerformanceEntryType } from '../browser/performanceCollection';
// Delay to wait for a page activity to validate the tracking process

@@ -78,3 +79,3 @@ export var PAGE_ACTIVITY_VALIDATION_DELAY = 100;

subscriptions.push(domMutationObservable.subscribe(notifyPageActivity), lifeCycle.subscribe(0 /* LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED */, function (entries) {
if (entries.some(function (entry) { return entry.entryType === 'resource' && !isExcludedUrl(configuration, entry.name); })) {
if (entries.some(function (entry) { return entry.entryType === RumPerformanceEntryType.RESOURCE && !isExcludedUrl(configuration, entry.name); })) {
notifyPageActivity();

@@ -81,0 +82,0 @@ }

@@ -15,4 +15,4 @@ export { RumPublicApi, makeRumPublicApi, RecorderApi, StartRum } from './boot/rumPublicApi';

export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/action/getActionNameFromElement';
export { STABLE_ATTRIBUTES } from './domain/action/getSelectorFromElement';
export { STABLE_ATTRIBUTES } from './domain/getSelectorFromElement';
export * from './browser/htmlDomUtils';
export { getSessionReplayUrl } from './domain/getSessionReplayUrl';

@@ -8,5 +8,5 @@ export { makeRumPublicApi } from './boot/rumPublicApi';

export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/action/getActionNameFromElement';
export { STABLE_ATTRIBUTES } from './domain/action/getSelectorFromElement';
export { STABLE_ATTRIBUTES } from './domain/getSelectorFromElement';
export * from './browser/htmlDomUtils';
export { getSessionReplayUrl } from './domain/getSessionReplayUrl';
//# sourceMappingURL=index.js.map

@@ -70,4 +70,7 @@ import type { Context, Duration, ErrorSource, ErrorHandling, ResourceType, ServerDuration, TimeStamp, RawErrorCause, DefaultPrivacyLevel } from '@datadog/browser-core';

first_input_time?: ServerDuration;
first_input_target_selector?: string;
interaction_to_next_paint?: ServerDuration;
interaction_to_next_paint_target_selector?: string;
cumulative_layout_shift?: number;
cumulative_layout_shift_target_selector?: string;
custom_timings?: {

@@ -77,2 +80,3 @@ [key: string]: ServerDuration;

largest_contentful_paint?: ServerDuration;
largest_contentful_paint_target_selector?: string;
dom_interactive?: ServerDuration;

@@ -111,5 +115,5 @@ dom_content_loaded?: ServerDuration;

max_depth?: number;
max_depth_scroll_height?: number;
max_depth_scroll_top?: number;
max_depth_time?: ServerDuration;
max_scroll_height?: number;
max_scroll_height_time?: ServerDuration;
};

@@ -116,0 +120,0 @@ }

@@ -460,2 +460,24 @@ /**

};
/**
* GraphQL requests parameters
*/
readonly graphql?: {
/**
* Type of the GraphQL operation
*/
readonly operationType: 'query' | 'mutation' | 'subscription';
/**
* Name of the GraphQL operation
*/
readonly operationName?: string;
/**
* Content of the GraphQL operation
*/
payload?: string;
/**
* String representation of the operation variables
*/
variables?: string;
[k: string]: unknown;
};
[k: string]: unknown;

@@ -520,2 +542,6 @@ };

/**
* CSS selector path of the largest contentful paint element
*/
readonly largest_contentful_paint_target_selector?: string;
/**
* Duration in ns of the first input event delay

@@ -529,2 +555,6 @@ */

/**
* CSS selector path of the first input target element
*/
readonly first_input_target_selector?: string;
/**
* Longest duration in ns between an interaction and the next paint

@@ -534,2 +564,6 @@ */

/**
* CSS selector path of the interacted element corresponding to INP
*/
readonly interaction_to_next_paint_target_selector?: string;
/**
* Total layout shift score that occurred on the view

@@ -539,2 +573,6 @@ */

/**
* CSS selector path of the first element (in document order) of the largest layout shift contributing to CLS
*/
readonly cumulative_layout_shift_target_selector?: string;
/**
* Duration in ns to the complete parsing and loading of the document and its sub resources

@@ -784,6 +822,2 @@ */

/**
* Page scroll height (total height) when the maximum scroll depth was reached for this view (in pixels)
*/
readonly max_depth_scroll_height: number;
/**
* Page scroll top (scrolled distance) when the maximum scroll depth was reached for this view (in pixels)

@@ -793,5 +827,9 @@ */

/**
* Duration between the view start and the scroll event that reached the maximum scroll depth for this view (in nanoseconds)
* Maximum page scroll height (total height) for this view (in pixels)
*/
readonly max_depth_time: number;
readonly max_scroll_height: number;
/**
* Duration between the view start and the time the max scroll height was reached for this view (in nanoseconds)
*/
readonly max_scroll_height_time: number;
[k: string]: unknown;

@@ -830,2 +868,6 @@ };

/**
* The build version for this application
*/
readonly build_version?: string;
/**
* Session properties

@@ -832,0 +874,0 @@ */

{
"name": "@datadog/browser-rum-core",
"version": "4.49.0",
"version": "4.50.0",
"license": "Apache-2.0",

@@ -15,3 +15,3 @@ "main": "cjs/index.js",

"dependencies": {
"@datadog/browser-core": "4.49.0"
"@datadog/browser-core": "4.50.0"
},

@@ -32,3 +32,3 @@ "devDependencies": {

},
"gitHead": "4aa09a00c7457f4d4f302b15bc1c1bb645072016"
"gitHead": "6bb23089915b99c9dab8edbf0131b5edc09eb4b5"
}

@@ -1,2 +0,2 @@

import type { Context, InitConfiguration, TimeStamp, RelativeTime, User, Observable } from '@datadog/browser-core'
import type { Context, InitConfiguration, TimeStamp, RelativeTime, User } from '@datadog/browser-core'
import {

@@ -57,4 +57,2 @@ noop,

) => string | undefined
getSerializedNodeId: (node: Node) => number | undefined
recorderStartObservable: Observable<RelativeTime>
}

@@ -61,0 +59,0 @@ interface RumPublicApiOptions {

@@ -39,3 +39,2 @@ import type { Observable, TelemetryEvent, RawError, ContextManager } from '@datadog/browser-core'

import { buildCommonContext } from '../domain/contexts/commonContext'
import { startWebVitalTelemetryDebug } from '../domain/view/startWebVitalTelemetryDebug'
import { startDisplayContext } from '../domain/contexts/displayContext'

@@ -136,3 +135,2 @@ import type { RecorderApi } from './rumPublicApi'

const webVitalTelemetryDebug = startWebVitalTelemetryDebug(configuration, telemetry, recorderApi, session)
const {

@@ -151,3 +149,2 @@ addTiming,

recorderApi,
webVitalTelemetryDebug,
initialViewOptions

@@ -154,0 +151,0 @@ )

@@ -14,2 +14,3 @@ import type { Duration, RelativeTime, TimeStamp } from '@datadog/browser-core'

addEventListener,
objectHasValue,
} from '@datadog/browser-core'

@@ -36,4 +37,18 @@

// We want to use a real enum (i.e. not a const enum) here, to be able to check whether an arbitrary
// string is an expected performance entry
// eslint-disable-next-line no-restricted-syntax
export enum RumPerformanceEntryType {
EVENT = 'event',
FIRST_INPUT = 'first-input',
LARGEST_CONTENTFUL_PAINT = 'largest-contentful-paint',
LAYOUT_SHIFT = 'layout-shift',
LONG_TASK = 'longtask',
NAVIGATION = 'navigation',
PAINT = 'paint',
RESOURCE = 'resource',
}
export interface RumPerformanceResourceTiming {
entryType: 'resource'
entryType: RumPerformanceEntryType.RESOURCE
initiatorType: string

@@ -56,6 +71,7 @@ name: string

traceId?: string
toJSON(): PerformanceEntryRepresentation
}
export interface RumPerformanceLongTaskTiming {
entryType: 'longtask'
entryType: RumPerformanceEntryType.LONG_TASK
startTime: RelativeTime

@@ -67,3 +83,3 @@ duration: Duration

export interface RumPerformancePaintTiming {
entryType: 'paint'
entryType: RumPerformanceEntryType.PAINT
name: 'first-paint' | 'first-contentful-paint'

@@ -74,3 +90,3 @@ startTime: RelativeTime

export interface RumPerformanceNavigationTiming {
entryType: 'navigation'
entryType: RumPerformanceEntryType.NAVIGATION
domComplete: RelativeTime

@@ -84,3 +100,3 @@ domContentLoadedEventEnd: RelativeTime

export interface RumLargestContentfulPaintTiming {
entryType: 'largest-contentful-paint'
entryType: RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT
startTime: RelativeTime

@@ -92,3 +108,3 @@ size: number

export interface RumFirstInputTiming {
entryType: 'first-input'
entryType: RumPerformanceEntryType.FIRST_INPUT
startTime: RelativeTime

@@ -102,10 +118,11 @@ processingStart: RelativeTime

export interface RumPerformanceEventTiming {
entryType: 'event'
entryType: RumPerformanceEntryType.EVENT
startTime: RelativeTime
duration: Duration
interactionId?: number
target?: Node
}
export interface RumLayoutShiftTiming {
entryType: 'layout-shift'
entryType: RumPerformanceEntryType.LAYOUT_SHIFT
startTime: RelativeTime

@@ -133,3 +150,3 @@ value: number

export function supportPerformanceTimingEvent(entryType: string) {
export function supportPerformanceTimingEvent(entryType: RumPerformanceEntryType) {
return (

@@ -158,4 +175,14 @@ window.PerformanceObserver &&

)
const mainEntries = ['resource', 'navigation', 'longtask', 'paint']
const experimentalEntries = ['largest-contentful-paint', 'first-input', 'layout-shift', 'event']
const mainEntries = [
RumPerformanceEntryType.RESOURCE,
RumPerformanceEntryType.NAVIGATION,
RumPerformanceEntryType.LONG_TASK,
RumPerformanceEntryType.PAINT,
]
const experimentalEntries = [
RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT,
RumPerformanceEntryType.FIRST_INPUT,
RumPerformanceEntryType.LAYOUT_SHIFT,
RumPerformanceEntryType.EVENT,
]

@@ -192,3 +219,3 @@ try {

}
if (!supportPerformanceTimingEvent('navigation')) {
if (!supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION)) {
retrieveNavigationTiming(configuration, (timing) => {

@@ -198,3 +225,3 @@ handleRumPerformanceEntries(lifeCycle, configuration, [timing])

}
if (!supportPerformanceTimingEvent('first-input')) {
if (!supportPerformanceTimingEvent(RumPerformanceEntryType.FIRST_INPUT)) {
retrieveFirstInputTiming(configuration, (timing) => {

@@ -214,8 +241,12 @@ handleRumPerformanceEntries(lifeCycle, configuration, [timing])

const forcedAttributes = {
entryType: 'resource' as const,
entryType: RumPerformanceEntryType.RESOURCE as const,
initiatorType: FAKE_INITIAL_DOCUMENT,
traceId: getDocumentTraceId(document),
toJSON: () => assign({}, timing, { toJSON: undefined }),
}
if (supportPerformanceTimingEvent('navigation') && performance.getEntriesByType('navigation').length > 0) {
const navigationEntry = performance.getEntriesByType('navigation')[0]
if (
supportPerformanceTimingEvent(RumPerformanceEntryType.NAVIGATION) &&
performance.getEntriesByType(RumPerformanceEntryType.NAVIGATION).length > 0
) {
const navigationEntry = performance.getEntriesByType(RumPerformanceEntryType.NAVIGATION)[0]
timing = assign(navigationEntry.toJSON(), forcedAttributes)

@@ -246,3 +277,3 @@ } else {

assign(computeRelativePerformanceTiming(), {
entryType: 'navigation' as const,
entryType: RumPerformanceEntryType.NAVIGATION as const,
})

@@ -280,3 +311,3 @@ )

const timing: RumFirstInputTiming = {
entryType: 'first-input',
entryType: RumPerformanceEntryType.FIRST_INPUT,
processingStart: relativeNow(),

@@ -355,13 +386,5 @@ startTime: evt.timeStamp as RelativeTime,

) {
const rumPerformanceEntries = entries.filter(
(entry) =>
entry.entryType === 'resource' ||
entry.entryType === 'navigation' ||
entry.entryType === 'paint' ||
entry.entryType === 'longtask' ||
entry.entryType === 'largest-contentful-paint' ||
entry.entryType === 'first-input' ||
entry.entryType === 'layout-shift' ||
entry.entryType === 'event'
) as RumPerformanceEntry[]
const rumPerformanceEntries = entries.filter((entry): entry is RumPerformanceEntry =>
objectHasValue(RumPerformanceEntryType, entry.entryType)
)

@@ -378,7 +401,7 @@ const rumAllowedPerformanceEntries = rumPerformanceEntries.filter(

function isIncompleteNavigation(entry: RumPerformanceEntry) {
return entry.entryType === 'navigation' && entry.loadEventEnd <= 0
return entry.entryType === RumPerformanceEntryType.NAVIGATION && entry.loadEventEnd <= 0
}
function isForbiddenResource(configuration: RumConfiguration, entry: RumPerformanceEntry) {
return entry.entryType === 'resource' && !isAllowedRequestUrl(configuration, entry.name)
return entry.entryType === RumPerformanceEntryType.RESOURCE && !isAllowedRequestUrl(configuration, entry.name)
}

@@ -22,6 +22,6 @@ import type { Duration, ClocksState, RelativeTime, TimeStamp } from '@datadog/browser-core'

import { PAGE_ACTIVITY_VALIDATION_DELAY, waitPageActivityEnd } from '../waitPageActivityEnd'
import { getSelectorFromElement } from '../getSelectorFromElement'
import type { ClickChain } from './clickChain'
import { createClickChain } from './clickChain'
import { getActionNameFromElement } from './getActionNameFromElement'
import { getSelectorFromElement } from './getSelectorFromElement'
import type { MouseEventOnElement, UserActivity } from './listenActionEvents'

@@ -28,0 +28,0 @@ import { listenActionEvents } from './listenActionEvents'

@@ -7,2 +7,3 @@ import { toServerDuration, relativeToClocks, generateUUID } from '@datadog/browser-core'

import type { RumSessionManager } from '../rumSessionManager'
import { RumPerformanceEntryType } from '../../browser/performanceCollection'

@@ -12,3 +13,3 @@ export function startLongTaskCollection(lifeCycle: LifeCycle, sessionManager: RumSessionManager) {

for (const entry of entries) {
if (entry.entryType !== 'longtask') {
if (entry.entryType !== RumPerformanceEntryType.LONG_TASK) {
break

@@ -15,0 +16,0 @@ }

@@ -16,2 +16,3 @@ import {

import type { RumPerformanceEntry, RumPerformanceResourceTiming } from '../../browser/performanceCollection'
import { RumPerformanceEntryType } from '../../browser/performanceCollection'
import type {

@@ -54,3 +55,3 @@ PerformanceEntryRepresentation,

for (const entry of entries) {
if (entry.entryType === 'resource' && !isRequestKind(entry)) {
if (entry.entryType === RumPerformanceEntryType.RESOURCE && !isRequestKind(entry)) {
lifeCycle.notify(

@@ -57,0 +58,0 @@ LifeCycleEventType.RAW_RUM_EVENT_COLLECTED,

@@ -30,5 +30,4 @@ import type { Duration, ClocksState, TimeStamp, Subscription, RelativeTime } from '@datadog/browser-core'

import { trackViewEventCounts } from './trackViewEventCounts'
import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug'
import { trackInitialViewMetrics } from './viewMetrics/trackInitialViewMetrics'
import type { InitialViewMetrics } from './viewMetrics/trackInitialViewMetrics'
import { trackInitialViewMetrics } from './viewMetrics/trackInitialViewMetrics'
import type { CommonViewMetrics } from './viewMetrics/trackCommonViewMetrics'

@@ -91,3 +90,2 @@ import { trackCommonViewMetrics } from './viewMetrics/trackCommonViewMetrics'

areViewsTrackedAutomatically: boolean,
webVitalTelemetryDebug: WebVitalTelemetryDebug,
initialViewOptions?: ViewOptions

@@ -112,3 +110,2 @@ ) {

loadingType,
webVitalTelemetryDebug,
startClocks,

@@ -177,3 +174,2 @@ viewOptions

loadingType: ViewLoadingType,
webVitalTelemetryDebug: WebVitalTelemetryDebug,
startClocks: ClocksState = clocksNow(),

@@ -227,4 +223,3 @@ viewOptions?: ViewOptions

loadingType,
startClocks,
webVitalTelemetryDebug
startClocks
)

@@ -234,3 +229,3 @@

loadingType === ViewLoadingType.INITIAL_LOAD
? trackInitialViewMetrics(lifeCycle, configuration, webVitalTelemetryDebug, setLoadEvent, scheduleViewUpdate)
? trackInitialViewMetrics(lifeCycle, configuration, setLoadEvent, scheduleViewUpdate)
: { stop: noop, initialViewMetrics: {} as InitialViewMetrics }

@@ -237,0 +232,0 @@

@@ -22,3 +22,2 @@ import type { Duration, ServerDuration, Observable } from '@datadog/browser-core'

import { trackViews } from './trackViews'
import type { WebVitalTelemetryDebug } from './startWebVitalTelemetryDebug'

@@ -34,3 +33,2 @@ export function startViewCollection(

recorderApi: RecorderApi,
webVitalTelemetryDebug: WebVitalTelemetryDebug,
initialViewOptions?: ViewOptions

@@ -51,3 +49,2 @@ ) {

!configuration.trackViewsManually,
webVitalTelemetryDebug,
initialViewOptions

@@ -83,7 +80,8 @@ )

},
cumulative_layout_shift: view.commonViewMetrics.cumulativeLayoutShift,
first_byte: toServerDuration(view.initialViewMetrics.firstByte),
dom_complete: toServerDuration(view.initialViewMetrics.domComplete),
dom_content_loaded: toServerDuration(view.initialViewMetrics.domContentLoaded),
dom_interactive: toServerDuration(view.initialViewMetrics.domInteractive),
cumulative_layout_shift: view.commonViewMetrics.cumulativeLayoutShift?.value,
cumulative_layout_shift_target_selector: view.commonViewMetrics.cumulativeLayoutShift?.targetSelector,
first_byte: toServerDuration(view.initialViewMetrics.navigationTimings?.firstByte),
dom_complete: toServerDuration(view.initialViewMetrics.navigationTimings?.domComplete),
dom_content_loaded: toServerDuration(view.initialViewMetrics.navigationTimings?.domContentLoaded),
dom_interactive: toServerDuration(view.initialViewMetrics.navigationTimings?.domInteractive),
error: {

@@ -93,9 +91,12 @@ count: view.eventCounts.errorCount,

first_contentful_paint: toServerDuration(view.initialViewMetrics.firstContentfulPaint),
first_input_delay: toServerDuration(view.initialViewMetrics.firstInputDelay),
first_input_time: toServerDuration(view.initialViewMetrics.firstInputTime),
interaction_to_next_paint: toServerDuration(view.commonViewMetrics.interactionToNextPaint),
first_input_delay: toServerDuration(view.initialViewMetrics.firstInput?.delay),
first_input_time: toServerDuration(view.initialViewMetrics.firstInput?.time),
first_input_target_selector: view.initialViewMetrics.firstInput?.targetSelector,
interaction_to_next_paint: toServerDuration(view.commonViewMetrics.interactionToNextPaint?.value),
interaction_to_next_paint_target_selector: view.commonViewMetrics.interactionToNextPaint?.targetSelector,
is_active: view.isActive,
name: view.name,
largest_contentful_paint: toServerDuration(view.initialViewMetrics.largestContentfulPaint),
load_event: toServerDuration(view.initialViewMetrics.loadEvent),
largest_contentful_paint: toServerDuration(view.initialViewMetrics.largestContentfulPaint?.value),
largest_contentful_paint_target_selector: view.initialViewMetrics.largestContentfulPaint?.targetSelector,
load_event: toServerDuration(view.initialViewMetrics.navigationTimings?.loadEvent),
loading_time: discardNegativeDuration(toServerDuration(view.commonViewMetrics.loadingTime)),

@@ -118,5 +119,5 @@ loading_type: view.loadingType,

max_depth: view.commonViewMetrics.scroll.maxDepth,
max_depth_scroll_height: view.commonViewMetrics.scroll.maxDepthScrollHeight,
max_depth_scroll_top: view.commonViewMetrics.scroll.maxDepthScrollTop,
max_depth_time: toServerDuration(view.commonViewMetrics.scroll.maxDepthTime),
max_scroll_height: view.commonViewMetrics.scroll.maxScrollHeight,
max_scroll_height_time: toServerDuration(view.commonViewMetrics.scroll.maxScrollHeightTime),
},

@@ -123,0 +124,0 @@ }

import type { ClocksState, Duration, Observable } from '@datadog/browser-core'
import { noop } from '@datadog/browser-core'
import type { ViewLoadingType } from '../../../rawRumEvent.types'
import type { RumConfiguration } from '../../configuration'
import type { LifeCycle } from '../../lifeCycle'
import type { WebVitalTelemetryDebug } from '../startWebVitalTelemetryDebug'
import type { CumulativeLayoutShift } from './trackCumulativeLayoutShift'
import { trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'
import type { InteractionToNextPaint } from './trackInteractionToNextPaint'
import { trackInteractionToNextPaint } from './trackInteractionToNextPaint'
import { trackLoadingTime } from './trackLoadingTime'
import type { ScrollMetrics } from './trackScrollMetrics'
import { computeScrollValues, trackScrollMetrics } from './trackScrollMetrics'
import { trackLoadingTime } from './trackLoadingTime'
import { isLayoutShiftSupported, trackCumulativeLayoutShift } from './trackCumulativeLayoutShift'
import { trackInteractionToNextPaint } from './trackInteractionToNextPaint'
import { trackScrollMetrics } from './trackScrollMetrics'
export interface CommonViewMetrics {
loadingTime?: Duration
cumulativeLayoutShift?: number
interactionToNextPaint?: Duration
cumulativeLayoutShift?: CumulativeLayoutShift
interactionToNextPaint?: InteractionToNextPaint
scroll?: ScrollMetrics

@@ -26,4 +26,3 @@ }

loadingType: ViewLoadingType,
viewStart: ClocksState,
webVitalTelemetryDebug: WebVitalTelemetryDebug
viewStart: ClocksState
) {

@@ -40,13 +39,2 @@ const commonViewMetrics: CommonViewMetrics = {}

commonViewMetrics.loadingTime = newLoadingTime
// We compute scroll metrics at loading time to ensure we have scroll data when loading the view initially
// This is to ensure that we have the depth data even if the user didn't scroll or if the view is not scrollable.
const { scrollHeight, scrollDepth, scrollTop } = computeScrollValues()
commonViewMetrics.scroll = {
maxDepth: scrollDepth,
maxDepthScrollHeight: scrollHeight,
maxDepthTime: newLoadingTime,
maxDepthScrollTop: scrollTop,
}
scheduleViewUpdate()

@@ -56,33 +44,17 @@ }

const { stop: stopScrollMetricsTracking } = trackScrollMetrics(
const { stop: stopScrollMetricsTracking } = trackScrollMetrics(configuration, viewStart, (newScrollMetrics) => {
commonViewMetrics.scroll = newScrollMetrics
})
const { stop: stopCLSTracking } = trackCumulativeLayoutShift(configuration, lifeCycle, (cumulativeLayoutShift) => {
commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift
scheduleViewUpdate()
})
const { stop: stopINPTracking, getInteractionToNextPaint } = trackInteractionToNextPaint(
configuration,
viewStart,
(newScrollMetrics) => {
commonViewMetrics.scroll = newScrollMetrics
},
computeScrollValues
loadingType,
lifeCycle
)
let stopCLSTracking: () => void
let clsAttributionCollected = false
if (isLayoutShiftSupported()) {
commonViewMetrics.cumulativeLayoutShift = 0
;({ stop: stopCLSTracking } = trackCumulativeLayoutShift(
lifeCycle,
(cumulativeLayoutShift, largestLayoutShiftNode, largestLayoutShiftTime) => {
commonViewMetrics.cumulativeLayoutShift = cumulativeLayoutShift
if (!clsAttributionCollected) {
clsAttributionCollected = true
webVitalTelemetryDebug.addWebVitalTelemetryDebug('CLS', largestLayoutShiftNode, largestLayoutShiftTime)
}
scheduleViewUpdate()
}
))
} else {
stopCLSTracking = noop
}
const { stop: stopINPTracking, getInteractionToNextPaint } = trackInteractionToNextPaint(loadingType, lifeCycle)
return {

@@ -89,0 +61,0 @@ stop: () => {

@@ -1,6 +0,23 @@

import { round, type RelativeTime, find, ONE_SECOND } from '@datadog/browser-core'
import {
round,
type RelativeTime,
find,
ONE_SECOND,
isExperimentalFeatureEnabled,
ExperimentalFeature,
noop,
} from '@datadog/browser-core'
import { isElementNode } from '../../../browser/htmlDomUtils'
import type { LifeCycle } from '../../lifeCycle'
import { LifeCycleEventType } from '../../lifeCycle'
import { supportPerformanceTimingEvent, type RumLayoutShiftTiming } from '../../../browser/performanceCollection'
import type { RumLayoutShiftTiming } from '../../../browser/performanceCollection'
import { supportPerformanceTimingEvent, RumPerformanceEntryType } from '../../../browser/performanceCollection'
import { getSelectorFromElement } from '../../getSelectorFromElement'
import type { RumConfiguration } from '../../configuration'
export interface CumulativeLayoutShift {
value: number
targetSelector?: string
}
/**

@@ -24,11 +41,24 @@ * Track the cumulative layout shifts (CLS).

export function trackCumulativeLayoutShift(
configuration: RumConfiguration,
lifeCycle: LifeCycle,
callback: (layoutShift: number, largestShiftNode: Node | undefined, largestShiftTime: RelativeTime) => void
callback: (cumulativeLayoutShift: CumulativeLayoutShift) => void
) {
if (!isLayoutShiftSupported()) {
return {
stop: noop,
}
}
let maxClsValue = 0
// if no layout shift happen the value should be reported as 0
callback({
value: 0,
})
const window = slidingSessionWindow()
const { unsubscribe: stop } = lifeCycle.subscribe(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, (entries) => {
for (const entry of entries) {
if (entry.entryType === 'layout-shift' && !entry.hadRecentInput) {
if (entry.entryType === RumPerformanceEntryType.LAYOUT_SHIFT && !entry.hadRecentInput) {
window.update(entry)

@@ -38,3 +68,14 @@

maxClsValue = window.value()
callback(round(maxClsValue, 4), window.largestLayoutShiftNode(), window.largestLayoutShiftTime())
const cls = round(maxClsValue, 4)
const clsTarget = window.largestLayoutShiftTarget()
let cslTargetSelector
if (isExperimentalFeatureEnabled(ExperimentalFeature.WEB_VITALS_ATTRIBUTION) && clsTarget) {
cslTargetSelector = getSelectorFromElement(clsTarget, configuration.actionNameAttribute)
}
callback({
value: cls,
targetSelector: cslTargetSelector,
})
}

@@ -56,3 +97,3 @@ }

let largestLayoutShift = 0
let largestLayoutShiftNode: Node | undefined
let largestLayoutShiftTarget: HTMLElement | undefined
let largestLayoutShiftTime: RelativeTime

@@ -70,3 +111,3 @@

largestLayoutShift = 0
largestLayoutShiftNode = undefined
largestLayoutShiftTarget = undefined
} else {

@@ -82,6 +123,8 @@ value += entry.value

if (entry.sources?.length) {
const largestLayoutShiftSource = find(entry.sources, (s) => s.node?.nodeType === 1) || entry.sources[0]
largestLayoutShiftNode = largestLayoutShiftSource.node
largestLayoutShiftTarget = find(
entry.sources,
(s): s is { node: HTMLElement } => !!s.node && isElementNode(s.node)
)?.node
} else {
largestLayoutShiftNode = undefined
largestLayoutShiftTarget = undefined
}

@@ -91,3 +134,3 @@ }

value: () => value,
largestLayoutShiftNode: () => largestLayoutShiftNode,
largestLayoutShiftTarget: () => largestLayoutShiftTarget,
largestLayoutShiftTime: () => largestLayoutShiftTime,

@@ -101,3 +144,3 @@ }

export function isLayoutShiftSupported() {
return supportPerformanceTimingEvent('layout-shift')
return supportPerformanceTimingEvent(RumPerformanceEntryType.LAYOUT_SHIFT)
}

@@ -6,2 +6,3 @@ import type { RelativeTime } from '@datadog/browser-core'

import type { RumPerformancePaintTiming } from '../../../browser/performanceCollection'
import { RumPerformanceEntryType } from '../../../browser/performanceCollection'
import type { FirstHidden } from './trackFirstHidden'

@@ -24,3 +25,3 @@

(entry): entry is RumPerformancePaintTiming =>
entry.entryType === 'paint' &&
entry.entryType === RumPerformanceEntryType.PAINT &&
entry.name === 'first-contentful-paint' &&

@@ -27,0 +28,0 @@ entry.startTime < firstHidden.timeStamp &&

import type { Duration } from '@datadog/browser-core'
import { assign } from '@datadog/browser-core'
import type { RumConfiguration } from '../../configuration'
import type { LifeCycle } from '../../lifeCycle'
import type { WebVitalTelemetryDebug } from '../startWebVitalTelemetryDebug'
import { trackFirstContentfulPaint } from './trackFirstContentfulPaint'
import { trackFirstInputTimings } from './trackFirstInputTimings'
import type { FirstInput } from './trackFirstInput'
import { trackFirstInput } from './trackFirstInput'
import type { NavigationTimings } from './trackNavigationTimings'
import { trackNavigationTimings } from './trackNavigationTimings'
import type { LargestContentfulPaint } from './trackLargestContentfulPaint'
import { trackLargestContentfulPaint } from './trackLargestContentfulPaint'

@@ -14,10 +15,5 @@ import { trackFirstHidden } from './trackFirstHidden'

firstContentfulPaint?: Duration
firstByte?: Duration
domInteractive?: Duration
domContentLoaded?: Duration
domComplete?: Duration
loadEvent?: Duration
largestContentfulPaint?: Duration
firstInputDelay?: Duration
firstInputTime?: Duration
navigationTimings?: NavigationTimings
largestContentfulPaint?: LargestContentfulPaint
firstInput?: FirstInput
}

@@ -28,3 +24,2 @@

configuration: RumConfiguration,
webVitalTelemetryDebug: WebVitalTelemetryDebug,
setLoadEvent: (loadEnd: Duration) => void,

@@ -35,15 +30,14 @@ scheduleViewUpdate: () => void

function setMetrics(newMetrics: Partial<InitialViewMetrics>) {
assign(initialViewMetrics, newMetrics)
scheduleViewUpdate()
}
const { stop: stopNavigationTracking } = trackNavigationTimings(lifeCycle, (navigationTimings) => {
setLoadEvent(navigationTimings.loadEvent)
setMetrics(navigationTimings)
initialViewMetrics.navigationTimings = navigationTimings
scheduleViewUpdate()
})
const firstHidden = trackFirstHidden(configuration)
const { stop: stopFCPTracking } = trackFirstContentfulPaint(lifeCycle, firstHidden, (firstContentfulPaint) =>
setMetrics({ firstContentfulPaint })
)
const { stop: stopFCPTracking } = trackFirstContentfulPaint(lifeCycle, firstHidden, (firstContentfulPaint) => {
initialViewMetrics.firstContentfulPaint = firstContentfulPaint
scheduleViewUpdate()
})
const { stop: stopLCPTracking } = trackLargestContentfulPaint(

@@ -54,24 +48,13 @@ lifeCycle,

window,
(largestContentfulPaint, lcpElement) => {
webVitalTelemetryDebug.addWebVitalTelemetryDebug('LCP', lcpElement, largestContentfulPaint)
setMetrics({
largestContentfulPaint,
})
(largestContentfulPaint) => {
initialViewMetrics.largestContentfulPaint = largestContentfulPaint
scheduleViewUpdate()
}
)
const { stop: stopFIDTracking } = trackFirstInputTimings(
lifeCycle,
firstHidden,
({ firstInputDelay, firstInputTime, firstInputTarget }) => {
webVitalTelemetryDebug.addWebVitalTelemetryDebug('FID', firstInputTarget, firstInputTime)
const { stop: stopFIDTracking } = trackFirstInput(lifeCycle, configuration, firstHidden, (firstInput) => {
initialViewMetrics.firstInput = firstInput
scheduleViewUpdate()
})
setMetrics({
firstInputDelay,
firstInputTime,
})
}
)
function stop() {

@@ -78,0 +61,0 @@ stopNavigationTracking()

import { noop, isExperimentalFeatureEnabled, ExperimentalFeature } from '@datadog/browser-core'
import type { Duration } from '@datadog/browser-core'
import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection'
import { RumPerformanceEntryType, supportPerformanceTimingEvent } from '../../../browser/performanceCollection'
import type { RumFirstInputTiming, RumPerformanceEventTiming } from '../../../browser/performanceCollection'
import { LifeCycleEventType, type LifeCycle } from '../../lifeCycle'
import { LifeCycleEventType } from '../../lifeCycle'
import type { LifeCycle } from '../../lifeCycle'
import { ViewLoadingType } from '../../../rawRumEvent.types'
import { getSelectorFromElement } from '../../getSelectorFromElement'
import { isElementNode } from '../../../browser/htmlDomUtils'
import type { RumConfiguration } from '../../configuration'
import { getInteractionCount, initInteractionCountPolyfill } from './interactionCountPolyfill'

@@ -12,2 +16,6 @@

export interface InteractionToNextPaint {
value: Duration
targetSelector?: string
}
/**

@@ -19,3 +27,7 @@ * Track the interaction to next paint (INP).

*/
export function trackInteractionToNextPaint(viewLoadingType: ViewLoadingType, lifeCycle: LifeCycle) {
export function trackInteractionToNextPaint(
configuration: RumConfiguration,
viewLoadingType: ViewLoadingType,
lifeCycle: LifeCycle
) {
if (

@@ -33,7 +45,12 @@ !isInteractionToNextPaintSupported() ||

const longestInteractions = trackLongestInteractions(getViewInteractionCount)
let inpDuration = -1 as Duration
let interactionToNextPaint = -1 as Duration
let interactionToNextPaintTargetSelector: string | undefined
const { unsubscribe: stop } = lifeCycle.subscribe(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, (entries) => {
for (const entry of entries) {
if ((entry.entryType === 'event' || entry.entryType === 'first-input') && entry.interactionId) {
if (
(entry.entryType === RumPerformanceEntryType.EVENT ||
entry.entryType === RumPerformanceEntryType.FIRST_INPUT) &&
entry.interactionId
) {
longestInteractions.process(entry)

@@ -43,5 +60,17 @@ }

const newInpDuration = longestInteractions.estimateP98Duration()
if (newInpDuration) {
inpDuration = newInpDuration
const newInteraction = longestInteractions.estimateP98Interaction()
if (newInteraction) {
interactionToNextPaint = newInteraction.duration
if (
isExperimentalFeatureEnabled(ExperimentalFeature.WEB_VITALS_ATTRIBUTION) &&
newInteraction.target &&
isElementNode(newInteraction.target)
) {
interactionToNextPaintTargetSelector = getSelectorFromElement(
newInteraction.target,
configuration.actionNameAttribute
)
} else {
interactionToNextPaintTargetSelector = undefined
}
}

@@ -51,9 +80,14 @@ })

return {
getInteractionToNextPaint: () => {
getInteractionToNextPaint: (): InteractionToNextPaint | undefined => {
// If no INP duration where captured because of the performanceObserver 40ms threshold
// but the view interaction count > 0 then report 0
if (inpDuration >= 0) {
return inpDuration
if (interactionToNextPaint >= 0) {
return {
value: interactionToNextPaint,
targetSelector: interactionToNextPaintTargetSelector,
}
} else if (getViewInteractionCount()) {
return 0 as Duration
return {
value: 0 as Duration,
}
}

@@ -102,5 +136,5 @@ },

*/
estimateP98Duration(): Duration | undefined {
estimateP98Interaction(): RumPerformanceEventTiming | RumFirstInputTiming | undefined {
const interactionIndex = Math.min(longestInteractions.length - 1, Math.floor(getViewInteractionCount() / 50))
return longestInteractions[interactionIndex]?.duration
return longestInteractions[interactionIndex]
},

@@ -120,3 +154,3 @@ }

return (
supportPerformanceTimingEvent('event') &&
supportPerformanceTimingEvent(RumPerformanceEntryType.EVENT) &&
window.PerformanceEventTiming &&

@@ -123,0 +157,0 @@ 'interactionId' in PerformanceEventTiming.prototype

import type { RelativeTime } from '@datadog/browser-core'
import { DOM_EVENT, ONE_MINUTE, addEventListeners, findLast } from '@datadog/browser-core'
import { LifeCycleEventType, type LifeCycle } from '../../lifeCycle'
import {
DOM_EVENT,
ExperimentalFeature,
ONE_MINUTE,
addEventListeners,
findLast,
isExperimentalFeatureEnabled,
} from '@datadog/browser-core'
import { LifeCycleEventType } from '../../lifeCycle'
import type { LifeCycle } from '../../lifeCycle'
import type { RumConfiguration } from '../../configuration'
import { RumPerformanceEntryType } from '../../../browser/performanceCollection'
import type { RumLargestContentfulPaintTiming } from '../../../browser/performanceCollection'
import { getSelectorFromElement } from '../../getSelectorFromElement'
import type { FirstHidden } from './trackFirstHidden'

@@ -12,2 +22,6 @@

export interface LargestContentfulPaint {
value: RelativeTime
targetSelector?: string
}
/**

@@ -17,3 +31,3 @@ * Track the largest contentful paint (LCP) occurring during the initial View. This can yield

* Documentation: https://web.dev/lcp/
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/getLCP.ts
* Reference implementation: https://github.com/GoogleChrome/web-vitals/blob/master/src/onLCP.ts
*/

@@ -25,3 +39,3 @@ export function trackLargestContentfulPaint(

eventTarget: Window,
callback: (lcpTiming: RelativeTime, lcpElement?: Element) => void
callback: (largestContentfulPaint: LargestContentfulPaint) => void
) {

@@ -48,3 +62,3 @@ // Ignore entries that come after the first user interaction. According to the documentation, the

(entry): entry is RumLargestContentfulPaintTiming =>
entry.entryType === 'largest-contentful-paint' &&
entry.entryType === RumPerformanceEntryType.LARGEST_CONTENTFUL_PAINT &&
entry.startTime < firstInteractionTimestamp &&

@@ -54,4 +68,13 @@ entry.startTime < firstHidden.timeStamp &&

)
if (lcpEntry) {
callback(lcpEntry.startTime, lcpEntry.element)
let lcpTargetSelector
if (isExperimentalFeatureEnabled(ExperimentalFeature.WEB_VITALS_ATTRIBUTION) && lcpEntry.element) {
lcpTargetSelector = getSelectorFromElement(lcpEntry.element, configuration.actionNameAttribute)
}
callback({
value: lcpEntry.startTime,
targetSelector: lcpTargetSelector,
})
}

@@ -58,0 +81,0 @@ }

import type { Duration } from '@datadog/browser-core'
import { relativeNow } from '@datadog/browser-core'
import { RumPerformanceEntryType } from '../../../browser/performanceCollection'
import type { LifeCycle } from '../../lifeCycle'

@@ -17,3 +18,3 @@ import { LifeCycleEventType } from '../../lifeCycle'

for (const entry of entries) {
if (entry.entryType === 'navigation') {
if (entry.entryType === RumPerformanceEntryType.NAVIGATION) {
callback({

@@ -20,0 +21,0 @@ domComplete: entry.domComplete,

import type { ClocksState, Duration } from '@datadog/browser-core'
import { ONE_SECOND, elapsed, relativeNow, throttle, addEventListener, DOM_EVENT } from '@datadog/browser-core'
import {
Observable,
ONE_SECOND,
elapsed,
relativeNow,
throttle,
addEventListener,
DOM_EVENT,
monitor,
} from '@datadog/browser-core'
import type { RumConfiguration } from '../../configuration'

@@ -12,5 +21,5 @@ import { getScrollY } from '../../../browser/scroll'

maxDepth: number
maxDepthScrollHeight: number
maxScrollHeight: number
maxDepthScrollTop: number
maxDepthTime: Duration
maxScrollHeightTime: Duration
}

@@ -22,37 +31,44 @@

callback: (scrollMetrics: ScrollMetrics) => void,
getScrollValues = computeScrollValues
scrollValues = createScrollValuesObservable(configuration)
) {
let maxDepth = 0
const handleScrollEvent = throttle(
() => {
const { scrollHeight, scrollDepth, scrollTop } = getScrollValues()
let maxScrollDepth = 0
let maxScrollHeight = 0
let maxScrollHeightTime = 0 as Duration
if (scrollDepth > maxDepth) {
const now = relativeNow()
const maxDepthTime = elapsed(viewStart.relative, now)
maxDepth = scrollDepth
callback({
maxDepth,
maxDepthScrollHeight: scrollHeight,
maxDepthTime,
maxDepthScrollTop: scrollTop,
})
}
},
THROTTLE_SCROLL_DURATION,
{ leading: false, trailing: true }
)
const subscription = scrollValues.subscribe(({ scrollDepth, scrollTop, scrollHeight }) => {
let shouldUpdate = false
const { stop } = addEventListener(configuration, window, DOM_EVENT.SCROLL, handleScrollEvent.throttled, {
passive: true,
if (scrollDepth > maxScrollDepth) {
maxScrollDepth = scrollDepth
shouldUpdate = true
}
if (scrollHeight > maxScrollHeight) {
maxScrollHeight = scrollHeight
const now = relativeNow()
maxScrollHeightTime = elapsed(viewStart.relative, now)
shouldUpdate = true
}
if (shouldUpdate) {
callback({
maxDepth: Math.min(maxScrollDepth, maxScrollHeight),
maxDepthScrollTop: scrollTop,
maxScrollHeight,
maxScrollHeightTime,
})
}
})
return {
stop: () => {
handleScrollEvent.cancel()
stop()
},
stop: () => subscription.unsubscribe(),
}
}
export interface ScrollValues {
scrollDepth: number
scrollTop: number
scrollHeight: number
}
export function computeScrollValues() {

@@ -64,2 +80,3 @@ const scrollTop = getScrollY()

const scrollHeight = Math.round((document.scrollingElement || document.documentElement).scrollHeight)
const scrollDepth = Math.round(height + scrollTop)

@@ -73,1 +90,34 @@

}
export function createScrollValuesObservable(
configuration: RumConfiguration,
throttleDuration = THROTTLE_SCROLL_DURATION
): Observable<ScrollValues> {
const observable = new Observable<ScrollValues>(() => {
function notify() {
observable.notify(computeScrollValues())
}
if (window.ResizeObserver) {
const throttledNotify = throttle(notify, throttleDuration, {
leading: false,
trailing: true,
})
const observerTarget = document.scrollingElement || document.documentElement
const resizeObserver = new ResizeObserver(monitor(throttledNotify.throttled))
resizeObserver.observe(observerTarget)
const eventListener = addEventListener(configuration, window, DOM_EVENT.SCROLL, throttledNotify.throttled, {
passive: true,
})
return () => {
throttledNotify.cancel()
resizeObserver.unobserve(observerTarget)
eventListener.stop()
}
}
})
return observable
}

@@ -11,2 +11,3 @@ import type { Subscription, TimeoutId, TimeStamp } from '@datadog/browser-core'

} from '@datadog/browser-core'
import { RumPerformanceEntryType } from '../browser/performanceCollection'
import type { RumConfiguration } from './configuration'

@@ -131,3 +132,7 @@ import type { LifeCycle } from './lifeCycle'

lifeCycle.subscribe(LifeCycleEventType.PERFORMANCE_ENTRIES_COLLECTED, (entries) => {
if (entries.some((entry) => entry.entryType === 'resource' && !isExcludedUrl(configuration, entry.name))) {
if (
entries.some(
(entry) => entry.entryType === RumPerformanceEntryType.RESOURCE && !isExcludedUrl(configuration, entry.name)
)
) {
notifyPageActivity()

@@ -134,0 +139,0 @@ }

@@ -32,4 +32,4 @@ export { RumPublicApi, makeRumPublicApi, RecorderApi, StartRum } from './boot/rumPublicApi'

export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/action/getActionNameFromElement'
export { STABLE_ATTRIBUTES } from './domain/action/getSelectorFromElement'
export { STABLE_ATTRIBUTES } from './domain/getSelectorFromElement'
export * from './browser/htmlDomUtils'
export { getSessionReplayUrl } from './domain/getSessionReplayUrl'

@@ -86,4 +86,7 @@ import type {

first_input_time?: ServerDuration
first_input_target_selector?: string
interaction_to_next_paint?: ServerDuration
interaction_to_next_paint_target_selector?: string
cumulative_layout_shift?: number
cumulative_layout_shift_target_selector?: string
custom_timings?: {

@@ -93,2 +96,3 @@ [key: string]: ServerDuration

largest_contentful_paint?: ServerDuration
largest_contentful_paint_target_selector?: string
dom_interactive?: ServerDuration

@@ -128,5 +132,5 @@ dom_content_loaded?: ServerDuration

max_depth?: number
max_depth_scroll_height?: number
max_depth_scroll_top?: number
max_depth_time?: ServerDuration
max_scroll_height?: number
max_scroll_height_time?: ServerDuration
}

@@ -133,0 +137,0 @@ }

@@ -504,2 +504,24 @@ /* eslint-disable */

}
/**
* GraphQL requests parameters
*/
readonly graphql?: {
/**
* Type of the GraphQL operation
*/
readonly operationType: 'query' | 'mutation' | 'subscription'
/**
* Name of the GraphQL operation
*/
readonly operationName?: string
/**
* Content of the GraphQL operation
*/
payload?: string
/**
* String representation of the operation variables
*/
variables?: string
[k: string]: unknown
}
[k: string]: unknown

@@ -572,2 +594,6 @@ }

/**
* CSS selector path of the largest contentful paint element
*/
readonly largest_contentful_paint_target_selector?: string
/**
* Duration in ns of the first input event delay

@@ -581,2 +607,6 @@ */

/**
* CSS selector path of the first input target element
*/
readonly first_input_target_selector?: string
/**
* Longest duration in ns between an interaction and the next paint

@@ -586,2 +616,6 @@ */

/**
* CSS selector path of the interacted element corresponding to INP
*/
readonly interaction_to_next_paint_target_selector?: string
/**
* Total layout shift score that occurred on the view

@@ -591,2 +625,6 @@ */

/**
* CSS selector path of the first element (in document order) of the largest layout shift contributing to CLS
*/
readonly cumulative_layout_shift_target_selector?: string
/**
* Duration in ns to the complete parsing and loading of the document and its sub resources

@@ -841,6 +879,2 @@ */

/**
* Page scroll height (total height) when the maximum scroll depth was reached for this view (in pixels)
*/
readonly max_depth_scroll_height: number
/**
* Page scroll top (scrolled distance) when the maximum scroll depth was reached for this view (in pixels)

@@ -850,5 +884,9 @@ */

/**
* Duration between the view start and the scroll event that reached the maximum scroll depth for this view (in nanoseconds)
* Maximum page scroll height (total height) for this view (in pixels)
*/
readonly max_depth_time: number
readonly max_scroll_height: number
/**
* Duration between the view start and the time the max scroll height was reached for this view (in nanoseconds)
*/
readonly max_scroll_height_time: number
[k: string]: unknown

@@ -888,2 +926,6 @@ }

/**
* The build version for this application
*/
readonly build_version?: string
/**
* Session properties

@@ -890,0 +932,0 @@ */

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc