@datadog/browser-rum-core
Advanced tools
Comparing version 2.5.4 to 2.5.5
@@ -7,4 +7,4 @@ "use strict"; | ||
datacenter: 'us', | ||
sdkVersion: '2.5.4', | ||
sdkVersion: '2.5.5', | ||
}; | ||
//# sourceMappingURL=buildEnv.js.map |
@@ -6,3 +6,9 @@ import { Configuration } from '@datadog/browser-core'; | ||
import { RumUserConfiguration } from './rumPublicApi'; | ||
export declare function startRum(userConfiguration: RumUserConfiguration, getCommonContext: () => CommonContext): { | ||
export declare type NewLocationListener = (newLocation: Location, oldLocation?: Location) => undefined | { | ||
shouldCreateView?: boolean; | ||
viewName?: string; | ||
}; | ||
export declare function startRum(userConfiguration: RumUserConfiguration & { | ||
onNewLocation?: NewLocationListener; | ||
}, getCommonContext: () => CommonContext): { | ||
addAction: (action: import("../domain/rumEventsCollection/action/trackActions").CustomAction, savedCommonContext?: CommonContext | undefined) => void; | ||
@@ -17,3 +23,3 @@ addError: ({ error, startTime, context: customerContext, source }: import("../domain/rumEventsCollection/error/errorCollection").ProvidedError, savedCommonContext?: CommonContext | undefined) => void; | ||
}; | ||
export declare function startRumEventCollection(applicationId: string, location: Location, lifeCycle: LifeCycle, configuration: Configuration, session: RumSession, getCommonContext: () => CommonContext): { | ||
export declare function startRumEventCollection(applicationId: string, location: Location, lifeCycle: LifeCycle, configuration: Configuration, session: RumSession, getCommonContext: () => CommonContext, onNewLocation?: NewLocationListener): { | ||
addAction: (action: import("../domain/rumEventsCollection/action/trackActions").CustomAction, savedCommonContext?: CommonContext | undefined) => void; | ||
@@ -20,0 +26,0 @@ addError: ({ error, startTime, context: customerContext, source }: import("../domain/rumEventsCollection/error/errorCollection").ProvidedError, savedCommonContext?: CommonContext | undefined) => void; |
@@ -24,2 +24,5 @@ "use strict"; | ||
var session = rumSession_1.startRumSession(configuration, lifeCycle); | ||
if (!configuration.isEnabled('onNewLocation')) { | ||
userConfiguration.onNewLocation = undefined; | ||
} | ||
internalMonitoring.setExternalContextProvider(function () { | ||
@@ -30,3 +33,3 @@ return browser_core_1.combine({ | ||
}); | ||
var _b = startRumEventCollection(userConfiguration.applicationId, location, lifeCycle, configuration, session, getCommonContext), parentContexts = _b.parentContexts, addError = _b.addError, addAction = _b.addAction, addTiming = _b.addTiming; | ||
var _b = startRumEventCollection(userConfiguration.applicationId, location, lifeCycle, configuration, session, getCommonContext, userConfiguration.onNewLocation), parentContexts = _b.parentContexts, addError = _b.addError, addAction = _b.addAction, addTiming = _b.addTiming; | ||
requestCollection_1.startRequestCollection(lifeCycle, configuration); | ||
@@ -48,3 +51,3 @@ performanceCollection_1.startPerformanceCollection(lifeCycle, configuration); | ||
exports.startRum = startRum; | ||
function startRumEventCollection(applicationId, location, lifeCycle, configuration, session, getCommonContext) { | ||
function startRumEventCollection(applicationId, location, lifeCycle, configuration, session, getCommonContext, onNewLocation) { | ||
var parentContexts = parentContexts_1.startParentContexts(lifeCycle, session); | ||
@@ -55,3 +58,3 @@ var batch = batch_1.startRumBatch(configuration, lifeCycle); | ||
resourceCollection_1.startResourceCollection(lifeCycle, session); | ||
var addTiming = viewCollection_1.startViewCollection(lifeCycle, location).addTiming; | ||
var addTiming = viewCollection_1.startViewCollection(lifeCycle, location, onNewLocation).addTiming; | ||
var addError = errorCollection_1.startErrorCollection(lifeCycle, configuration).addError; | ||
@@ -58,0 +61,0 @@ var addAction = actionCollection_1.startActionCollection(lifeCycle, configuration).addAction; |
@@ -8,3 +8,3 @@ import { Context, UserConfiguration } from '@datadog/browser-core'; | ||
applicationId: string; | ||
beforeSend?: (event: RumEvent) => void; | ||
beforeSend?: (event: RumEvent) => void | boolean; | ||
} | ||
@@ -11,0 +11,0 @@ export declare type RumPublicApi = ReturnType<typeof makeRumPublicApi>; |
@@ -56,6 +56,5 @@ "use strict"; | ||
} | ||
if (configuration.beforeSend) { | ||
browser_core_1.limitModification(serverRumEvent, FIELDS_WITH_SENSITIVE_DATA, configuration.beforeSend); | ||
if (shouldSend(serverRumEvent, configuration.beforeSend)) { | ||
lifeCycle.notify(lifeCycle_1.LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent); | ||
} | ||
lifeCycle.notify(lifeCycle_1.LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent); | ||
} | ||
@@ -65,2 +64,14 @@ }); | ||
exports.startRumAssembly = startRumAssembly; | ||
function shouldSend(event, beforeSend) { | ||
if (beforeSend) { | ||
var result = browser_core_1.limitModification(event, FIELDS_WITH_SENSITIVE_DATA, beforeSend); | ||
if (result === false && event.type !== rawRumEvent_types_1.RumEventType.VIEW) { | ||
return false; | ||
} | ||
if (result === false) { | ||
console.warn("Can't dismiss view events using beforeSend, use onNewLocation instead!"); | ||
} | ||
} | ||
return true; | ||
} | ||
function needToAssembleWithAction(event) { | ||
@@ -67,0 +78,0 @@ return [rawRumEvent_types_1.RumEventType.ERROR, rawRumEvent_types_1.RumEventType.RESOURCE, rawRumEvent_types_1.RumEventType.LONG_TASK].indexOf(event.type) !== -1; |
@@ -72,2 +72,3 @@ "use strict"; | ||
id: currentView.id, | ||
name: currentView.name, | ||
referrer: currentView.referrer, | ||
@@ -74,0 +75,0 @@ url: currentView.location.href, |
@@ -0,1 +1,2 @@ | ||
import { NewLocationListener } from '../../../boot/rum'; | ||
import { LifeCycle } from '../../lifeCycle'; | ||
@@ -7,2 +8,3 @@ import { EventCounts } from '../../trackEventCounts'; | ||
id: string; | ||
name?: string; | ||
location: Location; | ||
@@ -23,2 +25,3 @@ referrer: string; | ||
id: string; | ||
name?: string; | ||
location: Location; | ||
@@ -30,5 +33,5 @@ referrer: string; | ||
export declare const SESSION_KEEP_ALIVE_INTERVAL: number; | ||
export declare function trackViews(location: Location, lifeCycle: LifeCycle): { | ||
export declare function trackViews(location: Location, lifeCycle: LifeCycle, onNewLocation?: NewLocationListener): { | ||
addTiming: (name: string, time?: number) => void; | ||
stop: () => void; | ||
}; |
@@ -14,5 +14,8 @@ "use strict"; | ||
exports.SESSION_KEEP_ALIVE_INTERVAL = 5 * browser_core_1.ONE_MINUTE; | ||
function trackViews(location, lifeCycle) { | ||
function trackViews(location, lifeCycle, onNewLocation) { | ||
var _a; | ||
if (onNewLocation === void 0) { onNewLocation = function () { return undefined; }; } | ||
onNewLocation = wrapOnNewLocation(onNewLocation); | ||
var startOrigin = 0; | ||
var initialView = newView(lifeCycle, location, rawRumEvent_types_1.ViewLoadingType.INITIAL_LOAD, document.referrer, startOrigin); | ||
var initialView = newView(lifeCycle, location, rawRumEvent_types_1.ViewLoadingType.INITIAL_LOAD, document.referrer, startOrigin, (_a = onNewLocation(location)) === null || _a === void 0 ? void 0 : _a.viewName); | ||
var currentView = initialView; | ||
@@ -23,15 +26,15 @@ var stopTimingsTracking = trackTimings_1.trackTimings(lifeCycle, function (timings) { | ||
}).stop; | ||
trackHistory(onLocationChange); | ||
trackHash(onLocationChange); | ||
var stopHistoryTracking = trackHistory(onLocationChange).stop; | ||
var stopHashTracking = trackHash(onLocationChange).stop; | ||
function onLocationChange() { | ||
if (currentView.isDifferentView(location)) { | ||
var _a = onNewLocation(location, currentView.getLocation()) || {}, viewName = _a.viewName, shouldCreateView = _a.shouldCreateView; | ||
if (shouldCreateView || (shouldCreateView === undefined && currentView.isDifferentView(location))) { | ||
// Renew view on location changes | ||
currentView.end(); | ||
currentView.triggerUpdate(); | ||
currentView = newView(lifeCycle, location, rawRumEvent_types_1.ViewLoadingType.ROUTE_CHANGE, currentView.url); | ||
currentView = newView(lifeCycle, location, rawRumEvent_types_1.ViewLoadingType.ROUTE_CHANGE, currentView.url, undefined, viewName); | ||
return; | ||
} | ||
else { | ||
currentView.updateLocation(location); | ||
currentView.triggerUpdate(); | ||
} | ||
currentView.updateLocation(location); | ||
currentView.triggerUpdate(); | ||
} | ||
@@ -60,2 +63,4 @@ // Renew view on session renewal | ||
stop: function () { | ||
stopHistoryTracking(); | ||
stopHashTracking(); | ||
stopTimingsTracking(); | ||
@@ -68,3 +73,3 @@ currentView.end(); | ||
exports.trackViews = trackViews; | ||
function newView(lifeCycle, initialLocation, loadingType, referrer, startTime) { | ||
function newView(lifeCycle, initialLocation, loadingType, referrer, startTime, name) { | ||
if (startTime === void 0) { startTime = performance.now(); } | ||
@@ -121,2 +126,3 @@ // Setup initial values | ||
id: id, | ||
name: name, | ||
loadingTime: loadingTime, | ||
@@ -145,2 +151,5 @@ loadingType: loadingType, | ||
}, | ||
getLocation: function () { | ||
return location; | ||
}, | ||
triggerUpdate: function () { | ||
@@ -185,6 +194,12 @@ // cancel any pending view updates execution | ||
}); | ||
browser_core_1.addEventListener(window, browser_core_1.DOM_EVENT.POP_STATE, onHistoryChange); | ||
var removeListener = browser_core_1.addEventListener(window, browser_core_1.DOM_EVENT.POP_STATE, onHistoryChange).stop; | ||
var stop = function () { | ||
removeListener(); | ||
history.pushState = originalPushState; | ||
history.replaceState = originalReplaceState; | ||
}; | ||
return { stop: stop }; | ||
} | ||
function trackHash(onHashChange) { | ||
browser_core_1.addEventListener(window, browser_core_1.DOM_EVENT.HASH_CHANGE, onHashChange); | ||
return browser_core_1.addEventListener(window, browser_core_1.DOM_EVENT.HASH_CHANGE, onHashChange); | ||
} | ||
@@ -266,2 +281,14 @@ function trackLoadingTime(loadType, callback) { | ||
} | ||
function wrapOnNewLocation(onNewLocation) { | ||
return function (newLocation, oldLocation) { | ||
var result; | ||
try { | ||
result = onNewLocation(newLocation, oldLocation); | ||
} | ||
catch (err) { | ||
console.error('onNewLocation threw an error:', err); | ||
} | ||
return result; | ||
}; | ||
} | ||
//# sourceMappingURL=trackViews.js.map |
@@ -0,5 +1,6 @@ | ||
import { NewLocationListener } from '../../../boot/rum'; | ||
import { LifeCycle } from '../../lifeCycle'; | ||
export declare function startViewCollection(lifeCycle: LifeCycle, location: Location): { | ||
export declare function startViewCollection(lifeCycle: LifeCycle, location: Location, onNewLocation?: NewLocationListener): { | ||
addTiming: (name: string, time?: number) => void; | ||
stop: () => void; | ||
}; |
@@ -8,7 +8,7 @@ "use strict"; | ||
var trackViews_1 = require("./trackViews"); | ||
function startViewCollection(lifeCycle, location) { | ||
function startViewCollection(lifeCycle, location, onNewLocation) { | ||
lifeCycle.subscribe(lifeCycle_1.LifeCycleEventType.VIEW_UPDATED, function (view) { | ||
return lifeCycle.notify(lifeCycle_1.LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processViewUpdate(view)); | ||
}); | ||
return trackViews_1.trackViews(location, lifeCycle); | ||
return trackViews_1.trackViews(location, lifeCycle, onNewLocation); | ||
} | ||
@@ -38,2 +38,3 @@ exports.startViewCollection = startViewCollection; | ||
is_active: view.isActive, | ||
name: view.name, | ||
largest_contentful_paint: browser_core_1.msToNs(view.timings.largestContentfulPaint), | ||
@@ -40,0 +41,0 @@ load_event: browser_core_1.msToNs(view.timings.loadEvent), |
@@ -15,5 +15,5 @@ "use strict"; | ||
}; | ||
var subscription = lifeCycle.subscribe(lifeCycle_1.LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, function (_a) { | ||
var rawRumEvent = _a.rawRumEvent; | ||
switch (rawRumEvent.type) { | ||
var subscription = lifeCycle.subscribe(lifeCycle_1.LifeCycleEventType.RUM_EVENT_COLLECTED, function (_a) { | ||
var type = _a.type; | ||
switch (type) { | ||
case rawRumEvent_types_1.RumEventType.ERROR: | ||
@@ -20,0 +20,0 @@ eventCounts.errorCount += 1; |
@@ -69,2 +69,3 @@ import { Context, ErrorSource, ResourceType } from '@datadog/browser-core'; | ||
is_active: boolean; | ||
name?: string; | ||
error: Count; | ||
@@ -136,2 +137,3 @@ action: Count; | ||
id: string; | ||
name?: string; | ||
url: string; | ||
@@ -138,0 +140,0 @@ referrer: string; |
@@ -115,2 +115,6 @@ /** | ||
/** | ||
* The type of the error | ||
*/ | ||
readonly type?: string; | ||
/** | ||
* Resource properties of the error | ||
@@ -426,3 +430,3 @@ */ | ||
/** | ||
* User custom timings of the view | ||
* User custom timings of the view. As timing name is used as facet path, it must contain only letters, digits, or the characters - _ . @ $ | ||
*/ | ||
@@ -556,2 +560,6 @@ readonly custom_timings?: { | ||
url: string; | ||
/** | ||
* User defined name of the view | ||
*/ | ||
name?: string; | ||
[k: string]: unknown; | ||
@@ -558,0 +566,0 @@ }; |
export var buildEnv = { | ||
buildMode: 'release', | ||
datacenter: 'us', | ||
sdkVersion: '2.5.4', | ||
sdkVersion: '2.5.5', | ||
}; | ||
//# sourceMappingURL=buildEnv.js.map |
@@ -6,3 +6,9 @@ import { Configuration } from '@datadog/browser-core'; | ||
import { RumUserConfiguration } from './rumPublicApi'; | ||
export declare function startRum(userConfiguration: RumUserConfiguration, getCommonContext: () => CommonContext): { | ||
export declare type NewLocationListener = (newLocation: Location, oldLocation?: Location) => undefined | { | ||
shouldCreateView?: boolean; | ||
viewName?: string; | ||
}; | ||
export declare function startRum(userConfiguration: RumUserConfiguration & { | ||
onNewLocation?: NewLocationListener; | ||
}, getCommonContext: () => CommonContext): { | ||
addAction: (action: import("../domain/rumEventsCollection/action/trackActions").CustomAction, savedCommonContext?: CommonContext | undefined) => void; | ||
@@ -17,3 +23,3 @@ addError: ({ error, startTime, context: customerContext, source }: import("../domain/rumEventsCollection/error/errorCollection").ProvidedError, savedCommonContext?: CommonContext | undefined) => void; | ||
}; | ||
export declare function startRumEventCollection(applicationId: string, location: Location, lifeCycle: LifeCycle, configuration: Configuration, session: RumSession, getCommonContext: () => CommonContext): { | ||
export declare function startRumEventCollection(applicationId: string, location: Location, lifeCycle: LifeCycle, configuration: Configuration, session: RumSession, getCommonContext: () => CommonContext, onNewLocation?: NewLocationListener): { | ||
addAction: (action: import("../domain/rumEventsCollection/action/trackActions").CustomAction, savedCommonContext?: CommonContext | undefined) => void; | ||
@@ -20,0 +26,0 @@ addError: ({ error, startTime, context: customerContext, source }: import("../domain/rumEventsCollection/error/errorCollection").ProvidedError, savedCommonContext?: CommonContext | undefined) => void; |
@@ -21,2 +21,5 @@ import { combine, commonInit } from '@datadog/browser-core'; | ||
var session = startRumSession(configuration, lifeCycle); | ||
if (!configuration.isEnabled('onNewLocation')) { | ||
userConfiguration.onNewLocation = undefined; | ||
} | ||
internalMonitoring.setExternalContextProvider(function () { | ||
@@ -27,3 +30,3 @@ return combine({ | ||
}); | ||
var _b = startRumEventCollection(userConfiguration.applicationId, location, lifeCycle, configuration, session, getCommonContext), parentContexts = _b.parentContexts, addError = _b.addError, addAction = _b.addAction, addTiming = _b.addTiming; | ||
var _b = startRumEventCollection(userConfiguration.applicationId, location, lifeCycle, configuration, session, getCommonContext, userConfiguration.onNewLocation), parentContexts = _b.parentContexts, addError = _b.addError, addAction = _b.addAction, addTiming = _b.addTiming; | ||
startRequestCollection(lifeCycle, configuration); | ||
@@ -44,3 +47,3 @@ startPerformanceCollection(lifeCycle, configuration); | ||
} | ||
export function startRumEventCollection(applicationId, location, lifeCycle, configuration, session, getCommonContext) { | ||
export function startRumEventCollection(applicationId, location, lifeCycle, configuration, session, getCommonContext, onNewLocation) { | ||
var parentContexts = startParentContexts(lifeCycle, session); | ||
@@ -51,3 +54,3 @@ var batch = startRumBatch(configuration, lifeCycle); | ||
startResourceCollection(lifeCycle, session); | ||
var addTiming = startViewCollection(lifeCycle, location).addTiming; | ||
var addTiming = startViewCollection(lifeCycle, location, onNewLocation).addTiming; | ||
var addError = startErrorCollection(lifeCycle, configuration).addError; | ||
@@ -54,0 +57,0 @@ var addAction = startActionCollection(lifeCycle, configuration).addAction; |
@@ -8,3 +8,3 @@ import { Context, UserConfiguration } from '@datadog/browser-core'; | ||
applicationId: string; | ||
beforeSend?: (event: RumEvent) => void; | ||
beforeSend?: (event: RumEvent) => void | boolean; | ||
} | ||
@@ -11,0 +11,0 @@ export declare type RumPublicApi = ReturnType<typeof makeRumPublicApi>; |
@@ -53,9 +53,20 @@ import { combine, isEmptyObject, limitModification } from '@datadog/browser-core'; | ||
} | ||
if (configuration.beforeSend) { | ||
limitModification(serverRumEvent, FIELDS_WITH_SENSITIVE_DATA, configuration.beforeSend); | ||
if (shouldSend(serverRumEvent, configuration.beforeSend)) { | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent); | ||
} | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent); | ||
} | ||
}); | ||
} | ||
function shouldSend(event, beforeSend) { | ||
if (beforeSend) { | ||
var result = limitModification(event, FIELDS_WITH_SENSITIVE_DATA, beforeSend); | ||
if (result === false && event.type !== RumEventType.VIEW) { | ||
return false; | ||
} | ||
if (result === false) { | ||
console.warn("Can't dismiss view events using beforeSend, use onNewLocation instead!"); | ||
} | ||
} | ||
return true; | ||
} | ||
function needToAssembleWithAction(event) { | ||
@@ -62,0 +73,0 @@ return [RumEventType.ERROR, RumEventType.RESOURCE, RumEventType.LONG_TASK].indexOf(event.type) !== -1; |
@@ -69,2 +69,3 @@ import { monitor, ONE_MINUTE, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core'; | ||
id: currentView.id, | ||
name: currentView.name, | ||
referrer: currentView.referrer, | ||
@@ -71,0 +72,0 @@ url: currentView.location.href, |
@@ -0,1 +1,2 @@ | ||
import { NewLocationListener } from '../../../boot/rum'; | ||
import { LifeCycle } from '../../lifeCycle'; | ||
@@ -7,2 +8,3 @@ import { EventCounts } from '../../trackEventCounts'; | ||
id: string; | ||
name?: string; | ||
location: Location; | ||
@@ -23,2 +25,3 @@ referrer: string; | ||
id: string; | ||
name?: string; | ||
location: Location; | ||
@@ -30,5 +33,5 @@ referrer: string; | ||
export declare const SESSION_KEEP_ALIVE_INTERVAL: number; | ||
export declare function trackViews(location: Location, lifeCycle: LifeCycle): { | ||
export declare function trackViews(location: Location, lifeCycle: LifeCycle, onNewLocation?: NewLocationListener): { | ||
addTiming: (name: string, time?: number) => void; | ||
stop: () => void; | ||
}; |
@@ -11,5 +11,8 @@ import { __assign } from "tslib"; | ||
export var SESSION_KEEP_ALIVE_INTERVAL = 5 * ONE_MINUTE; | ||
export function trackViews(location, lifeCycle) { | ||
export function trackViews(location, lifeCycle, onNewLocation) { | ||
var _a; | ||
if (onNewLocation === void 0) { onNewLocation = function () { return undefined; }; } | ||
onNewLocation = wrapOnNewLocation(onNewLocation); | ||
var startOrigin = 0; | ||
var initialView = newView(lifeCycle, location, ViewLoadingType.INITIAL_LOAD, document.referrer, startOrigin); | ||
var initialView = newView(lifeCycle, location, ViewLoadingType.INITIAL_LOAD, document.referrer, startOrigin, (_a = onNewLocation(location)) === null || _a === void 0 ? void 0 : _a.viewName); | ||
var currentView = initialView; | ||
@@ -20,15 +23,15 @@ var stopTimingsTracking = trackTimings(lifeCycle, function (timings) { | ||
}).stop; | ||
trackHistory(onLocationChange); | ||
trackHash(onLocationChange); | ||
var stopHistoryTracking = trackHistory(onLocationChange).stop; | ||
var stopHashTracking = trackHash(onLocationChange).stop; | ||
function onLocationChange() { | ||
if (currentView.isDifferentView(location)) { | ||
var _a = onNewLocation(location, currentView.getLocation()) || {}, viewName = _a.viewName, shouldCreateView = _a.shouldCreateView; | ||
if (shouldCreateView || (shouldCreateView === undefined && currentView.isDifferentView(location))) { | ||
// Renew view on location changes | ||
currentView.end(); | ||
currentView.triggerUpdate(); | ||
currentView = newView(lifeCycle, location, ViewLoadingType.ROUTE_CHANGE, currentView.url); | ||
currentView = newView(lifeCycle, location, ViewLoadingType.ROUTE_CHANGE, currentView.url, undefined, viewName); | ||
return; | ||
} | ||
else { | ||
currentView.updateLocation(location); | ||
currentView.triggerUpdate(); | ||
} | ||
currentView.updateLocation(location); | ||
currentView.triggerUpdate(); | ||
} | ||
@@ -57,2 +60,4 @@ // Renew view on session renewal | ||
stop: function () { | ||
stopHistoryTracking(); | ||
stopHashTracking(); | ||
stopTimingsTracking(); | ||
@@ -64,3 +69,3 @@ currentView.end(); | ||
} | ||
function newView(lifeCycle, initialLocation, loadingType, referrer, startTime) { | ||
function newView(lifeCycle, initialLocation, loadingType, referrer, startTime, name) { | ||
if (startTime === void 0) { startTime = performance.now(); } | ||
@@ -117,2 +122,3 @@ // Setup initial values | ||
id: id, | ||
name: name, | ||
loadingTime: loadingTime, | ||
@@ -141,2 +147,5 @@ loadingType: loadingType, | ||
}, | ||
getLocation: function () { | ||
return location; | ||
}, | ||
triggerUpdate: function () { | ||
@@ -181,6 +190,12 @@ // cancel any pending view updates execution | ||
}); | ||
addEventListener(window, DOM_EVENT.POP_STATE, onHistoryChange); | ||
var removeListener = addEventListener(window, DOM_EVENT.POP_STATE, onHistoryChange).stop; | ||
var stop = function () { | ||
removeListener(); | ||
history.pushState = originalPushState; | ||
history.replaceState = originalReplaceState; | ||
}; | ||
return { stop: stop }; | ||
} | ||
function trackHash(onHashChange) { | ||
addEventListener(window, DOM_EVENT.HASH_CHANGE, onHashChange); | ||
return addEventListener(window, DOM_EVENT.HASH_CHANGE, onHashChange); | ||
} | ||
@@ -262,2 +277,14 @@ function trackLoadingTime(loadType, callback) { | ||
} | ||
function wrapOnNewLocation(onNewLocation) { | ||
return function (newLocation, oldLocation) { | ||
var result; | ||
try { | ||
result = onNewLocation(newLocation, oldLocation); | ||
} | ||
catch (err) { | ||
console.error('onNewLocation threw an error:', err); | ||
} | ||
return result; | ||
}; | ||
} | ||
//# sourceMappingURL=trackViews.js.map |
@@ -0,5 +1,6 @@ | ||
import { NewLocationListener } from '../../../boot/rum'; | ||
import { LifeCycle } from '../../lifeCycle'; | ||
export declare function startViewCollection(lifeCycle: LifeCycle, location: Location): { | ||
export declare function startViewCollection(lifeCycle: LifeCycle, location: Location, onNewLocation?: NewLocationListener): { | ||
addTiming: (name: string, time?: number) => void; | ||
stop: () => void; | ||
}; |
@@ -5,7 +5,7 @@ import { getTimestamp, isEmptyObject, mapValues, msToNs } from '@datadog/browser-core'; | ||
import { trackViews } from './trackViews'; | ||
export function startViewCollection(lifeCycle, location) { | ||
export function startViewCollection(lifeCycle, location, onNewLocation) { | ||
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, function (view) { | ||
return lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processViewUpdate(view)); | ||
}); | ||
return trackViews(location, lifeCycle); | ||
return trackViews(location, lifeCycle, onNewLocation); | ||
} | ||
@@ -34,2 +34,3 @@ function processViewUpdate(view) { | ||
is_active: view.isActive, | ||
name: view.name, | ||
largest_contentful_paint: msToNs(view.timings.largestContentfulPaint), | ||
@@ -36,0 +37,0 @@ load_event: msToNs(view.timings.loadEvent), |
@@ -12,5 +12,5 @@ import { noop } from '@datadog/browser-core'; | ||
}; | ||
var subscription = lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, function (_a) { | ||
var rawRumEvent = _a.rawRumEvent; | ||
switch (rawRumEvent.type) { | ||
var subscription = lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, function (_a) { | ||
var type = _a.type; | ||
switch (type) { | ||
case RumEventType.ERROR: | ||
@@ -17,0 +17,0 @@ eventCounts.errorCount += 1; |
@@ -69,2 +69,3 @@ import { Context, ErrorSource, ResourceType } from '@datadog/browser-core'; | ||
is_active: boolean; | ||
name?: string; | ||
error: Count; | ||
@@ -136,2 +137,3 @@ action: Count; | ||
id: string; | ||
name?: string; | ||
url: string; | ||
@@ -138,0 +140,0 @@ referrer: string; |
@@ -115,2 +115,6 @@ /** | ||
/** | ||
* The type of the error | ||
*/ | ||
readonly type?: string; | ||
/** | ||
* Resource properties of the error | ||
@@ -426,3 +430,3 @@ */ | ||
/** | ||
* User custom timings of the view | ||
* User custom timings of the view. As timing name is used as facet path, it must contain only letters, digits, or the characters - _ . @ $ | ||
*/ | ||
@@ -556,2 +560,6 @@ readonly custom_timings?: { | ||
url: string; | ||
/** | ||
* User defined name of the view | ||
*/ | ||
name?: string; | ||
[k: string]: unknown; | ||
@@ -558,0 +566,0 @@ }; |
{ | ||
"name": "@datadog/browser-rum-core", | ||
"version": "2.5.4", | ||
"version": "2.5.5", | ||
"license": "Apache-2.0", | ||
@@ -15,3 +15,3 @@ "main": "cjs/index.js", | ||
"dependencies": { | ||
"@datadog/browser-core": "2.5.4", | ||
"@datadog/browser-core": "2.5.5", | ||
"tslib": "^1.10.0" | ||
@@ -27,3 +27,3 @@ }, | ||
}, | ||
"gitHead": "55c80ce2190bd663ead758834e1f85ac157cd691" | ||
"gitHead": "3dd657412678742c415e4c49815deb96b3dabd53" | ||
} |
@@ -21,3 +21,11 @@ import { combine, commonInit, Configuration } from '@datadog/browser-core' | ||
export function startRum(userConfiguration: RumUserConfiguration, getCommonContext: () => CommonContext) { | ||
export type NewLocationListener = ( | ||
newLocation: Location, | ||
oldLocation?: Location | ||
) => undefined | { shouldCreateView?: boolean; viewName?: string } | ||
export function startRum( | ||
userConfiguration: RumUserConfiguration & { onNewLocation?: NewLocationListener }, | ||
getCommonContext: () => CommonContext | ||
) { | ||
const lifeCycle = new LifeCycle() | ||
@@ -27,2 +35,5 @@ | ||
const session = startRumSession(configuration, lifeCycle) | ||
if (!configuration.isEnabled('onNewLocation')) { | ||
userConfiguration.onNewLocation = undefined | ||
} | ||
@@ -45,3 +56,4 @@ internalMonitoring.setExternalContextProvider(() => | ||
session, | ||
getCommonContext | ||
getCommonContext, | ||
userConfiguration.onNewLocation | ||
) | ||
@@ -73,3 +85,4 @@ | ||
session: RumSession, | ||
getCommonContext: () => CommonContext | ||
getCommonContext: () => CommonContext, | ||
onNewLocation?: NewLocationListener | ||
) { | ||
@@ -81,3 +94,3 @@ const parentContexts = startParentContexts(lifeCycle, session) | ||
startResourceCollection(lifeCycle, session) | ||
const { addTiming } = startViewCollection(lifeCycle, location) | ||
const { addTiming } = startViewCollection(lifeCycle, location, onNewLocation) | ||
const { addError } = startErrorCollection(lifeCycle, configuration) | ||
@@ -84,0 +97,0 @@ const { addAction } = startActionCollection(lifeCycle, configuration) |
@@ -23,3 +23,3 @@ import { | ||
applicationId: string | ||
beforeSend?: (event: RumEvent) => void | ||
beforeSend?: (event: RumEvent) => void | boolean | ||
} | ||
@@ -26,0 +26,0 @@ |
@@ -92,2 +92,52 @@ import { DEFAULT_CONFIGURATION, noop } from '@datadog/browser-core' | ||
}) | ||
it('should allow dismissing events other than views', () => { | ||
beforeSend = () => false | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.ACTION, { | ||
view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' }, | ||
}), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.ERROR, { | ||
view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' }, | ||
}), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK, { | ||
view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' }, | ||
}), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE, { | ||
view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' }, | ||
}), | ||
startTime: 0, | ||
}) | ||
expect(serverRumEvents.length).toBe(0) | ||
}) | ||
it('should not allow dismissing view events', () => { | ||
beforeSend = () => false | ||
const consoleWarnSpy = spyOn(console, 'warn') | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.VIEW, { | ||
view: { id: 'aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee' }, | ||
}), | ||
startTime: 0, | ||
}) | ||
expect(serverRumEvents[0].view.id).toBe('aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee') | ||
expect(consoleWarnSpy).toHaveBeenCalledWith( | ||
`Can't dismiss view events using beforeSend, use onNewLocation instead!` | ||
) | ||
}) | ||
}) | ||
@@ -94,0 +144,0 @@ |
@@ -80,7 +80,5 @@ import { combine, Configuration, Context, isEmptyObject, limitModification } from '@datadog/browser-core' | ||
} | ||
if (configuration.beforeSend) { | ||
limitModification(serverRumEvent, FIELDS_WITH_SENSITIVE_DATA, configuration.beforeSend) | ||
if (shouldSend(serverRumEvent, configuration.beforeSend)) { | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent) | ||
} | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, serverRumEvent) | ||
} | ||
@@ -91,2 +89,15 @@ } | ||
function shouldSend(event: RumEvent & Context, beforeSend?: (event: any) => unknown) { | ||
if (beforeSend) { | ||
const result = limitModification(event, FIELDS_WITH_SENSITIVE_DATA, beforeSend) | ||
if (result === false && event.type !== RumEventType.VIEW) { | ||
return false | ||
} | ||
if (result === false) { | ||
console.warn(`Can't dismiss view events using beforeSend, use onNewLocation instead!`) | ||
} | ||
} | ||
return true | ||
} | ||
function needToAssembleWithAction( | ||
@@ -93,0 +104,0 @@ event: RawRumEvent |
@@ -107,2 +107,9 @@ import { setup, TestSetupBuilder } from '../../test/specHelper' | ||
it('should return the view name with the view', () => { | ||
const { lifeCycle } = setupBuilder.build() | ||
lifeCycle.notify(LifeCycleEventType.VIEW_CREATED, buildViewCreatedEvent({ name: 'Fake name' })) | ||
expect(parentContexts.findView()!.view.name).toBe('Fake name') | ||
}) | ||
it('should update session id only on VIEW_CREATED', () => { | ||
@@ -109,0 +116,0 @@ const { lifeCycle } = setupBuilder.build() |
@@ -100,2 +100,3 @@ import { monitor, ONE_MINUTE, SESSION_TIME_OUT_DELAY } from '@datadog/browser-core' | ||
id: currentView!.id, | ||
name: currentView!.name, | ||
referrer: currentView!.referrer, | ||
@@ -102,0 +103,0 @@ url: currentView!.location.href, |
@@ -1,3 +0,3 @@ | ||
import { DOM_EVENT } from '@datadog/browser-core' | ||
import { createRawRumEvent } from '../../../../test/fixtures' | ||
import { Context, DOM_EVENT } from '@datadog/browser-core' | ||
import { RumEvent } from '../../../../../rum/src' | ||
import { setup, TestSetupBuilder } from '../../../../test/specHelper' | ||
@@ -177,6 +177,3 @@ import { RumEventType, ActionType } from '../../../rawRumEvent.types' | ||
const { lifeCycle, clock } = setupBuilder.build() | ||
const collectedRawRumEvent = { | ||
rawRumEvent: createRawRumEvent(RumEventType.ERROR), | ||
startTime: 0, | ||
} | ||
const collectedRumEvent = { type: RumEventType.ERROR } as RumEvent & Context | ||
lifeCycle.subscribe(LifeCycleEventType.AUTO_ACTION_COMPLETED, pushEvent) | ||
@@ -186,9 +183,9 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, collectedRawRumEvent) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, collectedRumEvent) | ||
clock.tick(BEFORE_PAGE_ACTIVITY_VALIDATION_DELAY) | ||
lifeCycle.notify(LifeCycleEventType.DOM_MUTATED) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, collectedRawRumEvent) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, collectedRumEvent) | ||
clock.tick(EXPIRE_DELAY) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, collectedRawRumEvent) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, collectedRumEvent) | ||
@@ -195,0 +192,0 @@ expect(events.length).toBe(1) |
@@ -1,3 +0,5 @@ | ||
import { createRawRumEvent } from '../../../../test/fixtures' | ||
import { Context } from '../../../../../core/src' | ||
import { RumEvent } from '../../../../../rum/src' | ||
import { setup, TestSetupBuilder } from '../../../../test/specHelper' | ||
import { NewLocationListener } from '../../../boot/rum' | ||
import { | ||
@@ -211,2 +213,146 @@ RumLargestContentfulPaintTiming, | ||
describe('rum use onNewLocation callback to rename/ignore views', () => { | ||
let setupBuilder: TestSetupBuilder | ||
let handler: jasmine.Spy | ||
let getViewEvent: (index: number) => View | ||
let onNewLocation: NewLocationListener | ||
beforeEach(() => { | ||
;({ handler, getViewEvent } = spyOnViews()) | ||
setupBuilder = setup() | ||
.withFakeLocation('/foo') | ||
.beforeBuild(({ location, lifeCycle }) => { | ||
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, handler) | ||
return trackViews(location, lifeCycle, onNewLocation) | ||
}) | ||
}) | ||
afterEach(() => { | ||
setupBuilder.cleanup() | ||
}) | ||
it('should set the view name to the returned viewName', () => { | ||
onNewLocation = (location) => { | ||
switch (location.pathname) { | ||
case '/foo': | ||
return { viewName: 'Foo' } | ||
case '/bar': | ||
return { viewName: 'Bar' } | ||
} | ||
} | ||
setupBuilder.build() | ||
history.pushState({}, '', '/bar') | ||
history.pushState({}, '', '/baz') | ||
expect(getViewEvent(0).name).toBe('Foo') | ||
expect(getViewEvent(2).name).toBe('Bar') | ||
expect(getViewEvent(4).name).toBeUndefined() | ||
}) | ||
it('should allow customer to consider other location changes as new views', () => { | ||
onNewLocation = (location) => ({ viewName: `Foo ${location.search}`, shouldCreateView: true }) | ||
setupBuilder.build() | ||
history.pushState({}, '', '/foo?view=bar') | ||
history.pushState({}, '', '/foo?view=baz') | ||
expect(getViewEvent(0).name).toBe('Foo ') | ||
expect(getViewEvent(2).name).toBe('Foo ?view=bar') | ||
expect(getViewEvent(4).name).toBe('Foo ?view=baz') | ||
}) | ||
it('pass current and old locations to onNewLocation', () => { | ||
onNewLocation = (location, oldLocation) => ({ | ||
viewName: `old: ${oldLocation?.pathname || 'undefined'}, new: ${location.pathname}`, | ||
}) | ||
setupBuilder.build() | ||
history.pushState({}, '', '/bar') | ||
expect(getViewEvent(0).name).toBe('old: undefined, new: /foo') | ||
expect(getViewEvent(2).name).toBe('old: /foo, new: /bar') | ||
}) | ||
it('should use our own new view detection rules when shouldCreateView is undefined', () => { | ||
onNewLocation = (location) => { | ||
switch (location.pathname) { | ||
case '/foo': | ||
return { viewName: 'Foo' } | ||
case '/bar': | ||
return { viewName: 'Bar' } | ||
} | ||
} | ||
setupBuilder.build() | ||
history.pushState({}, '', '/foo') | ||
history.pushState({}, '', '/bar') | ||
history.pushState({}, '', '/bar') | ||
history.pushState({}, '', '/foo') | ||
expect(getViewEvent(0).name).toBe('Foo') | ||
expect(getViewEvent(2).id).toBe(getViewEvent(0).id) | ||
expect(getViewEvent(3).name).toBe('Bar') | ||
expect(getViewEvent(5).id).toBe(getViewEvent(3).id) | ||
expect(getViewEvent(6).name).toBe('Foo') | ||
}) | ||
it('should ignore the view when shouldCreateView is false', () => { | ||
onNewLocation = (location) => { | ||
switch (location.pathname) { | ||
case '/foo': | ||
return { viewName: 'Foo', shouldCreateView: true } | ||
case '/bar': | ||
return { shouldCreateView: false } | ||
case '/baz': | ||
return { viewName: 'Baz', shouldCreateView: true } | ||
} | ||
} | ||
setupBuilder.build() | ||
history.pushState({}, '', '/bar') | ||
history.pushState({}, '', '/baz') | ||
const initialViewId = getViewEvent(0).id | ||
expect(getViewEvent(0).name).toBe('Foo') | ||
expect(getViewEvent(2).name).toBe('Foo') | ||
expect(getViewEvent(2).id).toBe(initialViewId) | ||
expect(getViewEvent(3).name).toBe('Baz') | ||
expect(getViewEvent(3).id).not.toBe(initialViewId) | ||
}) | ||
it('should create the initial view even when shouldCreateView is false', () => { | ||
onNewLocation = (location) => { | ||
if (location.pathname === '/foo') { | ||
return { shouldCreateView: false } | ||
} | ||
if (location.pathname === '/bar') { | ||
return { shouldCreateView: true } | ||
} | ||
} | ||
setupBuilder.build() | ||
history.pushState({}, '', '/bar') | ||
history.pushState({}, '', '/foo') | ||
expect(getViewEvent(0).location.pathname).toBe('/foo') | ||
expect(getViewEvent(2).location.pathname).toBe('/bar') | ||
expect(getViewEvent(4)).toBeUndefined() | ||
}) | ||
it('should catch thrown errors', () => { | ||
const fooError = 'Error on /foo path' | ||
const barError = 'Error on /bar path' | ||
onNewLocation = (location) => { | ||
if (location.pathname === '/foo') { | ||
throw fooError | ||
} | ||
if (location.pathname === '/bar') { | ||
throw barError | ||
} | ||
return undefined | ||
} | ||
const consoleErrorSpy = spyOn(console, 'error') | ||
setupBuilder.build() | ||
expect(consoleErrorSpy).toHaveBeenCalledWith('onNewLocation threw an error:', fooError) | ||
history.pushState({}, '', '/bar') | ||
expect(consoleErrorSpy).toHaveBeenCalledWith('onNewLocation threw an error:', barError) | ||
}) | ||
}) | ||
describe('rum view referrer', () => { | ||
@@ -626,10 +772,4 @@ let setupBuilder: TestSetupBuilder | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.ERROR), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.ERROR), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.ERROR } as RumEvent & Context) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.ERROR } as RumEvent & Context) | ||
history.pushState({}, '', '/bar') | ||
@@ -647,6 +787,3 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.LONG_TASK), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.LONG_TASK } as RumEvent & Context) | ||
history.pushState({}, '', '/bar') | ||
@@ -664,6 +801,3 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.RESOURCE } as RumEvent & Context) | ||
history.pushState({}, '', '/bar') | ||
@@ -681,6 +815,3 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.ACTION), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.ACTION } as RumEvent & Context) | ||
history.pushState({}, '', '/bar') | ||
@@ -698,6 +829,3 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.RESOURCE } as RumEvent & Context) | ||
history.pushState({}, '', '/bar') | ||
@@ -709,10 +837,4 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.RESOURCE } as RumEvent & Context) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.RESOURCE } as RumEvent & Context) | ||
history.pushState({}, '', '/baz') | ||
@@ -735,6 +857,3 @@ | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.RESOURCE } as RumEvent & Context) | ||
@@ -758,6 +877,3 @@ expect(getHandledCount()).toEqual(1) | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: createRawRumEvent(RumEventType.RESOURCE), | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type: RumEventType.RESOURCE } as RumEvent & Context) | ||
@@ -764,0 +880,0 @@ expect(getHandledCount()).toEqual(1) |
import { addEventListener, DOM_EVENT, generateUUID, monitor, noop, ONE_MINUTE, throttle } from '@datadog/browser-core' | ||
import { NewLocationListener } from '../../../boot/rum' | ||
@@ -12,2 +13,3 @@ import { supportPerformanceTimingEvent } from '../../../browser/performanceCollection' | ||
id: string | ||
name?: string | ||
location: Location | ||
@@ -29,2 +31,3 @@ referrer: string | ||
id: string | ||
name?: string | ||
location: Location | ||
@@ -38,5 +41,17 @@ referrer: string | ||
export function trackViews(location: Location, lifeCycle: LifeCycle) { | ||
export function trackViews( | ||
location: Location, | ||
lifeCycle: LifeCycle, | ||
onNewLocation: NewLocationListener = () => undefined | ||
) { | ||
onNewLocation = wrapOnNewLocation(onNewLocation) | ||
const startOrigin = 0 | ||
const initialView = newView(lifeCycle, location, ViewLoadingType.INITIAL_LOAD, document.referrer, startOrigin) | ||
const initialView = newView( | ||
lifeCycle, | ||
location, | ||
ViewLoadingType.INITIAL_LOAD, | ||
document.referrer, | ||
startOrigin, | ||
onNewLocation(location)?.viewName | ||
) | ||
let currentView = initialView | ||
@@ -49,15 +64,16 @@ | ||
trackHistory(onLocationChange) | ||
trackHash(onLocationChange) | ||
const { stop: stopHistoryTracking } = trackHistory(onLocationChange) | ||
const { stop: stopHashTracking } = trackHash(onLocationChange) | ||
function onLocationChange() { | ||
if (currentView.isDifferentView(location)) { | ||
const { viewName, shouldCreateView } = onNewLocation(location, currentView.getLocation()) || {} | ||
if (shouldCreateView || (shouldCreateView === undefined && currentView.isDifferentView(location))) { | ||
// Renew view on location changes | ||
currentView.end() | ||
currentView.triggerUpdate() | ||
currentView = newView(lifeCycle, location, ViewLoadingType.ROUTE_CHANGE, currentView.url) | ||
} else { | ||
currentView.updateLocation(location) | ||
currentView.triggerUpdate() | ||
currentView = newView(lifeCycle, location, ViewLoadingType.ROUTE_CHANGE, currentView.url, undefined, viewName) | ||
return | ||
} | ||
currentView.updateLocation(location) | ||
currentView.triggerUpdate() | ||
} | ||
@@ -92,2 +108,4 @@ | ||
stop: () => { | ||
stopHistoryTracking() | ||
stopHashTracking() | ||
stopTimingsTracking() | ||
@@ -105,3 +123,4 @@ currentView.end() | ||
referrer: string, | ||
startTime: number = performance.now() | ||
startTime: number = performance.now(), | ||
name?: string | ||
) { | ||
@@ -169,2 +188,3 @@ // Setup initial values | ||
id, | ||
name, | ||
loadingTime, | ||
@@ -196,2 +216,5 @@ loadingType, | ||
}, | ||
getLocation() { | ||
return location | ||
}, | ||
triggerUpdate() { | ||
@@ -238,7 +261,13 @@ // cancel any pending view updates execution | ||
}) | ||
addEventListener(window, DOM_EVENT.POP_STATE, onHistoryChange) | ||
const { stop: removeListener } = addEventListener(window, DOM_EVENT.POP_STATE, onHistoryChange) | ||
const stop = () => { | ||
removeListener() | ||
history.pushState = originalPushState | ||
history.replaceState = originalReplaceState | ||
} | ||
return { stop } | ||
} | ||
function trackHash(onHashChange: () => void) { | ||
addEventListener(window, DOM_EVENT.HASH_CHANGE, onHashChange) | ||
return addEventListener(window, DOM_EVENT.HASH_CHANGE, onHashChange) | ||
} | ||
@@ -328,1 +357,13 @@ | ||
} | ||
function wrapOnNewLocation(onNewLocation: NewLocationListener): NewLocationListener { | ||
return (newLocation, oldLocation) => { | ||
let result | ||
try { | ||
result = onNewLocation(newLocation, oldLocation) | ||
} catch (err) { | ||
console.error('onNewLocation threw an error:', err) | ||
} | ||
return result | ||
} | ||
} |
@@ -41,2 +41,3 @@ import { setup, TestSetupBuilder } from '../../../../test/specHelper' | ||
id: 'xxx', | ||
name: undefined, | ||
isActive: false, | ||
@@ -87,2 +88,3 @@ loadingTime: 20, | ||
is_active: false, | ||
name: undefined, | ||
largest_contentful_paint: 10 * 1e6, | ||
@@ -89,0 +91,0 @@ load_event: 10 * 1e6, |
import { getTimestamp, isEmptyObject, mapValues, msToNs } from '@datadog/browser-core' | ||
import { NewLocationListener } from '../../../boot/rum' | ||
import { RawRumViewEvent, RumEventType } from '../../../rawRumEvent.types' | ||
@@ -6,3 +7,3 @@ import { LifeCycle, LifeCycleEventType } from '../../lifeCycle' | ||
export function startViewCollection(lifeCycle: LifeCycle, location: Location) { | ||
export function startViewCollection(lifeCycle: LifeCycle, location: Location, onNewLocation?: NewLocationListener) { | ||
lifeCycle.subscribe(LifeCycleEventType.VIEW_UPDATED, (view) => | ||
@@ -12,3 +13,3 @@ lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, processViewUpdate(view)) | ||
return trackViews(location, lifeCycle) | ||
return trackViews(location, lifeCycle, onNewLocation) | ||
} | ||
@@ -38,2 +39,3 @@ | ||
is_active: view.isActive, | ||
name: view.name, | ||
largest_contentful_paint: msToNs(view.timings.largestContentfulPaint), | ||
@@ -40,0 +42,0 @@ load_event: msToNs(view.timings.loadEvent), |
@@ -1,3 +0,4 @@ | ||
import { objectValues } from '@datadog/browser-core' | ||
import { RawRumEvent, RumEventType } from '../rawRumEvent.types' | ||
import { Context, objectValues } from '@datadog/browser-core' | ||
import { RumEvent } from '../../../rum/src' | ||
import { RumEventType } from '../rawRumEvent.types' | ||
import { LifeCycle, LifeCycleEventType } from './lifeCycle' | ||
@@ -14,6 +15,3 @@ import { EventCounts, trackEventCounts } from './trackEventCounts' | ||
function notifyCollectedRawRumEvent(type: RumEventType) { | ||
lifeCycle.notify(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, { | ||
rawRumEvent: ({ type } as unknown) as RawRumEvent, | ||
startTime: 0, | ||
}) | ||
lifeCycle.notify(LifeCycleEventType.RUM_EVENT_COLLECTED, { type } as RumEvent & Context) | ||
} | ||
@@ -20,0 +18,0 @@ |
@@ -20,4 +20,4 @@ import { noop } from '@datadog/browser-core' | ||
const subscription = lifeCycle.subscribe(LifeCycleEventType.RAW_RUM_EVENT_COLLECTED, ({ rawRumEvent }): void => { | ||
switch (rawRumEvent.type) { | ||
const subscription = lifeCycle.subscribe(LifeCycleEventType.RUM_EVENT_COLLECTED, ({ type }): void => { | ||
switch (type) { | ||
case RumEventType.ERROR: | ||
@@ -24,0 +24,0 @@ eventCounts.errorCount += 1 |
@@ -74,2 +74,3 @@ import { Context, ErrorSource, ResourceType } from '@datadog/browser-core' | ||
is_active: boolean | ||
name?: string | ||
error: Count | ||
@@ -155,2 +156,3 @@ action: Count | ||
id: string | ||
name?: string | ||
url: string | ||
@@ -157,0 +159,0 @@ referrer: string |
@@ -117,2 +117,6 @@ /* eslint-disable */ | ||
/** | ||
* The type of the error | ||
*/ | ||
readonly type?: string | ||
/** | ||
* Resource properties of the error | ||
@@ -464,3 +468,3 @@ */ | ||
/** | ||
* User custom timings of the view | ||
* User custom timings of the view. As timing name is used as facet path, it must contain only letters, digits, or the characters - _ . @ $ | ||
*/ | ||
@@ -595,2 +599,6 @@ readonly custom_timings?: { | ||
url: string | ||
/** | ||
* User defined name of the view | ||
*/ | ||
name?: string | ||
[k: string]: unknown | ||
@@ -597,0 +605,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
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
764563
15928
+ Added@datadog/browser-core@2.5.5(transitive)
- Removed@datadog/browser-core@2.5.4(transitive)
Updated@datadog/browser-core@2.5.5