@datadog/browser-rum-core
Advanced tools
Comparing version 4.43.0 to 4.44.0
@@ -23,3 +23,2 @@ import type { Observable, RawError, ContextManager } from '@datadog/browser-core'; | ||
viewContexts: import("../domain/contexts/viewContexts").ViewContexts; | ||
foregroundContexts: import("../domain/contexts/foregroundContexts").ForegroundContexts; | ||
pageStateHistory: import("../domain/contexts/pageStateHistory").PageStateHistory; | ||
@@ -26,0 +25,0 @@ urlContexts: { |
@@ -8,3 +8,2 @@ "use strict"; | ||
var assembly_1 = require("../domain/assembly"); | ||
var foregroundContexts_1 = require("../domain/contexts/foregroundContexts"); | ||
var internalContext_1 = require("../domain/contexts/internalContext"); | ||
@@ -68,8 +67,8 @@ var lifeCycle_1 = require("../domain/lifeCycle"); | ||
var locationChangeObservable = (0, locationChangeObservable_1.createLocationChangeObservable)(location); | ||
var _a = startRumEventCollection(lifeCycle, configuration, location, session, locationChangeObservable, domMutationObservable, function () { return (0, commonContext_1.buildCommonContext)(globalContextManager, userContextManager, recorderApi); }, reportError), viewContexts = _a.viewContexts, foregroundContexts = _a.foregroundContexts, pageStateHistory = _a.pageStateHistory, urlContexts = _a.urlContexts, actionContexts = _a.actionContexts, addAction = _a.addAction; | ||
var _a = startRumEventCollection(lifeCycle, configuration, location, session, locationChangeObservable, domMutationObservable, function () { return (0, commonContext_1.buildCommonContext)(globalContextManager, userContextManager, recorderApi); }, reportError), viewContexts = _a.viewContexts, pageStateHistory = _a.pageStateHistory, urlContexts = _a.urlContexts, actionContexts = _a.actionContexts, addAction = _a.addAction; | ||
(0, browser_core_1.addTelemetryConfiguration)((0, configuration_1.serializeRumConfiguration)(initConfiguration)); | ||
(0, longTaskCollection_1.startLongTaskCollection)(lifeCycle, session); | ||
(0, resourceCollection_1.startResourceCollection)(lifeCycle, configuration, session, pageStateHistory); | ||
var _b = (0, viewCollection_1.startViewCollection)(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, foregroundContexts, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView; | ||
var addError = (0, errorCollection_1.startErrorCollection)(lifeCycle, foregroundContexts, featureFlagContexts).addError; | ||
var _b = (0, viewCollection_1.startViewCollection)(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView; | ||
var addError = (0, errorCollection_1.startErrorCollection)(lifeCycle, pageStateHistory, featureFlagContexts).addError; | ||
(0, requestCollection_1.startRequestCollection)(lifeCycle, configuration, session); | ||
@@ -103,9 +102,7 @@ (0, performanceCollection_1.startPerformanceCollection)(lifeCycle, configuration); | ||
var urlContexts = (0, urlContexts_1.startUrlContexts)(lifeCycle, locationChangeObservable, location); | ||
var foregroundContexts = (0, foregroundContexts_1.startForegroundContexts)(); | ||
var pageStateHistory = (0, pageStateHistory_1.startPageStateHistory)(); | ||
var _a = (0, actionCollection_1.startActionCollection)(lifeCycle, domMutationObservable, configuration, foregroundContexts), addAction = _a.addAction, actionContexts = _a.actionContexts; | ||
var _a = (0, actionCollection_1.startActionCollection)(lifeCycle, domMutationObservable, configuration, pageStateHistory), addAction = _a.addAction, actionContexts = _a.actionContexts; | ||
(0, assembly_1.startRumAssembly)(configuration, lifeCycle, sessionManager, viewContexts, urlContexts, actionContexts, buildCommonContext, reportError); | ||
return { | ||
viewContexts: viewContexts, | ||
foregroundContexts: foregroundContexts, | ||
pageStateHistory: pageStateHistory, | ||
@@ -117,3 +114,3 @@ urlContexts: urlContexts, | ||
viewContexts.stop(); | ||
foregroundContexts.stop(); | ||
pageStateHistory.stop(); | ||
}, | ||
@@ -120,0 +117,0 @@ }; |
@@ -56,3 +56,3 @@ "use strict"; | ||
}, | ||
browser_sdk_version: (0, browser_core_1.canUseEventBridge)() ? "4.43.0" : undefined, | ||
browser_sdk_version: (0, browser_core_1.canUseEventBridge)() ? "4.44.0" : undefined, | ||
}, | ||
@@ -59,0 +59,0 @@ application: { |
import type { RelativeTime, Duration } from '@datadog/browser-core'; | ||
import type { InForegroundPeriod } from '../../rawRumEvent.types'; | ||
export declare const MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS = 500; | ||
export declare const MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS = 2500; | ||
export interface ForegroundContexts { | ||
isInForegroundAt: (startTime: RelativeTime) => boolean | undefined; | ||
selectInForegroundPeriodsFor: (startTime: RelativeTime, duration: Duration) => InForegroundPeriod[] | undefined; | ||
stop: () => void; | ||
} | ||
import type { InForegroundPeriod, PageStateServerEntry } from '../../rawRumEvent.types'; | ||
export interface ForegroundPeriod { | ||
@@ -14,4 +7,2 @@ start: RelativeTime; | ||
} | ||
export declare function startForegroundContexts(): ForegroundContexts; | ||
export declare function addNewForegroundPeriod(): void; | ||
export declare function closeForegroundPeriod(): void; | ||
export declare function mapToForegroundPeriods(pageStateServerEntries: PageStateServerEntry[], duration: Duration): InForegroundPeriod[]; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.closeForegroundPeriod = exports.addNewForegroundPeriod = exports.startForegroundContexts = exports.MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS = exports.MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS = void 0; | ||
exports.mapToForegroundPeriods = void 0; | ||
var browser_core_1 = require("@datadog/browser-core"); | ||
// Arbitrary value to cap number of element mostly for backend & to save bandwidth | ||
exports.MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS = 500; | ||
// Arbitrary value to cap number of element mostly for memory consumption in the browser | ||
exports.MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS = 2500; | ||
var foregroundPeriods = []; | ||
function startForegroundContexts() { | ||
if (document.hasFocus()) { | ||
addNewForegroundPeriod(); | ||
} | ||
var stopForegroundTracking = trackFocus(addNewForegroundPeriod).stop; | ||
var stopBlurTracking = trackBlur(closeForegroundPeriod).stop; | ||
return { | ||
isInForegroundAt: isInForegroundAt, | ||
selectInForegroundPeriodsFor: selectInForegroundPeriodsFor, | ||
stop: function () { | ||
foregroundPeriods = []; | ||
stopForegroundTracking(); | ||
stopBlurTracking(); | ||
}, | ||
}; | ||
} | ||
exports.startForegroundContexts = startForegroundContexts; | ||
function addNewForegroundPeriod() { | ||
if (foregroundPeriods.length > exports.MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS) { | ||
return; | ||
} | ||
var currentForegroundPeriod = foregroundPeriods[foregroundPeriods.length - 1]; | ||
var now = (0, browser_core_1.relativeNow)(); | ||
if (currentForegroundPeriod !== undefined && currentForegroundPeriod.end === undefined) { | ||
return; | ||
} | ||
foregroundPeriods.push({ | ||
start: now, | ||
}); | ||
} | ||
exports.addNewForegroundPeriod = addNewForegroundPeriod; | ||
function closeForegroundPeriod() { | ||
if (foregroundPeriods.length === 0) { | ||
return; | ||
} | ||
var currentForegroundPeriod = foregroundPeriods[foregroundPeriods.length - 1]; | ||
var now = (0, browser_core_1.relativeNow)(); | ||
if (currentForegroundPeriod.end !== undefined) { | ||
return; | ||
} | ||
currentForegroundPeriod.end = now; | ||
} | ||
exports.closeForegroundPeriod = closeForegroundPeriod; | ||
function trackFocus(onFocusChange) { | ||
return (0, browser_core_1.addEventListener)(window, "focus" /* DOM_EVENT.FOCUS */, function (event) { | ||
if (!event.isTrusted) { | ||
return; | ||
// Todo: Remove in the next major release | ||
function mapToForegroundPeriods(pageStateServerEntries, duration) { | ||
var foregroundPeriods = []; | ||
for (var i = 0; i < pageStateServerEntries.length; i++) { | ||
var current = pageStateServerEntries[i]; | ||
var next = pageStateServerEntries[i + 1]; | ||
if (current.state === "active" /* PageState.ACTIVE */) { | ||
var start = current.start >= 0 ? current.start : 0; | ||
var end = next ? next.start : (0, browser_core_1.toServerDuration)(duration); | ||
foregroundPeriods.push({ | ||
start: start, | ||
duration: (end - start), | ||
}); | ||
} | ||
onFocusChange(); | ||
}); | ||
} | ||
function trackBlur(onBlurChange) { | ||
return (0, browser_core_1.addEventListener)(window, "blur" /* DOM_EVENT.BLUR */, function (event) { | ||
if (!event.isTrusted) { | ||
return; | ||
} | ||
onBlurChange(); | ||
}); | ||
} | ||
function isInForegroundAt(startTime) { | ||
for (var i = foregroundPeriods.length - 1; i >= 0; i--) { | ||
var foregroundPeriod = foregroundPeriods[i]; | ||
if (foregroundPeriod.end !== undefined && startTime > foregroundPeriod.end) { | ||
break; | ||
} | ||
if (startTime > foregroundPeriod.start && | ||
(foregroundPeriod.end === undefined || startTime < foregroundPeriod.end)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
return foregroundPeriods; | ||
} | ||
function selectInForegroundPeriodsFor(eventStartTime, duration) { | ||
var eventEndTime = (0, browser_core_1.addDuration)(eventStartTime, duration); | ||
var filteredForegroundPeriods = []; | ||
var earliestIndex = Math.max(0, foregroundPeriods.length - exports.MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS); | ||
for (var i = foregroundPeriods.length - 1; i >= earliestIndex; i--) { | ||
var foregroundPeriod = foregroundPeriods[i]; | ||
if (foregroundPeriod.end !== undefined && eventStartTime > foregroundPeriod.end) { | ||
// event starts after the end of the current focus period | ||
// since the array is sorted, we can stop looking for foreground periods | ||
break; | ||
} | ||
if (eventEndTime < foregroundPeriod.start) { | ||
// event ends before the start of the current focus period | ||
// continue to previous one | ||
continue; | ||
} | ||
var startTime = eventStartTime > foregroundPeriod.start ? eventStartTime : foregroundPeriod.start; | ||
var startDuration = (0, browser_core_1.elapsed)(eventStartTime, startTime); | ||
var endTime = foregroundPeriod.end === undefined || eventEndTime < foregroundPeriod.end ? eventEndTime : foregroundPeriod.end; | ||
var endDuration = (0, browser_core_1.elapsed)(startTime, endTime); | ||
filteredForegroundPeriods.unshift({ | ||
start: (0, browser_core_1.toServerDuration)(startDuration), | ||
duration: (0, browser_core_1.toServerDuration)(endDuration), | ||
}); | ||
} | ||
return filteredForegroundPeriods; | ||
} | ||
exports.mapToForegroundPeriods = mapToForegroundPeriods; | ||
//# sourceMappingURL=foregroundContexts.js.map |
@@ -19,2 +19,3 @@ import type { Duration, RelativeTime } from '@datadog/browser-core'; | ||
findAll: (startTime: RelativeTime, duration: Duration) => PageStateServerEntry[] | undefined; | ||
isInActivePageStateAt: (startTime: RelativeTime) => boolean; | ||
addPageState(nextPageState: PageState, startTime?: RelativeTime): void; | ||
@@ -21,0 +22,0 @@ stop: () => void; |
@@ -60,2 +60,6 @@ "use strict"; | ||
}, | ||
isInActivePageStateAt: function (startTime) { | ||
var pageStateEntry = pageStateHistory.find(startTime); | ||
return pageStateEntry !== undefined && pageStateEntry.state === "active" /* PageState.ACTIVE */; | ||
}, | ||
addPageState: addPageState, | ||
@@ -62,0 +66,0 @@ stop: function () { |
import type { ClocksState, Context, Observable } from '@datadog/browser-core'; | ||
import { ActionType } from '../../../rawRumEvent.types'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts'; | ||
import type { RumConfiguration } from '../../configuration'; | ||
import type { CommonContext } from '../../contexts/commonContext'; | ||
import type { PageStateHistory } from '../../contexts/pageStateHistory'; | ||
import type { ActionContexts, ClickAction } from './trackClickActions'; | ||
@@ -16,5 +16,5 @@ export type { ActionContexts }; | ||
export type AutoAction = ClickAction; | ||
export declare function startActionCollection(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, foregroundContexts: ForegroundContexts): { | ||
export declare function startActionCollection(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, pageStateHistory: PageStateHistory): { | ||
addAction: (action: CustomAction, savedCommonContext?: CommonContext) => void; | ||
actionContexts: ActionContexts; | ||
}; |
@@ -6,5 +6,5 @@ "use strict"; | ||
var trackClickActions_1 = require("./trackClickActions"); | ||
function startActionCollection(lifeCycle, domMutationObservable, configuration, foregroundContexts) { | ||
function startActionCollection(lifeCycle, domMutationObservable, configuration, pageStateHistory) { | ||
lifeCycle.subscribe(1 /* LifeCycleEventType.AUTO_ACTION_COMPLETED */, function (action) { | ||
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processAction(action, foregroundContexts)); | ||
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processAction(action, pageStateHistory)); | ||
}); | ||
@@ -19,3 +19,3 @@ var actionContexts = { findActionId: browser_core_1.noop }; | ||
savedCommonContext: savedCommonContext, | ||
}, processAction(action, foregroundContexts))); | ||
}, processAction(action, pageStateHistory))); | ||
}, | ||
@@ -26,3 +26,3 @@ actionContexts: actionContexts, | ||
exports.startActionCollection = startActionCollection; | ||
function processAction(action, foregroundContexts) { | ||
function processAction(action, pageStateHistory) { | ||
var autoActionProperties = isAutoAction(action) | ||
@@ -65,7 +65,4 @@ ? { | ||
type: "action" /* RumEventType.ACTION */, | ||
view: { in_foreground: pageStateHistory.isInActivePageStateAt(action.startClocks.relative) }, | ||
}, autoActionProperties); | ||
var inForeground = foregroundContexts.isInForegroundAt(action.startClocks.relative); | ||
if (inForeground !== undefined) { | ||
actionEvent.view = { in_foreground: inForeground }; | ||
} | ||
return { | ||
@@ -72,0 +69,0 @@ customerContext: customerContext, |
import type { Context, ClocksState } from '@datadog/browser-core'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts'; | ||
import type { FeatureFlagContexts } from '../../contexts/featureFlagContext'; | ||
import type { CommonContext } from '../../contexts/commonContext'; | ||
import type { PageStateHistory } from '../../contexts/pageStateHistory'; | ||
export interface ProvidedError { | ||
@@ -12,7 +12,7 @@ startClocks: ClocksState; | ||
} | ||
export declare function startErrorCollection(lifeCycle: LifeCycle, foregroundContexts: ForegroundContexts, featureFlagContexts: FeatureFlagContexts): { | ||
export declare function startErrorCollection(lifeCycle: LifeCycle, pageStateHistory: PageStateHistory, featureFlagContexts: FeatureFlagContexts): { | ||
addError: ({ error, handlingStack, startClocks, context: customerContext }: ProvidedError, savedCommonContext?: CommonContext | undefined) => void; | ||
}; | ||
export declare function doStartErrorCollection(lifeCycle: LifeCycle, foregroundContexts: ForegroundContexts, featureFlagContexts: FeatureFlagContexts): { | ||
export declare function doStartErrorCollection(lifeCycle: LifeCycle, pageStateHistory: PageStateHistory, featureFlagContexts: FeatureFlagContexts): { | ||
addError: ({ error, handlingStack, startClocks, context: customerContext }: ProvidedError, savedCommonContext?: CommonContext) => void; | ||
}; |
@@ -7,3 +7,3 @@ "use strict"; | ||
var trackReportError_1 = require("./trackReportError"); | ||
function startErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts) { | ||
function startErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) { | ||
var errorObservable = new browser_core_1.Observable(); | ||
@@ -14,6 +14,6 @@ (0, trackConsoleError_1.trackConsoleError)(errorObservable); | ||
errorObservable.subscribe(function (error) { return lifeCycle.notify(12 /* LifeCycleEventType.RAW_ERROR_COLLECTED */, { error: error }); }); | ||
return doStartErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts); | ||
return doStartErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts); | ||
} | ||
exports.startErrorCollection = startErrorCollection; | ||
function doStartErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts) { | ||
function doStartErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) { | ||
lifeCycle.subscribe(12 /* LifeCycleEventType.RAW_ERROR_COLLECTED */, function (_a) { | ||
@@ -24,3 +24,3 @@ var error = _a.error, customerContext = _a.customerContext, savedCommonContext = _a.savedCommonContext; | ||
savedCommonContext: savedCommonContext, | ||
}, processError(error, foregroundContexts, featureFlagContexts))); | ||
}, processError(error, pageStateHistory, featureFlagContexts))); | ||
}); | ||
@@ -49,3 +49,3 @@ return { | ||
exports.doStartErrorCollection = doStartErrorCollection; | ||
function processError(error, foregroundContexts, featureFlagContexts) { | ||
function processError(error, pageStateHistory, featureFlagContexts) { | ||
var rawRumEvent = { | ||
@@ -66,7 +66,4 @@ date: error.startClocks.timeStamp, | ||
type: "error" /* RumEventType.ERROR */, | ||
view: { in_foreground: pageStateHistory.isInActivePageStateAt(error.startClocks.relative) }, | ||
}; | ||
var inForeground = foregroundContexts.isInForegroundAt(error.startClocks.relative); | ||
if (inForeground) { | ||
rawRumEvent.view = { in_foreground: inForeground }; | ||
} | ||
var featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(error.startClocks.relative); | ||
@@ -73,0 +70,0 @@ if (featureFlagContext && !(0, browser_core_1.isEmptyObject)(featureFlagContext)) { |
@@ -1,5 +0,14 @@ | ||
import type { Duration, Observable, ClocksState } from '@datadog/browser-core'; | ||
import type { ClocksState, Duration, Observable } from '@datadog/browser-core'; | ||
import { noop } from '@datadog/browser-core'; | ||
import { ViewLoadingType } from '../../../rawRumEvent.types'; | ||
import type { RumConfiguration } from '../../configuration'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
export interface ScrollMetrics { | ||
maxDepth: number; | ||
maxDepthScrollHeight: number; | ||
maxDepthScrollTop: number; | ||
maxDepthTime: Duration; | ||
} | ||
/** Arbitrary scroll throttle duration */ | ||
export declare const THROTTLE_SCROLL_DURATION = 1000; | ||
export interface ViewMetrics { | ||
@@ -13,2 +22,12 @@ loadingTime?: Duration; | ||
viewMetrics: ViewMetrics; | ||
getScrollMetrics: () => ScrollMetrics | undefined; | ||
}; | ||
export declare function trackScrollMetrics(viewStart: ClocksState, callback: (scrollMetrics: ScrollMetrics) => void, getScrollValues?: typeof computeScrollValues): { | ||
stop: typeof noop; | ||
}; | ||
declare function computeScrollValues(): { | ||
scrollHeight: number; | ||
scrollDepth: number; | ||
scrollTop: number; | ||
}; | ||
export {}; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.trackViewMetrics = void 0; | ||
exports.trackScrollMetrics = exports.trackViewMetrics = exports.THROTTLE_SCROLL_DURATION = void 0; | ||
var browser_core_1 = require("@datadog/browser-core"); | ||
var performanceCollection_1 = require("../../../browser/performanceCollection"); | ||
var waitPageActivityEnd_1 = require("../../waitPageActivityEnd"); | ||
var scroll_1 = require("../../../browser/scroll"); | ||
var viewportObservable_1 = require("../../../browser/viewportObservable"); | ||
/** Arbitrary scroll throttle duration */ | ||
exports.THROTTLE_SCROLL_DURATION = browser_core_1.ONE_SECOND; | ||
function trackViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, viewStart) { | ||
var viewMetrics = {}; | ||
var scrollMetrics; | ||
var _a = trackLoadingTime(lifeCycle, domMutationObservable, configuration, loadingType, viewStart, function (newLoadingTime) { | ||
viewMetrics.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. | ||
if ((0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.SCROLLMAP)) { | ||
var _a = computeScrollValues(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop; | ||
scrollMetrics = { | ||
maxDepth: scrollDepth, | ||
maxDepthScrollHeight: scrollHeight, | ||
maxDepthTime: newLoadingTime, | ||
maxDepthScrollTop: scrollTop, | ||
}; | ||
} | ||
scheduleViewUpdate(); | ||
}), stopLoadingTimeTracking = _a.stop, setLoadEvent = _a.setLoadEvent; | ||
var stopScrollMetricsTracking = trackScrollMetrics(viewStart, function (newScrollMetrics) { | ||
scrollMetrics = newScrollMetrics; | ||
}, computeScrollValues).stop; | ||
var stopCLSTracking; | ||
@@ -28,8 +47,50 @@ if (isLayoutShiftSupported()) { | ||
stopCLSTracking(); | ||
stopScrollMetricsTracking(); | ||
}, | ||
setLoadEvent: setLoadEvent, | ||
viewMetrics: viewMetrics, | ||
getScrollMetrics: function () { return scrollMetrics; }, | ||
}; | ||
} | ||
exports.trackViewMetrics = trackViewMetrics; | ||
function trackScrollMetrics(viewStart, callback, getScrollValues) { | ||
if (getScrollValues === void 0) { getScrollValues = computeScrollValues; } | ||
if (!(0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.SCROLLMAP)) { | ||
return { stop: browser_core_1.noop }; | ||
} | ||
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) { | ||
var now = (0, browser_core_1.relativeNow)(); | ||
var maxDepthTime = (0, browser_core_1.elapsed)(viewStart.relative, now); | ||
maxDepth = scrollDepth; | ||
callback({ | ||
maxDepth: maxDepth, | ||
maxDepthScrollHeight: scrollHeight, | ||
maxDepthTime: maxDepthTime, | ||
maxDepthScrollTop: scrollTop, | ||
}); | ||
} | ||
}, exports.THROTTLE_SCROLL_DURATION, { leading: false, trailing: true }); | ||
var stop = (0, browser_core_1.addEventListener)(window, "scroll" /* DOM_EVENT.SCROLL */, handleScrollEvent.throttled, { passive: true }).stop; | ||
return { | ||
stop: function () { | ||
handleScrollEvent.cancel(); | ||
stop(); | ||
}, | ||
}; | ||
} | ||
exports.trackScrollMetrics = trackScrollMetrics; | ||
function computeScrollValues() { | ||
var scrollTop = (0, scroll_1.getScrollY)(); | ||
var height = (0, viewportObservable_1.getViewportDimension)().height; | ||
var scrollHeight = Math.round((document.scrollingElement || document.documentElement).scrollHeight); | ||
var scrollDepth = Math.round(height + scrollTop); | ||
return { | ||
scrollHeight: scrollHeight, | ||
scrollDepth: scrollDepth, | ||
scrollTop: scrollTop, | ||
}; | ||
} | ||
function trackLoadingTime(lifeCycle, domMutationObservable, configuration, loadType, viewStart, callback) { | ||
@@ -36,0 +97,0 @@ var isWaitingForLoadEvent = loadType === "initial_load" /* ViewLoadingType.INITIAL_LOAD */; |
@@ -9,2 +9,3 @@ import type { Duration, ClocksState, TimeStamp, Observable, RelativeTime } from '@datadog/browser-core'; | ||
import type { Timings } from './trackInitialViewTimings'; | ||
import type { ScrollMetrics } from './trackViewMetrics'; | ||
export interface ViewEvent { | ||
@@ -27,2 +28,3 @@ id: string; | ||
cumulativeLayoutShift?: number; | ||
scrollMetrics?: ScrollMetrics; | ||
} | ||
@@ -29,0 +31,0 @@ export interface ViewCreatedEvent { |
@@ -92,3 +92,3 @@ "use strict"; | ||
}), scheduleViewUpdate = _a.throttled, cancelScheduleViewUpdate = _a.cancel; | ||
var _b = (0, trackViewMetrics_1.trackViewMetrics)(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks), setLoadEvent = _b.setLoadEvent, stopViewMetricsTracking = _b.stop, viewMetrics = _b.viewMetrics; | ||
var _b = (0, trackViewMetrics_1.trackViewMetrics)(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks), setLoadEvent = _b.setLoadEvent, stopViewMetricsTracking = _b.stop, viewMetrics = _b.viewMetrics, getScrollMetrics = _b.getScrollMetrics; | ||
var _c = loadingType === "initial_load" /* ViewLoadingType.INITIAL_LOAD */ | ||
@@ -121,2 +121,3 @@ ? (0, trackInitialViewTimings_1.trackInitialViewTimings)(lifeCycle, setLoadEvent, scheduleViewUpdate) | ||
eventCounts: eventCounts, | ||
scrollMetrics: getScrollMetrics(), | ||
}, viewMetrics)); | ||
@@ -123,0 +124,0 @@ } |
import type { Observable } from '@datadog/browser-core'; | ||
import type { RecorderApi } from '../../../boot/rumPublicApi'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts'; | ||
import type { LocationChange } from '../../../browser/locationChangeObservable'; | ||
@@ -10,3 +9,3 @@ import type { RumConfiguration } from '../../configuration'; | ||
import type { ViewOptions } from './trackViews'; | ||
export declare function startViewCollection(lifeCycle: LifeCycle, configuration: RumConfiguration, location: Location, domMutationObservable: Observable<void>, locationChangeObservable: Observable<LocationChange>, foregroundContexts: ForegroundContexts, featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, 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; |
@@ -5,6 +5,7 @@ "use strict"; | ||
var browser_core_1 = require("@datadog/browser-core"); | ||
var foregroundContexts_1 = require("../../contexts/foregroundContexts"); | ||
var trackViews_1 = require("./trackViews"); | ||
function startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, foregroundContexts, featureFlagContexts, pageStateHistory, recorderApi, 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, foregroundContexts, featureFlagContexts, recorderApi, pageStateHistory)); | ||
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory)); | ||
}); | ||
@@ -15,6 +16,7 @@ var trackViewResult = (0, trackViews_1.trackViews)(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, !configuration.trackViewsManually, initialViewOptions); | ||
exports.startViewCollection = startViewCollection; | ||
function processViewUpdate(view, foregroundContexts, featureFlagContexts, recorderApi, pageStateHistory) { | ||
function processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory) { | ||
var replayStats = recorderApi.getReplayStats(view.id); | ||
var featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(view.startClocks.relative); | ||
var pageStatesEnabled = (0, browser_core_1.isExperimentalFeatureEnabled)(browser_core_1.ExperimentalFeature.PAGE_STATES); | ||
var pageStates = pageStateHistory.findAll(view.startClocks.relative, view.duration); | ||
var viewEvent = { | ||
@@ -24,3 +26,3 @@ _dd: { | ||
replay_stats: replayStats, | ||
page_states: pageStatesEnabled ? pageStateHistory.findAll(view.startClocks.relative, view.duration) : undefined, | ||
page_states: pageStatesEnabled ? pageStates : undefined, | ||
}, | ||
@@ -60,7 +62,15 @@ date: view.startClocks.timeStamp, | ||
time_spent: (0, browser_core_1.toServerDuration)(view.duration), | ||
in_foreground_periods: !pageStatesEnabled | ||
? foregroundContexts.selectInForegroundPeriodsFor(view.startClocks.relative, view.duration) | ||
: undefined, | ||
in_foreground_periods: !pageStatesEnabled && pageStates ? (0, foregroundContexts_1.mapToForegroundPeriods)(pageStates, view.duration) : undefined, // Todo: Remove in the next major release | ||
}, | ||
feature_flags: featureFlagContext && !(0, browser_core_1.isEmptyObject)(featureFlagContext) ? featureFlagContext : undefined, | ||
display: view.scrollMetrics | ||
? { | ||
scroll: { | ||
max_depth: view.scrollMetrics.maxDepth, | ||
max_depth_scroll_height: view.scrollMetrics.maxDepthScrollHeight, | ||
max_depth_scroll_top: view.scrollMetrics.maxDepthScrollTop, | ||
max_depth_time: (0, browser_core_1.toServerDuration)(view.scrollMetrics.maxDepthTime), | ||
}, | ||
} | ||
: undefined, | ||
session: { | ||
@@ -70,2 +80,5 @@ has_replay: replayStats ? true : undefined, | ||
}, | ||
privacy: { | ||
replay_level: configuration.defaultPrivacyLevel, | ||
}, | ||
}; | ||
@@ -72,0 +85,0 @@ if (!(0, browser_core_1.isEmptyObject)(view.customTimings)) { |
@@ -12,2 +12,3 @@ export { RumPublicApi, makeRumPublicApi, RecorderApi, StartRum } from './boot/rumPublicApi'; | ||
export { initViewportObservable, getViewportDimension } from './browser/viewportObservable'; | ||
export { getScrollX, getScrollY } from './browser/scroll'; | ||
export { RumInitConfiguration, RumConfiguration } from './domain/configuration'; | ||
@@ -14,0 +15,0 @@ export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/rumEventsCollection/action/getActionNameFromElement'; |
@@ -17,3 +17,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getSessionReplayUrl = exports.STABLE_ATTRIBUTES = exports.DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE = exports.getViewportDimension = exports.initViewportObservable = exports.getMutationObserverConstructor = exports.LifeCycle = exports.startRum = exports.makeRumPublicApi = void 0; | ||
exports.getSessionReplayUrl = exports.STABLE_ATTRIBUTES = exports.DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE = exports.getScrollY = exports.getScrollX = exports.getViewportDimension = exports.initViewportObservable = exports.getMutationObserverConstructor = exports.LifeCycle = exports.startRum = exports.makeRumPublicApi = void 0; | ||
var rumPublicApi_1 = require("./boot/rumPublicApi"); | ||
@@ -30,2 +30,5 @@ Object.defineProperty(exports, "makeRumPublicApi", { enumerable: true, get: function () { return rumPublicApi_1.makeRumPublicApi; } }); | ||
Object.defineProperty(exports, "getViewportDimension", { enumerable: true, get: function () { return viewportObservable_1.getViewportDimension; } }); | ||
var scroll_1 = require("./browser/scroll"); | ||
Object.defineProperty(exports, "getScrollX", { enumerable: true, get: function () { return scroll_1.getScrollX; } }); | ||
Object.defineProperty(exports, "getScrollY", { enumerable: true, get: function () { return scroll_1.getScrollY; } }); | ||
var getActionNameFromElement_1 = require("./domain/rumEventsCollection/action/getActionNameFromElement"); | ||
@@ -32,0 +35,0 @@ Object.defineProperty(exports, "DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE", { enumerable: true, get: function () { return getActionNameFromElement_1.DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE; } }); |
@@ -1,2 +0,2 @@ | ||
import type { Context, Duration, ErrorSource, ErrorHandling, ResourceType, ServerDuration, TimeStamp, RawErrorCause } from '@datadog/browser-core'; | ||
import type { Context, Duration, ErrorSource, ErrorHandling, ResourceType, ServerDuration, TimeStamp, RawErrorCause, DefaultPrivacyLevel } from '@datadog/browser-core'; | ||
import type { PageState } from './domain/contexts/pageStateHistory'; | ||
@@ -95,2 +95,6 @@ import type { RumSessionPlan } from './domain/rumSessionManager'; | ||
feature_flags?: Context; | ||
display?: ViewDisplay; | ||
privacy?: { | ||
replay_level: DefaultPrivacyLevel; | ||
}; | ||
_dd: { | ||
@@ -102,2 +106,10 @@ document_version: number; | ||
} | ||
interface ViewDisplay { | ||
scroll: { | ||
max_depth?: number; | ||
max_depth_scroll_height?: number; | ||
max_depth_scroll_top?: number; | ||
max_depth_time?: ServerDuration; | ||
}; | ||
} | ||
export interface InForegroundPeriod { | ||
@@ -104,0 +116,0 @@ start: ServerDuration; |
@@ -711,2 +711,12 @@ /** | ||
/** | ||
* Privacy properties | ||
*/ | ||
readonly privacy?: { | ||
/** | ||
* The replay privacy level | ||
*/ | ||
readonly replay_level: 'allow' | 'mask' | 'mask-user-input'; | ||
[k: string]: unknown; | ||
}; | ||
/** | ||
* Internal properties | ||
@@ -733,4 +743,50 @@ */ | ||
}[]; | ||
/** | ||
* Debug metadata for Replay Sessions | ||
*/ | ||
replay_stats?: { | ||
/** | ||
* The number of records produced during this view lifetime | ||
*/ | ||
records_count?: number; | ||
/** | ||
* The number of segments sent during this view lifetime | ||
*/ | ||
segments_count?: number; | ||
/** | ||
* The total size in bytes of the segments sent during this view lifetime | ||
*/ | ||
segments_total_raw_size?: number; | ||
[k: string]: unknown; | ||
}; | ||
[k: string]: unknown; | ||
}; | ||
/** | ||
* Display properties | ||
*/ | ||
readonly display?: { | ||
/** | ||
* Scroll properties | ||
*/ | ||
readonly scroll?: { | ||
/** | ||
* Distance between the top and the lowest point reached on this view (in pixels) | ||
*/ | ||
readonly max_depth: number; | ||
/** | ||
* 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) | ||
*/ | ||
readonly max_depth_scroll_top: number; | ||
/** | ||
* Duration between the view start and the scroll event that reached the maximum scroll depth for this view (in nanoseconds) | ||
*/ | ||
readonly max_depth_time: number; | ||
[k: string]: unknown; | ||
}; | ||
[k: string]: unknown; | ||
}; | ||
[k: string]: unknown; | ||
@@ -915,2 +971,6 @@ }; | ||
/** | ||
* Operating system build number, e.g. 15D21 | ||
*/ | ||
readonly build?: string; | ||
/** | ||
* Major operating system version, e.g. 8 | ||
@@ -917,0 +977,0 @@ */ |
@@ -23,3 +23,2 @@ import type { Observable, RawError, ContextManager } from '@datadog/browser-core'; | ||
viewContexts: import("../domain/contexts/viewContexts").ViewContexts; | ||
foregroundContexts: import("../domain/contexts/foregroundContexts").ForegroundContexts; | ||
pageStateHistory: import("../domain/contexts/pageStateHistory").PageStateHistory; | ||
@@ -26,0 +25,0 @@ urlContexts: { |
@@ -5,3 +5,2 @@ import { sendToExtension, createPageExitObservable, addTelemetryConfiguration, startTelemetry, canUseEventBridge, getEventBridge, } from '@datadog/browser-core'; | ||
import { startRumAssembly } from '../domain/assembly'; | ||
import { startForegroundContexts } from '../domain/contexts/foregroundContexts'; | ||
import { startInternalContext } from '../domain/contexts/internalContext'; | ||
@@ -65,8 +64,8 @@ import { LifeCycle } from '../domain/lifeCycle'; | ||
var locationChangeObservable = createLocationChangeObservable(location); | ||
var _a = startRumEventCollection(lifeCycle, configuration, location, session, locationChangeObservable, domMutationObservable, function () { return buildCommonContext(globalContextManager, userContextManager, recorderApi); }, reportError), viewContexts = _a.viewContexts, foregroundContexts = _a.foregroundContexts, pageStateHistory = _a.pageStateHistory, urlContexts = _a.urlContexts, actionContexts = _a.actionContexts, addAction = _a.addAction; | ||
var _a = startRumEventCollection(lifeCycle, configuration, location, session, locationChangeObservable, domMutationObservable, function () { return buildCommonContext(globalContextManager, userContextManager, recorderApi); }, reportError), viewContexts = _a.viewContexts, pageStateHistory = _a.pageStateHistory, urlContexts = _a.urlContexts, actionContexts = _a.actionContexts, addAction = _a.addAction; | ||
addTelemetryConfiguration(serializeRumConfiguration(initConfiguration)); | ||
startLongTaskCollection(lifeCycle, session); | ||
startResourceCollection(lifeCycle, configuration, session, pageStateHistory); | ||
var _b = startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, foregroundContexts, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView; | ||
var addError = startErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts).addError; | ||
var _b = startViewCollection(lifeCycle, configuration, location, domMutationObservable, locationChangeObservable, featureFlagContexts, pageStateHistory, recorderApi, initialViewOptions), addTiming = _b.addTiming, startView = _b.startView; | ||
var addError = startErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts).addError; | ||
startRequestCollection(lifeCycle, configuration, session); | ||
@@ -99,9 +98,7 @@ startPerformanceCollection(lifeCycle, configuration); | ||
var urlContexts = startUrlContexts(lifeCycle, locationChangeObservable, location); | ||
var foregroundContexts = startForegroundContexts(); | ||
var pageStateHistory = startPageStateHistory(); | ||
var _a = startActionCollection(lifeCycle, domMutationObservable, configuration, foregroundContexts), addAction = _a.addAction, actionContexts = _a.actionContexts; | ||
var _a = startActionCollection(lifeCycle, domMutationObservable, configuration, pageStateHistory), addAction = _a.addAction, actionContexts = _a.actionContexts; | ||
startRumAssembly(configuration, lifeCycle, sessionManager, viewContexts, urlContexts, actionContexts, buildCommonContext, reportError); | ||
return { | ||
viewContexts: viewContexts, | ||
foregroundContexts: foregroundContexts, | ||
pageStateHistory: pageStateHistory, | ||
@@ -113,3 +110,3 @@ urlContexts: urlContexts, | ||
viewContexts.stop(); | ||
foregroundContexts.stop(); | ||
pageStateHistory.stop(); | ||
}, | ||
@@ -116,0 +113,0 @@ }; |
@@ -53,3 +53,3 @@ import { combine, isEmptyObject, timeStampNow, currentDrift, display, createEventRateLimiter, canUseEventBridge, assign, } from '@datadog/browser-core'; | ||
}, | ||
browser_sdk_version: canUseEventBridge() ? "4.43.0" : undefined, | ||
browser_sdk_version: canUseEventBridge() ? "4.44.0" : undefined, | ||
}, | ||
@@ -56,0 +56,0 @@ application: { |
import type { RelativeTime, Duration } from '@datadog/browser-core'; | ||
import type { InForegroundPeriod } from '../../rawRumEvent.types'; | ||
export declare const MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS = 500; | ||
export declare const MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS = 2500; | ||
export interface ForegroundContexts { | ||
isInForegroundAt: (startTime: RelativeTime) => boolean | undefined; | ||
selectInForegroundPeriodsFor: (startTime: RelativeTime, duration: Duration) => InForegroundPeriod[] | undefined; | ||
stop: () => void; | ||
} | ||
import type { InForegroundPeriod, PageStateServerEntry } from '../../rawRumEvent.types'; | ||
export interface ForegroundPeriod { | ||
@@ -14,4 +7,2 @@ start: RelativeTime; | ||
} | ||
export declare function startForegroundContexts(): ForegroundContexts; | ||
export declare function addNewForegroundPeriod(): void; | ||
export declare function closeForegroundPeriod(): void; | ||
export declare function mapToForegroundPeriods(pageStateServerEntries: PageStateServerEntry[], duration: Duration): InForegroundPeriod[]; |
@@ -1,103 +0,19 @@ | ||
import { addDuration, addEventListener, elapsed, relativeNow, toServerDuration } from '@datadog/browser-core'; | ||
// Arbitrary value to cap number of element mostly for backend & to save bandwidth | ||
export var MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS = 500; | ||
// Arbitrary value to cap number of element mostly for memory consumption in the browser | ||
export var MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS = 2500; | ||
var foregroundPeriods = []; | ||
export function startForegroundContexts() { | ||
if (document.hasFocus()) { | ||
addNewForegroundPeriod(); | ||
} | ||
var stopForegroundTracking = trackFocus(addNewForegroundPeriod).stop; | ||
var stopBlurTracking = trackBlur(closeForegroundPeriod).stop; | ||
return { | ||
isInForegroundAt: isInForegroundAt, | ||
selectInForegroundPeriodsFor: selectInForegroundPeriodsFor, | ||
stop: function () { | ||
foregroundPeriods = []; | ||
stopForegroundTracking(); | ||
stopBlurTracking(); | ||
}, | ||
}; | ||
} | ||
export function addNewForegroundPeriod() { | ||
if (foregroundPeriods.length > MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS) { | ||
return; | ||
} | ||
var currentForegroundPeriod = foregroundPeriods[foregroundPeriods.length - 1]; | ||
var now = relativeNow(); | ||
if (currentForegroundPeriod !== undefined && currentForegroundPeriod.end === undefined) { | ||
return; | ||
} | ||
foregroundPeriods.push({ | ||
start: now, | ||
}); | ||
} | ||
export function closeForegroundPeriod() { | ||
if (foregroundPeriods.length === 0) { | ||
return; | ||
} | ||
var currentForegroundPeriod = foregroundPeriods[foregroundPeriods.length - 1]; | ||
var now = relativeNow(); | ||
if (currentForegroundPeriod.end !== undefined) { | ||
return; | ||
} | ||
currentForegroundPeriod.end = now; | ||
} | ||
function trackFocus(onFocusChange) { | ||
return addEventListener(window, "focus" /* DOM_EVENT.FOCUS */, function (event) { | ||
if (!event.isTrusted) { | ||
return; | ||
import { toServerDuration } from '@datadog/browser-core'; | ||
// Todo: Remove in the next major release | ||
export function mapToForegroundPeriods(pageStateServerEntries, duration) { | ||
var foregroundPeriods = []; | ||
for (var i = 0; i < pageStateServerEntries.length; i++) { | ||
var current = pageStateServerEntries[i]; | ||
var next = pageStateServerEntries[i + 1]; | ||
if (current.state === "active" /* PageState.ACTIVE */) { | ||
var start = current.start >= 0 ? current.start : 0; | ||
var end = next ? next.start : toServerDuration(duration); | ||
foregroundPeriods.push({ | ||
start: start, | ||
duration: (end - start), | ||
}); | ||
} | ||
onFocusChange(); | ||
}); | ||
} | ||
function trackBlur(onBlurChange) { | ||
return addEventListener(window, "blur" /* DOM_EVENT.BLUR */, function (event) { | ||
if (!event.isTrusted) { | ||
return; | ||
} | ||
onBlurChange(); | ||
}); | ||
} | ||
function isInForegroundAt(startTime) { | ||
for (var i = foregroundPeriods.length - 1; i >= 0; i--) { | ||
var foregroundPeriod = foregroundPeriods[i]; | ||
if (foregroundPeriod.end !== undefined && startTime > foregroundPeriod.end) { | ||
break; | ||
} | ||
if (startTime > foregroundPeriod.start && | ||
(foregroundPeriod.end === undefined || startTime < foregroundPeriod.end)) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
return foregroundPeriods; | ||
} | ||
function selectInForegroundPeriodsFor(eventStartTime, duration) { | ||
var eventEndTime = addDuration(eventStartTime, duration); | ||
var filteredForegroundPeriods = []; | ||
var earliestIndex = Math.max(0, foregroundPeriods.length - MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS); | ||
for (var i = foregroundPeriods.length - 1; i >= earliestIndex; i--) { | ||
var foregroundPeriod = foregroundPeriods[i]; | ||
if (foregroundPeriod.end !== undefined && eventStartTime > foregroundPeriod.end) { | ||
// event starts after the end of the current focus period | ||
// since the array is sorted, we can stop looking for foreground periods | ||
break; | ||
} | ||
if (eventEndTime < foregroundPeriod.start) { | ||
// event ends before the start of the current focus period | ||
// continue to previous one | ||
continue; | ||
} | ||
var startTime = eventStartTime > foregroundPeriod.start ? eventStartTime : foregroundPeriod.start; | ||
var startDuration = elapsed(eventStartTime, startTime); | ||
var endTime = foregroundPeriod.end === undefined || eventEndTime < foregroundPeriod.end ? eventEndTime : foregroundPeriod.end; | ||
var endDuration = elapsed(startTime, endTime); | ||
filteredForegroundPeriods.unshift({ | ||
start: toServerDuration(startDuration), | ||
duration: toServerDuration(endDuration), | ||
}); | ||
} | ||
return filteredForegroundPeriods; | ||
} | ||
//# sourceMappingURL=foregroundContexts.js.map |
@@ -19,2 +19,3 @@ import type { Duration, RelativeTime } from '@datadog/browser-core'; | ||
findAll: (startTime: RelativeTime, duration: Duration) => PageStateServerEntry[] | undefined; | ||
isInActivePageStateAt: (startTime: RelativeTime) => boolean; | ||
addPageState(nextPageState: PageState, startTime?: RelativeTime): void; | ||
@@ -21,0 +22,0 @@ stop: () => void; |
@@ -57,2 +57,6 @@ import { elapsed, ValueHistory, SESSION_TIME_OUT_DELAY, toServerDuration, addEventListeners, relativeNow, } from '@datadog/browser-core'; | ||
}, | ||
isInActivePageStateAt: function (startTime) { | ||
var pageStateEntry = pageStateHistory.find(startTime); | ||
return pageStateEntry !== undefined && pageStateEntry.state === "active" /* PageState.ACTIVE */; | ||
}, | ||
addPageState: addPageState, | ||
@@ -59,0 +63,0 @@ stop: function () { |
import type { ClocksState, Context, Observable } from '@datadog/browser-core'; | ||
import { ActionType } from '../../../rawRumEvent.types'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts'; | ||
import type { RumConfiguration } from '../../configuration'; | ||
import type { CommonContext } from '../../contexts/commonContext'; | ||
import type { PageStateHistory } from '../../contexts/pageStateHistory'; | ||
import type { ActionContexts, ClickAction } from './trackClickActions'; | ||
@@ -16,5 +16,5 @@ export type { ActionContexts }; | ||
export type AutoAction = ClickAction; | ||
export declare function startActionCollection(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, foregroundContexts: ForegroundContexts): { | ||
export declare function startActionCollection(lifeCycle: LifeCycle, domMutationObservable: Observable<void>, configuration: RumConfiguration, pageStateHistory: PageStateHistory): { | ||
addAction: (action: CustomAction, savedCommonContext?: CommonContext) => void; | ||
actionContexts: ActionContexts; | ||
}; |
import { noop, assign, combine, toServerDuration, generateUUID } from '@datadog/browser-core'; | ||
import { trackClickActions } from './trackClickActions'; | ||
export function startActionCollection(lifeCycle, domMutationObservable, configuration, foregroundContexts) { | ||
export function startActionCollection(lifeCycle, domMutationObservable, configuration, pageStateHistory) { | ||
lifeCycle.subscribe(1 /* LifeCycleEventType.AUTO_ACTION_COMPLETED */, function (action) { | ||
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processAction(action, foregroundContexts)); | ||
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processAction(action, pageStateHistory)); | ||
}); | ||
@@ -15,3 +15,3 @@ var actionContexts = { findActionId: noop }; | ||
savedCommonContext: savedCommonContext, | ||
}, processAction(action, foregroundContexts))); | ||
}, processAction(action, pageStateHistory))); | ||
}, | ||
@@ -21,3 +21,3 @@ actionContexts: actionContexts, | ||
} | ||
function processAction(action, foregroundContexts) { | ||
function processAction(action, pageStateHistory) { | ||
var autoActionProperties = isAutoAction(action) | ||
@@ -60,7 +60,4 @@ ? { | ||
type: "action" /* RumEventType.ACTION */, | ||
view: { in_foreground: pageStateHistory.isInActivePageStateAt(action.startClocks.relative) }, | ||
}, autoActionProperties); | ||
var inForeground = foregroundContexts.isInForegroundAt(action.startClocks.relative); | ||
if (inForeground !== undefined) { | ||
actionEvent.view = { in_foreground: inForeground }; | ||
} | ||
return { | ||
@@ -67,0 +64,0 @@ customerContext: customerContext, |
import type { Context, ClocksState } from '@datadog/browser-core'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts'; | ||
import type { FeatureFlagContexts } from '../../contexts/featureFlagContext'; | ||
import type { CommonContext } from '../../contexts/commonContext'; | ||
import type { PageStateHistory } from '../../contexts/pageStateHistory'; | ||
export interface ProvidedError { | ||
@@ -12,7 +12,7 @@ startClocks: ClocksState; | ||
} | ||
export declare function startErrorCollection(lifeCycle: LifeCycle, foregroundContexts: ForegroundContexts, featureFlagContexts: FeatureFlagContexts): { | ||
export declare function startErrorCollection(lifeCycle: LifeCycle, pageStateHistory: PageStateHistory, featureFlagContexts: FeatureFlagContexts): { | ||
addError: ({ error, handlingStack, startClocks, context: customerContext }: ProvidedError, savedCommonContext?: CommonContext | undefined) => void; | ||
}; | ||
export declare function doStartErrorCollection(lifeCycle: LifeCycle, foregroundContexts: ForegroundContexts, featureFlagContexts: FeatureFlagContexts): { | ||
export declare function doStartErrorCollection(lifeCycle: LifeCycle, pageStateHistory: PageStateHistory, featureFlagContexts: FeatureFlagContexts): { | ||
addError: ({ error, handlingStack, startClocks, context: customerContext }: ProvidedError, savedCommonContext?: CommonContext) => void; | ||
}; |
import { isEmptyObject, assign, ErrorSource, generateUUID, computeRawError, computeStackTrace, Observable, trackRuntimeError, } from '@datadog/browser-core'; | ||
import { trackConsoleError } from './trackConsoleError'; | ||
import { trackReportError } from './trackReportError'; | ||
export function startErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts) { | ||
export function startErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) { | ||
var errorObservable = new Observable(); | ||
@@ -10,5 +10,5 @@ trackConsoleError(errorObservable); | ||
errorObservable.subscribe(function (error) { return lifeCycle.notify(12 /* LifeCycleEventType.RAW_ERROR_COLLECTED */, { error: error }); }); | ||
return doStartErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts); | ||
return doStartErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts); | ||
} | ||
export function doStartErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts) { | ||
export function doStartErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) { | ||
lifeCycle.subscribe(12 /* LifeCycleEventType.RAW_ERROR_COLLECTED */, function (_a) { | ||
@@ -19,3 +19,3 @@ var error = _a.error, customerContext = _a.customerContext, savedCommonContext = _a.savedCommonContext; | ||
savedCommonContext: savedCommonContext, | ||
}, processError(error, foregroundContexts, featureFlagContexts))); | ||
}, processError(error, pageStateHistory, featureFlagContexts))); | ||
}); | ||
@@ -43,3 +43,3 @@ return { | ||
} | ||
function processError(error, foregroundContexts, featureFlagContexts) { | ||
function processError(error, pageStateHistory, featureFlagContexts) { | ||
var rawRumEvent = { | ||
@@ -60,7 +60,4 @@ date: error.startClocks.timeStamp, | ||
type: "error" /* RumEventType.ERROR */, | ||
view: { in_foreground: pageStateHistory.isInActivePageStateAt(error.startClocks.relative) }, | ||
}; | ||
var inForeground = foregroundContexts.isInForegroundAt(error.startClocks.relative); | ||
if (inForeground) { | ||
rawRumEvent.view = { in_foreground: inForeground }; | ||
} | ||
var featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(error.startClocks.relative); | ||
@@ -67,0 +64,0 @@ if (featureFlagContext && !isEmptyObject(featureFlagContext)) { |
@@ -1,5 +0,14 @@ | ||
import type { Duration, Observable, ClocksState } from '@datadog/browser-core'; | ||
import type { ClocksState, Duration, Observable } from '@datadog/browser-core'; | ||
import { noop } from '@datadog/browser-core'; | ||
import { ViewLoadingType } from '../../../rawRumEvent.types'; | ||
import type { RumConfiguration } from '../../configuration'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
export interface ScrollMetrics { | ||
maxDepth: number; | ||
maxDepthScrollHeight: number; | ||
maxDepthScrollTop: number; | ||
maxDepthTime: Duration; | ||
} | ||
/** Arbitrary scroll throttle duration */ | ||
export declare const THROTTLE_SCROLL_DURATION = 1000; | ||
export interface ViewMetrics { | ||
@@ -13,2 +22,12 @@ loadingTime?: Duration; | ||
viewMetrics: ViewMetrics; | ||
getScrollMetrics: () => ScrollMetrics | undefined; | ||
}; | ||
export declare function trackScrollMetrics(viewStart: ClocksState, callback: (scrollMetrics: ScrollMetrics) => void, getScrollValues?: typeof computeScrollValues): { | ||
stop: typeof noop; | ||
}; | ||
declare function computeScrollValues(): { | ||
scrollHeight: number; | ||
scrollDepth: number; | ||
scrollTop: number; | ||
}; | ||
export {}; |
@@ -1,10 +0,29 @@ | ||
import { noop, round, ONE_SECOND, elapsed } from '@datadog/browser-core'; | ||
import { ExperimentalFeature, isExperimentalFeatureEnabled, ONE_SECOND, addEventListener, elapsed, noop, relativeNow, round, throttle, } from '@datadog/browser-core'; | ||
import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection'; | ||
import { waitPageActivityEnd } from '../../waitPageActivityEnd'; | ||
import { getScrollY } from '../../../browser/scroll'; | ||
import { getViewportDimension } from '../../../browser/viewportObservable'; | ||
/** Arbitrary scroll throttle duration */ | ||
export var THROTTLE_SCROLL_DURATION = ONE_SECOND; | ||
export function trackViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, viewStart) { | ||
var viewMetrics = {}; | ||
var scrollMetrics; | ||
var _a = trackLoadingTime(lifeCycle, domMutationObservable, configuration, loadingType, viewStart, function (newLoadingTime) { | ||
viewMetrics.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. | ||
if (isExperimentalFeatureEnabled(ExperimentalFeature.SCROLLMAP)) { | ||
var _a = computeScrollValues(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop; | ||
scrollMetrics = { | ||
maxDepth: scrollDepth, | ||
maxDepthScrollHeight: scrollHeight, | ||
maxDepthTime: newLoadingTime, | ||
maxDepthScrollTop: scrollTop, | ||
}; | ||
} | ||
scheduleViewUpdate(); | ||
}), stopLoadingTimeTracking = _a.stop, setLoadEvent = _a.setLoadEvent; | ||
var stopScrollMetricsTracking = trackScrollMetrics(viewStart, function (newScrollMetrics) { | ||
scrollMetrics = newScrollMetrics; | ||
}, computeScrollValues).stop; | ||
var stopCLSTracking; | ||
@@ -25,7 +44,48 @@ if (isLayoutShiftSupported()) { | ||
stopCLSTracking(); | ||
stopScrollMetricsTracking(); | ||
}, | ||
setLoadEvent: setLoadEvent, | ||
viewMetrics: viewMetrics, | ||
getScrollMetrics: function () { return scrollMetrics; }, | ||
}; | ||
} | ||
export function trackScrollMetrics(viewStart, callback, getScrollValues) { | ||
if (getScrollValues === void 0) { getScrollValues = computeScrollValues; } | ||
if (!isExperimentalFeatureEnabled(ExperimentalFeature.SCROLLMAP)) { | ||
return { stop: noop }; | ||
} | ||
var maxDepth = 0; | ||
var handleScrollEvent = throttle(function () { | ||
var _a = getScrollValues(), scrollHeight = _a.scrollHeight, scrollDepth = _a.scrollDepth, scrollTop = _a.scrollTop; | ||
if (scrollDepth > maxDepth) { | ||
var now = relativeNow(); | ||
var maxDepthTime = elapsed(viewStart.relative, now); | ||
maxDepth = scrollDepth; | ||
callback({ | ||
maxDepth: maxDepth, | ||
maxDepthScrollHeight: scrollHeight, | ||
maxDepthTime: maxDepthTime, | ||
maxDepthScrollTop: scrollTop, | ||
}); | ||
} | ||
}, THROTTLE_SCROLL_DURATION, { leading: false, trailing: true }); | ||
var stop = addEventListener(window, "scroll" /* DOM_EVENT.SCROLL */, handleScrollEvent.throttled, { passive: true }).stop; | ||
return { | ||
stop: function () { | ||
handleScrollEvent.cancel(); | ||
stop(); | ||
}, | ||
}; | ||
} | ||
function computeScrollValues() { | ||
var scrollTop = getScrollY(); | ||
var height = getViewportDimension().height; | ||
var scrollHeight = Math.round((document.scrollingElement || document.documentElement).scrollHeight); | ||
var scrollDepth = Math.round(height + scrollTop); | ||
return { | ||
scrollHeight: scrollHeight, | ||
scrollDepth: scrollDepth, | ||
scrollTop: scrollTop, | ||
}; | ||
} | ||
function trackLoadingTime(lifeCycle, domMutationObservable, configuration, loadType, viewStart, callback) { | ||
@@ -32,0 +92,0 @@ var isWaitingForLoadEvent = loadType === "initial_load" /* ViewLoadingType.INITIAL_LOAD */; |
@@ -9,2 +9,3 @@ import type { Duration, ClocksState, TimeStamp, Observable, RelativeTime } from '@datadog/browser-core'; | ||
import type { Timings } from './trackInitialViewTimings'; | ||
import type { ScrollMetrics } from './trackViewMetrics'; | ||
export interface ViewEvent { | ||
@@ -27,2 +28,3 @@ id: string; | ||
cumulativeLayoutShift?: number; | ||
scrollMetrics?: ScrollMetrics; | ||
} | ||
@@ -29,0 +31,0 @@ export interface ViewCreatedEvent { |
@@ -88,3 +88,3 @@ import { noop, PageExitReason, shallowClone, assign, elapsed, generateUUID, ONE_MINUTE, throttle, clocksNow, clocksOrigin, timeStampNow, display, looksLikeRelativeTime, setInterval, clearInterval, } from '@datadog/browser-core'; | ||
}), scheduleViewUpdate = _a.throttled, cancelScheduleViewUpdate = _a.cancel; | ||
var _b = trackViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks), setLoadEvent = _b.setLoadEvent, stopViewMetricsTracking = _b.stop, viewMetrics = _b.viewMetrics; | ||
var _b = trackViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks), setLoadEvent = _b.setLoadEvent, stopViewMetricsTracking = _b.stop, viewMetrics = _b.viewMetrics, getScrollMetrics = _b.getScrollMetrics; | ||
var _c = loadingType === "initial_load" /* ViewLoadingType.INITIAL_LOAD */ | ||
@@ -117,2 +117,3 @@ ? trackInitialViewTimings(lifeCycle, setLoadEvent, scheduleViewUpdate) | ||
eventCounts: eventCounts, | ||
scrollMetrics: getScrollMetrics(), | ||
}, viewMetrics)); | ||
@@ -119,0 +120,0 @@ } |
import type { Observable } from '@datadog/browser-core'; | ||
import type { RecorderApi } from '../../../boot/rumPublicApi'; | ||
import type { LifeCycle } from '../../lifeCycle'; | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts'; | ||
import type { LocationChange } from '../../../browser/locationChangeObservable'; | ||
@@ -10,3 +9,3 @@ import type { RumConfiguration } from '../../configuration'; | ||
import type { ViewOptions } from './trackViews'; | ||
export declare function startViewCollection(lifeCycle: LifeCycle, configuration: RumConfiguration, location: Location, domMutationObservable: Observable<void>, locationChangeObservable: Observable<LocationChange>, foregroundContexts: ForegroundContexts, featureFlagContexts: FeatureFlagContexts, pageStateHistory: PageStateHistory, recorderApi: RecorderApi, 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, foregroundContexts, featureFlagContexts, pageStateHistory, recorderApi, 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, foregroundContexts, featureFlagContexts, recorderApi, pageStateHistory)); | ||
return lifeCycle.notify(10 /* LifeCycleEventType.RAW_RUM_EVENT_COLLECTED */, processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory)); | ||
}); | ||
@@ -10,6 +11,7 @@ var trackViewResult = trackViews(location, lifeCycle, domMutationObservable, configuration, locationChangeObservable, !configuration.trackViewsManually, initialViewOptions); | ||
} | ||
function processViewUpdate(view, foregroundContexts, featureFlagContexts, recorderApi, pageStateHistory) { | ||
function processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory) { | ||
var replayStats = recorderApi.getReplayStats(view.id); | ||
var featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(view.startClocks.relative); | ||
var pageStatesEnabled = isExperimentalFeatureEnabled(ExperimentalFeature.PAGE_STATES); | ||
var pageStates = pageStateHistory.findAll(view.startClocks.relative, view.duration); | ||
var viewEvent = { | ||
@@ -19,3 +21,3 @@ _dd: { | ||
replay_stats: replayStats, | ||
page_states: pageStatesEnabled ? pageStateHistory.findAll(view.startClocks.relative, view.duration) : undefined, | ||
page_states: pageStatesEnabled ? pageStates : undefined, | ||
}, | ||
@@ -55,7 +57,15 @@ date: view.startClocks.timeStamp, | ||
time_spent: toServerDuration(view.duration), | ||
in_foreground_periods: !pageStatesEnabled | ||
? foregroundContexts.selectInForegroundPeriodsFor(view.startClocks.relative, view.duration) | ||
: undefined, | ||
in_foreground_periods: !pageStatesEnabled && pageStates ? mapToForegroundPeriods(pageStates, view.duration) : undefined, // Todo: Remove in the next major release | ||
}, | ||
feature_flags: featureFlagContext && !isEmptyObject(featureFlagContext) ? featureFlagContext : undefined, | ||
display: view.scrollMetrics | ||
? { | ||
scroll: { | ||
max_depth: view.scrollMetrics.maxDepth, | ||
max_depth_scroll_height: view.scrollMetrics.maxDepthScrollHeight, | ||
max_depth_scroll_top: view.scrollMetrics.maxDepthScrollTop, | ||
max_depth_time: toServerDuration(view.scrollMetrics.maxDepthTime), | ||
}, | ||
} | ||
: undefined, | ||
session: { | ||
@@ -65,2 +75,5 @@ has_replay: replayStats ? true : undefined, | ||
}, | ||
privacy: { | ||
replay_level: configuration.defaultPrivacyLevel, | ||
}, | ||
}; | ||
@@ -67,0 +80,0 @@ if (!isEmptyObject(view.customTimings)) { |
@@ -12,2 +12,3 @@ export { RumPublicApi, makeRumPublicApi, RecorderApi, StartRum } from './boot/rumPublicApi'; | ||
export { initViewportObservable, getViewportDimension } from './browser/viewportObservable'; | ||
export { getScrollX, getScrollY } from './browser/scroll'; | ||
export { RumInitConfiguration, RumConfiguration } from './domain/configuration'; | ||
@@ -14,0 +15,0 @@ export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/rumEventsCollection/action/getActionNameFromElement'; |
@@ -6,2 +6,3 @@ export { makeRumPublicApi } from './boot/rumPublicApi'; | ||
export { initViewportObservable, getViewportDimension } from './browser/viewportObservable'; | ||
export { getScrollX, getScrollY } from './browser/scroll'; | ||
export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/rumEventsCollection/action/getActionNameFromElement'; | ||
@@ -8,0 +9,0 @@ export { STABLE_ATTRIBUTES } from './domain/rumEventsCollection/action/getSelectorFromElement'; |
@@ -1,2 +0,2 @@ | ||
import type { Context, Duration, ErrorSource, ErrorHandling, ResourceType, ServerDuration, TimeStamp, RawErrorCause } from '@datadog/browser-core'; | ||
import type { Context, Duration, ErrorSource, ErrorHandling, ResourceType, ServerDuration, TimeStamp, RawErrorCause, DefaultPrivacyLevel } from '@datadog/browser-core'; | ||
import type { PageState } from './domain/contexts/pageStateHistory'; | ||
@@ -95,2 +95,6 @@ import type { RumSessionPlan } from './domain/rumSessionManager'; | ||
feature_flags?: Context; | ||
display?: ViewDisplay; | ||
privacy?: { | ||
replay_level: DefaultPrivacyLevel; | ||
}; | ||
_dd: { | ||
@@ -102,2 +106,10 @@ document_version: number; | ||
} | ||
interface ViewDisplay { | ||
scroll: { | ||
max_depth?: number; | ||
max_depth_scroll_height?: number; | ||
max_depth_scroll_top?: number; | ||
max_depth_time?: ServerDuration; | ||
}; | ||
} | ||
export interface InForegroundPeriod { | ||
@@ -104,0 +116,0 @@ start: ServerDuration; |
@@ -711,2 +711,12 @@ /** | ||
/** | ||
* Privacy properties | ||
*/ | ||
readonly privacy?: { | ||
/** | ||
* The replay privacy level | ||
*/ | ||
readonly replay_level: 'allow' | 'mask' | 'mask-user-input'; | ||
[k: string]: unknown; | ||
}; | ||
/** | ||
* Internal properties | ||
@@ -733,4 +743,50 @@ */ | ||
}[]; | ||
/** | ||
* Debug metadata for Replay Sessions | ||
*/ | ||
replay_stats?: { | ||
/** | ||
* The number of records produced during this view lifetime | ||
*/ | ||
records_count?: number; | ||
/** | ||
* The number of segments sent during this view lifetime | ||
*/ | ||
segments_count?: number; | ||
/** | ||
* The total size in bytes of the segments sent during this view lifetime | ||
*/ | ||
segments_total_raw_size?: number; | ||
[k: string]: unknown; | ||
}; | ||
[k: string]: unknown; | ||
}; | ||
/** | ||
* Display properties | ||
*/ | ||
readonly display?: { | ||
/** | ||
* Scroll properties | ||
*/ | ||
readonly scroll?: { | ||
/** | ||
* Distance between the top and the lowest point reached on this view (in pixels) | ||
*/ | ||
readonly max_depth: number; | ||
/** | ||
* 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) | ||
*/ | ||
readonly max_depth_scroll_top: number; | ||
/** | ||
* Duration between the view start and the scroll event that reached the maximum scroll depth for this view (in nanoseconds) | ||
*/ | ||
readonly max_depth_time: number; | ||
[k: string]: unknown; | ||
}; | ||
[k: string]: unknown; | ||
}; | ||
[k: string]: unknown; | ||
@@ -915,2 +971,6 @@ }; | ||
/** | ||
* Operating system build number, e.g. 15D21 | ||
*/ | ||
readonly build?: string; | ||
/** | ||
* Major operating system version, e.g. 8 | ||
@@ -917,0 +977,0 @@ */ |
{ | ||
"name": "@datadog/browser-rum-core", | ||
"version": "4.43.0", | ||
"version": "4.44.0", | ||
"license": "Apache-2.0", | ||
@@ -15,3 +15,3 @@ "main": "cjs/index.js", | ||
"dependencies": { | ||
"@datadog/browser-core": "4.43.0" | ||
"@datadog/browser-core": "4.44.0" | ||
}, | ||
@@ -29,3 +29,3 @@ "devDependencies": { | ||
}, | ||
"gitHead": "27baf6471a3e48028c52af9c6282e00662687cc2" | ||
"gitHead": "1d179b104265a2f149433026918f757eccc1bdd8" | ||
} |
@@ -14,3 +14,2 @@ import type { Observable, TelemetryEvent, RawError, ContextManager } from '@datadog/browser-core' | ||
import { startRumAssembly } from '../domain/assembly' | ||
import { startForegroundContexts } from '../domain/contexts/foregroundContexts' | ||
import { startInternalContext } from '../domain/contexts/internalContext' | ||
@@ -106,13 +105,12 @@ import { LifeCycle, LifeCycleEventType } from '../domain/lifeCycle' | ||
const { viewContexts, foregroundContexts, pageStateHistory, urlContexts, actionContexts, addAction } = | ||
startRumEventCollection( | ||
lifeCycle, | ||
configuration, | ||
location, | ||
session, | ||
locationChangeObservable, | ||
domMutationObservable, | ||
() => buildCommonContext(globalContextManager, userContextManager, recorderApi), | ||
reportError | ||
) | ||
const { viewContexts, pageStateHistory, urlContexts, actionContexts, addAction } = startRumEventCollection( | ||
lifeCycle, | ||
configuration, | ||
location, | ||
session, | ||
locationChangeObservable, | ||
domMutationObservable, | ||
() => buildCommonContext(globalContextManager, userContextManager, recorderApi), | ||
reportError | ||
) | ||
@@ -129,3 +127,2 @@ addTelemetryConfiguration(serializeRumConfiguration(initConfiguration)) | ||
locationChangeObservable, | ||
foregroundContexts, | ||
featureFlagContexts, | ||
@@ -136,3 +133,3 @@ pageStateHistory, | ||
) | ||
const { addError } = startErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts) | ||
const { addError } = startErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) | ||
@@ -186,3 +183,2 @@ startRequestCollection(lifeCycle, configuration, session) | ||
const foregroundContexts = startForegroundContexts() | ||
const pageStateHistory = startPageStateHistory() | ||
@@ -194,3 +190,3 @@ | ||
configuration, | ||
foregroundContexts | ||
pageStateHistory | ||
) | ||
@@ -211,3 +207,2 @@ | ||
viewContexts, | ||
foregroundContexts, | ||
pageStateHistory, | ||
@@ -219,5 +214,5 @@ urlContexts, | ||
viewContexts.stop() | ||
foregroundContexts.stop() | ||
pageStateHistory.stop() | ||
}, | ||
} | ||
} |
@@ -1,16 +0,6 @@ | ||
import type { RelativeTime, Duration } from '@datadog/browser-core' | ||
import { addDuration, addEventListener, DOM_EVENT, elapsed, relativeNow, toServerDuration } from '@datadog/browser-core' | ||
import type { InForegroundPeriod } from '../../rawRumEvent.types' | ||
import type { RelativeTime, Duration, ServerDuration } from '@datadog/browser-core' | ||
import { toServerDuration } from '@datadog/browser-core' | ||
import type { InForegroundPeriod, PageStateServerEntry } from '../../rawRumEvent.types' | ||
import { PageState } from './pageStateHistory' | ||
// Arbitrary value to cap number of element mostly for backend & to save bandwidth | ||
export const MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS = 500 | ||
// Arbitrary value to cap number of element mostly for memory consumption in the browser | ||
export const MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS = 2500 | ||
export interface ForegroundContexts { | ||
isInForegroundAt: (startTime: RelativeTime) => boolean | undefined | ||
selectInForegroundPeriodsFor: (startTime: RelativeTime, duration: Duration) => InForegroundPeriod[] | undefined | ||
stop: () => void | ||
} | ||
export interface ForegroundPeriod { | ||
@@ -21,110 +11,23 @@ start: RelativeTime | ||
let foregroundPeriods: ForegroundPeriod[] = [] | ||
// Todo: Remove in the next major release | ||
export function mapToForegroundPeriods( | ||
pageStateServerEntries: PageStateServerEntry[], | ||
duration: Duration | ||
): InForegroundPeriod[] { | ||
const foregroundPeriods: InForegroundPeriod[] = [] | ||
for (let i = 0; i < pageStateServerEntries.length; i++) { | ||
const current = pageStateServerEntries[i] | ||
const next = pageStateServerEntries[i + 1] | ||
export function startForegroundContexts(): ForegroundContexts { | ||
if (document.hasFocus()) { | ||
addNewForegroundPeriod() | ||
} | ||
const { stop: stopForegroundTracking } = trackFocus(addNewForegroundPeriod) | ||
const { stop: stopBlurTracking } = trackBlur(closeForegroundPeriod) | ||
return { | ||
isInForegroundAt, | ||
selectInForegroundPeriodsFor, | ||
stop: () => { | ||
foregroundPeriods = [] | ||
stopForegroundTracking() | ||
stopBlurTracking() | ||
}, | ||
} | ||
} | ||
export function addNewForegroundPeriod() { | ||
if (foregroundPeriods.length > MAX_NUMBER_OF_STORED_FOREGROUND_PERIODS) { | ||
return | ||
} | ||
const currentForegroundPeriod = foregroundPeriods[foregroundPeriods.length - 1] | ||
const now = relativeNow() | ||
if (currentForegroundPeriod !== undefined && currentForegroundPeriod.end === undefined) { | ||
return | ||
} | ||
foregroundPeriods.push({ | ||
start: now, | ||
}) | ||
} | ||
export function closeForegroundPeriod() { | ||
if (foregroundPeriods.length === 0) { | ||
return | ||
} | ||
const currentForegroundPeriod = foregroundPeriods[foregroundPeriods.length - 1] | ||
const now = relativeNow() | ||
if (currentForegroundPeriod.end !== undefined) { | ||
return | ||
} | ||
currentForegroundPeriod.end = now | ||
} | ||
function trackFocus(onFocusChange: () => void) { | ||
return addEventListener(window, DOM_EVENT.FOCUS, (event) => { | ||
if (!event.isTrusted) { | ||
return | ||
if (current.state === PageState.ACTIVE) { | ||
const start = current.start >= 0 ? current.start : (0 as ServerDuration) | ||
const end = next ? next.start : toServerDuration(duration) | ||
foregroundPeriods.push({ | ||
start, | ||
duration: (end - start) as ServerDuration, | ||
}) | ||
} | ||
onFocusChange() | ||
}) | ||
} | ||
function trackBlur(onBlurChange: () => void) { | ||
return addEventListener(window, DOM_EVENT.BLUR, (event) => { | ||
if (!event.isTrusted) { | ||
return | ||
} | ||
onBlurChange() | ||
}) | ||
} | ||
function isInForegroundAt(startTime: RelativeTime): boolean { | ||
for (let i = foregroundPeriods.length - 1; i >= 0; i--) { | ||
const foregroundPeriod = foregroundPeriods[i] | ||
if (foregroundPeriod.end !== undefined && startTime > foregroundPeriod.end) { | ||
break | ||
} | ||
if ( | ||
startTime > foregroundPeriod.start && | ||
(foregroundPeriod.end === undefined || startTime < foregroundPeriod.end) | ||
) { | ||
return true | ||
} | ||
} | ||
return false | ||
} | ||
function selectInForegroundPeriodsFor(eventStartTime: RelativeTime, duration: Duration): InForegroundPeriod[] { | ||
const eventEndTime = addDuration(eventStartTime, duration) | ||
const filteredForegroundPeriods: InForegroundPeriod[] = [] | ||
const earliestIndex = Math.max(0, foregroundPeriods.length - MAX_NUMBER_OF_SELECTABLE_FOREGROUND_PERIODS) | ||
for (let i = foregroundPeriods.length - 1; i >= earliestIndex; i--) { | ||
const foregroundPeriod = foregroundPeriods[i] | ||
if (foregroundPeriod.end !== undefined && eventStartTime > foregroundPeriod.end) { | ||
// event starts after the end of the current focus period | ||
// since the array is sorted, we can stop looking for foreground periods | ||
break | ||
} | ||
if (eventEndTime < foregroundPeriod.start) { | ||
// event ends before the start of the current focus period | ||
// continue to previous one | ||
continue | ||
} | ||
const startTime = eventStartTime > foregroundPeriod.start ? eventStartTime : foregroundPeriod.start | ||
const startDuration = elapsed(eventStartTime, startTime) | ||
const endTime = | ||
foregroundPeriod.end === undefined || eventEndTime < foregroundPeriod.end ? eventEndTime : foregroundPeriod.end | ||
const endDuration = elapsed(startTime, endTime) | ||
filteredForegroundPeriods.unshift({ | ||
start: toServerDuration(startDuration), | ||
duration: toServerDuration(endDuration), | ||
}) | ||
} | ||
return filteredForegroundPeriods | ||
return foregroundPeriods | ||
} |
@@ -32,2 +32,3 @@ import type { Duration, RelativeTime } from '@datadog/browser-core' | ||
findAll: (startTime: RelativeTime, duration: Duration) => PageStateServerEntry[] | undefined | ||
isInActivePageStateAt: (startTime: RelativeTime) => boolean | ||
addPageState(nextPageState: PageState, startTime?: RelativeTime): void | ||
@@ -102,2 +103,6 @@ stop: () => void | ||
}, | ||
isInActivePageStateAt: (startTime: RelativeTime) => { | ||
const pageStateEntry = pageStateHistory.find(startTime) | ||
return pageStateEntry !== undefined && pageStateEntry.state === PageState.ACTIVE | ||
}, | ||
addPageState, | ||
@@ -104,0 +109,0 @@ stop: () => { |
@@ -8,5 +8,5 @@ import type { ClocksState, Context, Observable } from '@datadog/browser-core' | ||
import { LifeCycleEventType } from '../../lifeCycle' | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts' | ||
import type { RumConfiguration } from '../../configuration' | ||
import type { CommonContext } from '../../contexts/commonContext' | ||
import type { PageStateHistory } from '../../contexts/pageStateHistory' | ||
import type { ActionContexts, ClickAction } from './trackClickActions' | ||
@@ -30,6 +30,6 @@ import { trackClickActions } from './trackClickActions' | ||
configuration: RumConfiguration, | ||
foregroundContexts: ForegroundContexts | ||
pageStateHistory: PageStateHistory | ||
) { | ||
lifeCycle.subscribe(LifeCycleEventType.AUTO_ACTION_COMPLETED, (action) => | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processAction(action, foregroundContexts)) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processAction(action, pageStateHistory)) | ||
) | ||
@@ -50,3 +50,3 @@ | ||
}, | ||
processAction(action, foregroundContexts) | ||
processAction(action, pageStateHistory) | ||
) | ||
@@ -61,3 +61,3 @@ ) | ||
action: AutoAction | CustomAction, | ||
foregroundContexts: ForegroundContexts | ||
pageStateHistory: PageStateHistory | ||
): RawRumEventCollectedData<RawRumActionEvent> { | ||
@@ -102,9 +102,7 @@ const autoActionProperties = isAutoAction(action) | ||
type: RumEventType.ACTION as const, | ||
view: { in_foreground: pageStateHistory.isInActivePageStateAt(action.startClocks.relative) }, | ||
}, | ||
autoActionProperties | ||
) | ||
const inForeground = foregroundContexts.isInForegroundAt(action.startClocks.relative) | ||
if (inForeground !== undefined) { | ||
actionEvent.view = { in_foreground: inForeground } | ||
} | ||
return { | ||
@@ -111,0 +109,0 @@ customerContext, |
@@ -18,5 +18,5 @@ import type { Context, RawError, ClocksState } from '@datadog/browser-core' | ||
import { LifeCycleEventType } from '../../lifeCycle' | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts' | ||
import type { FeatureFlagContexts } from '../../contexts/featureFlagContext' | ||
import type { CommonContext } from '../../contexts/commonContext' | ||
import type { PageStateHistory } from '../../contexts/pageStateHistory' | ||
import { trackConsoleError } from './trackConsoleError' | ||
@@ -34,3 +34,3 @@ import { trackReportError } from './trackReportError' | ||
lifeCycle: LifeCycle, | ||
foregroundContexts: ForegroundContexts, | ||
pageStateHistory: PageStateHistory, | ||
featureFlagContexts: FeatureFlagContexts | ||
@@ -46,3 +46,3 @@ ) { | ||
return doStartErrorCollection(lifeCycle, foregroundContexts, featureFlagContexts) | ||
return doStartErrorCollection(lifeCycle, pageStateHistory, featureFlagContexts) | ||
} | ||
@@ -52,3 +52,3 @@ | ||
lifeCycle: LifeCycle, | ||
foregroundContexts: ForegroundContexts, | ||
pageStateHistory: PageStateHistory, | ||
featureFlagContexts: FeatureFlagContexts | ||
@@ -64,3 +64,3 @@ ) { | ||
}, | ||
processError(error, foregroundContexts, featureFlagContexts) | ||
processError(error, pageStateHistory, featureFlagContexts) | ||
) | ||
@@ -97,3 +97,3 @@ ) | ||
error: RawError, | ||
foregroundContexts: ForegroundContexts, | ||
pageStateHistory: PageStateHistory, | ||
featureFlagContexts: FeatureFlagContexts | ||
@@ -116,9 +116,5 @@ ): RawRumEventCollectedData<RawRumErrorEvent> { | ||
type: RumEventType.ERROR as const, | ||
view: { in_foreground: pageStateHistory.isInActivePageStateAt(error.startClocks.relative) }, | ||
} | ||
const inForeground = foregroundContexts.isInForegroundAt(error.startClocks.relative) | ||
if (inForeground) { | ||
rawRumEvent.view = { in_foreground: inForeground } | ||
} | ||
const featureFlagContext = featureFlagContexts.findFeatureFlagEvaluations(error.startClocks.relative) | ||
@@ -125,0 +121,0 @@ if (featureFlagContext && !isEmptyObject(featureFlagContext)) { |
@@ -1,3 +0,14 @@ | ||
import type { Duration, RelativeTime, Observable, ClocksState } from '@datadog/browser-core' | ||
import { noop, round, ONE_SECOND, elapsed } from '@datadog/browser-core' | ||
import type { ClocksState, Duration, Observable, RelativeTime } from '@datadog/browser-core' | ||
import { | ||
ExperimentalFeature, | ||
isExperimentalFeatureEnabled, | ||
DOM_EVENT, | ||
ONE_SECOND, | ||
addEventListener, | ||
elapsed, | ||
noop, | ||
relativeNow, | ||
round, | ||
throttle, | ||
} from '@datadog/browser-core' | ||
import type { RumLayoutShiftTiming } from '../../../browser/performanceCollection' | ||
@@ -11,2 +22,15 @@ import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection' | ||
import { getScrollY } from '../../../browser/scroll' | ||
import { getViewportDimension } from '../../../browser/viewportObservable' | ||
export interface ScrollMetrics { | ||
maxDepth: number | ||
maxDepthScrollHeight: number | ||
maxDepthScrollTop: number | ||
maxDepthTime: Duration | ||
} | ||
/** Arbitrary scroll throttle duration */ | ||
export const THROTTLE_SCROLL_DURATION = ONE_SECOND | ||
export interface ViewMetrics { | ||
@@ -27,2 +51,4 @@ loadingTime?: Duration | ||
let scrollMetrics: ScrollMetrics | undefined | ||
const { stop: stopLoadingTimeTracking, setLoadEvent } = trackLoadingTime( | ||
@@ -36,2 +62,15 @@ lifeCycle, | ||
viewMetrics.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. | ||
if (isExperimentalFeatureEnabled(ExperimentalFeature.SCROLLMAP)) { | ||
const { scrollHeight, scrollDepth, scrollTop } = computeScrollValues() | ||
scrollMetrics = { | ||
maxDepth: scrollDepth, | ||
maxDepthScrollHeight: scrollHeight, | ||
maxDepthTime: newLoadingTime, | ||
maxDepthScrollTop: scrollTop, | ||
} | ||
} | ||
scheduleViewUpdate() | ||
@@ -41,2 +80,10 @@ } | ||
const { stop: stopScrollMetricsTracking } = trackScrollMetrics( | ||
viewStart, | ||
(newScrollMetrics) => { | ||
scrollMetrics = newScrollMetrics | ||
}, | ||
computeScrollValues | ||
) | ||
let stopCLSTracking: () => void | ||
@@ -52,2 +99,3 @@ if (isLayoutShiftSupported()) { | ||
} | ||
return { | ||
@@ -57,8 +105,64 @@ stop: () => { | ||
stopCLSTracking() | ||
stopScrollMetricsTracking() | ||
}, | ||
setLoadEvent, | ||
viewMetrics, | ||
getScrollMetrics: () => scrollMetrics, | ||
} | ||
} | ||
export function trackScrollMetrics( | ||
viewStart: ClocksState, | ||
callback: (scrollMetrics: ScrollMetrics) => void, | ||
getScrollValues = computeScrollValues | ||
) { | ||
if (!isExperimentalFeatureEnabled(ExperimentalFeature.SCROLLMAP)) { | ||
return { stop: noop } | ||
} | ||
let maxDepth = 0 | ||
const handleScrollEvent = throttle( | ||
() => { | ||
const { scrollHeight, scrollDepth, scrollTop } = getScrollValues() | ||
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 { stop } = addEventListener(window, DOM_EVENT.SCROLL, handleScrollEvent.throttled, { passive: true }) | ||
return { | ||
stop: () => { | ||
handleScrollEvent.cancel() | ||
stop() | ||
}, | ||
} | ||
} | ||
function computeScrollValues() { | ||
const scrollTop = getScrollY() | ||
const { height } = getViewportDimension() | ||
const scrollHeight = Math.round((document.scrollingElement || document.documentElement).scrollHeight) | ||
const scrollDepth = Math.round(height + scrollTop) | ||
return { | ||
scrollHeight, | ||
scrollDepth, | ||
scrollTop, | ||
} | ||
} | ||
function trackLoadingTime( | ||
@@ -65,0 +169,0 @@ lifeCycle: LifeCycle, |
@@ -30,2 +30,3 @@ import type { Duration, ClocksState, TimeStamp, Observable, Subscription, RelativeTime } from '@datadog/browser-core' | ||
import { trackInitialViewTimings } from './trackInitialViewTimings' | ||
import type { ScrollMetrics } from './trackViewMetrics' | ||
import { trackViewMetrics } from './trackViewMetrics' | ||
@@ -51,2 +52,3 @@ import { trackViewEventCounts } from './trackViewEventCounts' | ||
cumulativeLayoutShift?: number | ||
scrollMetrics?: ScrollMetrics | ||
} | ||
@@ -190,2 +192,3 @@ | ||
viewMetrics, | ||
getScrollMetrics, | ||
} = trackViewMetrics(lifeCycle, domMutationObservable, configuration, scheduleViewUpdate, loadingType, startClocks) | ||
@@ -212,5 +215,5 @@ | ||
cancelScheduleViewUpdate() | ||
documentVersion += 1 | ||
const currentEnd = endClocks === undefined ? timeStampNow() : endClocks.timeStamp | ||
lifeCycle.notify( | ||
@@ -234,2 +237,3 @@ LifeCycleEventType.VIEW_UPDATED, | ||
eventCounts, | ||
scrollMetrics: getScrollMetrics(), | ||
}, | ||
@@ -236,0 +240,0 @@ viewMetrics |
@@ -15,3 +15,3 @@ import type { Duration, ServerDuration, Observable } from '@datadog/browser-core' | ||
import { LifeCycleEventType } from '../../lifeCycle' | ||
import type { ForegroundContexts } from '../../contexts/foregroundContexts' | ||
import { mapToForegroundPeriods } from '../../contexts/foregroundContexts' | ||
import type { LocationChange } from '../../../browser/locationChangeObservable' | ||
@@ -30,3 +30,2 @@ import type { RumConfiguration } from '../../configuration' | ||
locationChangeObservable: Observable<LocationChange>, | ||
foregroundContexts: ForegroundContexts, | ||
featureFlagContexts: FeatureFlagContexts, | ||
@@ -40,3 +39,3 @@ pageStateHistory: PageStateHistory, | ||
LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, | ||
processViewUpdate(view, foregroundContexts, featureFlagContexts, recorderApi, pageStateHistory) | ||
processViewUpdate(view, configuration, featureFlagContexts, recorderApi, pageStateHistory) | ||
) | ||
@@ -59,3 +58,3 @@ ) | ||
view: ViewEvent, | ||
foregroundContexts: ForegroundContexts, | ||
configuration: RumConfiguration, | ||
featureFlagContexts: FeatureFlagContexts, | ||
@@ -68,2 +67,3 @@ recorderApi: RecorderApi, | ||
const pageStatesEnabled = isExperimentalFeatureEnabled(ExperimentalFeature.PAGE_STATES) | ||
const pageStates = pageStateHistory.findAll(view.startClocks.relative, view.duration) | ||
const viewEvent: RawRumViewEvent = { | ||
@@ -73,3 +73,3 @@ _dd: { | ||
replay_stats: replayStats, | ||
page_states: pageStatesEnabled ? pageStateHistory.findAll(view.startClocks.relative, view.duration) : undefined, | ||
page_states: pageStatesEnabled ? pageStates : undefined, | ||
}, | ||
@@ -109,7 +109,16 @@ date: view.startClocks.timeStamp, | ||
time_spent: toServerDuration(view.duration), | ||
in_foreground_periods: !pageStatesEnabled | ||
? foregroundContexts.selectInForegroundPeriodsFor(view.startClocks.relative, view.duration) | ||
: undefined, | ||
in_foreground_periods: | ||
!pageStatesEnabled && pageStates ? mapToForegroundPeriods(pageStates, view.duration) : undefined, // Todo: Remove in the next major release | ||
}, | ||
feature_flags: featureFlagContext && !isEmptyObject(featureFlagContext) ? featureFlagContext : undefined, | ||
display: view.scrollMetrics | ||
? { | ||
scroll: { | ||
max_depth: view.scrollMetrics.maxDepth, | ||
max_depth_scroll_height: view.scrollMetrics.maxDepthScrollHeight, | ||
max_depth_scroll_top: view.scrollMetrics.maxDepthScrollTop, | ||
max_depth_time: toServerDuration(view.scrollMetrics.maxDepthTime), | ||
}, | ||
} | ||
: undefined, | ||
session: { | ||
@@ -119,2 +128,5 @@ has_replay: replayStats ? true : undefined, | ||
}, | ||
privacy: { | ||
replay_level: configuration.defaultPrivacyLevel, | ||
}, | ||
} | ||
@@ -121,0 +133,0 @@ if (!isEmptyObject(view.customTimings)) { |
@@ -29,2 +29,3 @@ export { RumPublicApi, makeRumPublicApi, RecorderApi, StartRum } from './boot/rumPublicApi' | ||
export { initViewportObservable, getViewportDimension } from './browser/viewportObservable' | ||
export { getScrollX, getScrollY } from './browser/scroll' | ||
export { RumInitConfiguration, RumConfiguration } from './domain/configuration' | ||
@@ -31,0 +32,0 @@ export { DEFAULT_PROGRAMMATIC_ACTION_NAME_ATTRIBUTE } from './domain/rumEventsCollection/action/getActionNameFromElement' |
@@ -10,2 +10,3 @@ import type { | ||
RawErrorCause, | ||
DefaultPrivacyLevel, | ||
} from '@datadog/browser-core' | ||
@@ -111,2 +112,6 @@ import type { PageState } from './domain/contexts/pageStateHistory' | ||
feature_flags?: Context | ||
display?: ViewDisplay | ||
privacy?: { | ||
replay_level: DefaultPrivacyLevel | ||
} | ||
_dd: { | ||
@@ -119,2 +124,11 @@ document_version: number | ||
interface ViewDisplay { | ||
scroll: { | ||
max_depth?: number | ||
max_depth_scroll_height?: number | ||
max_depth_scroll_top?: number | ||
max_depth_time?: ServerDuration | ||
} | ||
} | ||
export interface InForegroundPeriod { | ||
@@ -121,0 +135,0 @@ start: ServerDuration |
@@ -768,2 +768,12 @@ /* eslint-disable */ | ||
/** | ||
* Privacy properties | ||
*/ | ||
readonly privacy?: { | ||
/** | ||
* The replay privacy level | ||
*/ | ||
readonly replay_level: 'allow' | 'mask' | 'mask-user-input' | ||
[k: string]: unknown | ||
} | ||
/** | ||
* Internal properties | ||
@@ -790,4 +800,50 @@ */ | ||
}[] | ||
/** | ||
* Debug metadata for Replay Sessions | ||
*/ | ||
replay_stats?: { | ||
/** | ||
* The number of records produced during this view lifetime | ||
*/ | ||
records_count?: number | ||
/** | ||
* The number of segments sent during this view lifetime | ||
*/ | ||
segments_count?: number | ||
/** | ||
* The total size in bytes of the segments sent during this view lifetime | ||
*/ | ||
segments_total_raw_size?: number | ||
[k: string]: unknown | ||
} | ||
[k: string]: unknown | ||
} | ||
/** | ||
* Display properties | ||
*/ | ||
readonly display?: { | ||
/** | ||
* Scroll properties | ||
*/ | ||
readonly scroll?: { | ||
/** | ||
* Distance between the top and the lowest point reached on this view (in pixels) | ||
*/ | ||
readonly max_depth: number | ||
/** | ||
* 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) | ||
*/ | ||
readonly max_depth_scroll_top: number | ||
/** | ||
* Duration between the view start and the scroll event that reached the maximum scroll depth for this view (in nanoseconds) | ||
*/ | ||
readonly max_depth_time: number | ||
[k: string]: unknown | ||
} | ||
[k: string]: unknown | ||
} | ||
[k: string]: unknown | ||
@@ -983,2 +1039,6 @@ } | ||
/** | ||
* Operating system build number, e.g. 15D21 | ||
*/ | ||
readonly build?: string | ||
/** | ||
* Major operating system version, e.g. 8 | ||
@@ -985,0 +1045,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
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
1104260
402
20503
+ Added@datadog/browser-core@4.44.0(transitive)
- Removed@datadog/browser-core@4.43.0(transitive)
Updated@datadog/browser-core@4.44.0