Socket
Socket
Sign inDemoInstall

@datadog/browser-core

Package Overview
Dependencies
0
Maintainers
1
Versions
246
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 4.34.1 to 4.34.2

2

cjs/boot/init.js

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

var publicApi = (0, utils_1.assign)({
version: "4.34.1",
version: "4.34.2",
// This API method is intentionally not monitored, since the only thing executed is the

@@ -12,0 +12,0 @@ // user-provided 'callback'. All SDK usages executed in the callback should be monitored, and

@@ -5,2 +5,3 @@ import { Observable } from '../tools/observable';

readonly UNLOADING: "before_unload";
readonly PAGEHIDE: "page_hide";
readonly FROZEN: "page_frozen";

@@ -7,0 +8,0 @@ };

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.isPageExitReason = exports.createPageExitObservable = exports.PageExitReason = void 0;
var configuration_1 = require("../domain/configuration");
var observable_1 = require("../tools/observable");

@@ -10,2 +11,3 @@ var utils_1 = require("../tools/utils");

UNLOADING: 'before_unload',
PAGEHIDE: 'page_hide',
FROZEN: 'page_frozen',

@@ -15,5 +17,12 @@ };

var observable = new observable_1.Observable(function () {
var stopListeners = (0, addEventListener_1.addEventListeners)(window, ["visibilitychange" /* VISIBILITY_CHANGE */, "freeze" /* FREEZE */], function (event) {
if (event.type === "visibilitychange" /* VISIBILITY_CHANGE */ && document.visibilityState === 'hidden') {
var pagehideEnabled = (0, configuration_1.isExperimentalFeatureEnabled)('pagehide');
var stopListeners = (0, addEventListener_1.addEventListeners)(window, ["visibilitychange" /* VISIBILITY_CHANGE */, "freeze" /* FREEZE */, "pagehide" /* PAGE_HIDE */], function (event) {
if (event.type === "pagehide" /* PAGE_HIDE */ && pagehideEnabled) {
/**
* Only event that detect page unload events while being compatible with the back/forward cache (bfcache)
*/
observable.notify({ reason: exports.PageExitReason.PAGEHIDE });
}
else if (event.type === "visibilitychange" /* VISIBILITY_CHANGE */ && document.visibilityState === 'hidden') {
/**
* Only event that guarantee to fire on mobile devices when the page transitions to background state

@@ -32,10 +41,8 @@ * (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.

}, { capture: true }).stop;
/**
* Safari does not support yet to send a request during:
* - a visibility change during doc unload (cf: https://bugs.webkit.org/show_bug.cgi?id=194897)
* - a page hide transition (cf: https://bugs.webkit.org/show_bug.cgi?id=188329)
*/
var stopBeforeUnloadListener = (0, addEventListener_1.addEventListener)(window, "beforeunload" /* BEFORE_UNLOAD */, function () {
observable.notify({ reason: exports.PageExitReason.UNLOADING });
}).stop;
var stopBeforeUnloadListener = utils_1.noop;
if (!pagehideEnabled) {
stopBeforeUnloadListener = (0, addEventListener_1.addEventListener)(window, "beforeunload" /* BEFORE_UNLOAD */, function () {
observable.notify({ reason: exports.PageExitReason.UNLOADING });
}).stop;
}
return function () {

@@ -42,0 +49,0 @@ stopListeners();

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

import type { RetryInfo } from '../../transport';
import type { RetryInfo, FlushReason } from '../../transport';
import type { InitConfiguration } from './configuration';

@@ -11,5 +11,5 @@ export declare const ENDPOINTS: {

export declare function createEndpointBuilder(initConfiguration: InitConfiguration, endpointType: EndpointType, configurationTags: string[]): {
build(api: 'xhr' | 'fetch' | 'beacon', retry?: RetryInfo | undefined): string;
build(api: 'xhr' | 'fetch' | 'beacon', flushReason?: FlushReason | undefined, retry?: RetryInfo | undefined): string;
urlPrefix: string;
endpointType: "logs" | "rum" | "sessionReplay";
};

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

var intakeSites_1 = require("./intakeSites");
var experimentalFeatures_1 = require("./experimentalFeatures");
exports.ENDPOINTS = {

@@ -22,4 +23,4 @@ logs: 'logs',

return {
build: function (api, retry) {
var parameters = buildEndpointParameters(initConfiguration, endpointType, configurationTags, api, retry);
build: function (api, flushReason, retry) {
var parameters = buildEndpointParameters(initConfiguration, endpointType, configurationTags, api, flushReason, retry);
return buildUrlWithParameters(parameters);

@@ -68,5 +69,8 @@ },

*/
function buildEndpointParameters(_a, endpointType, configurationTags, api, retry) {
function buildEndpointParameters(_a, endpointType, configurationTags, api, flushReason, retry) {
var clientToken = _a.clientToken, internalAnalyticsSubdomain = _a.internalAnalyticsSubdomain;
var tags = ["sdk_version:".concat("4.34.1"), "api:".concat(api)].concat(configurationTags);
var tags = ["sdk_version:".concat("4.34.2"), "api:".concat(api)].concat(configurationTags);
if (flushReason && (0, experimentalFeatures_1.isExperimentalFeatureEnabled)('collect_flush_reason')) {
tags.push("flush_reason:".concat(flushReason));
}
if (retry) {

@@ -79,3 +83,3 @@ tags.push("retry_count:".concat(retry.count), "retry_after:".concat(retry.lastFailureStatus));

"dd-api-key=".concat(clientToken),
"dd-evp-origin-version=".concat(encodeURIComponent("4.34.1")),
"dd-evp-origin-version=".concat(encodeURIComponent("4.34.2")),
'dd-evp-origin=browser',

@@ -82,0 +86,0 @@ "dd-request-id=".concat((0, utils_1.generateUUID)()),

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

service: telemetryService,
version: "4.34.1",
version: "4.34.2",
source: 'browser',

@@ -50,0 +50,0 @@ _dd: {

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.instrumentSetter = exports.instrumentMethodAndCallOriginal = exports.instrumentMethod = void 0;
var getZoneJsOriginalValue_1 = require("./getZoneJsOriginalValue");
var monitor_1 = require("./monitor");

@@ -56,2 +57,5 @@ var utils_1 = require("./utils");

}
// Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular
// component, see issue RUMF-1443
var setTimeout = (0, getZoneJsOriginalValue_1.getZoneJsOriginalValue)(window, 'setTimeout');
var instrumentation = function (thisObject, value) {

@@ -58,0 +62,0 @@ // put hooked setter into event loop to avoid of set latency

@@ -9,2 +9,3 @@ import type { Context } from '../tools/context';

}
export declare type FlushReason = 'batch_duration_limit' | 'batch_bytes_limit' | 'before_unload' | 'page_hide' | 'visibility_hidden' | 'page_frozen';
export declare class Batch {

@@ -25,3 +26,3 @@ private request;

upsert(message: Context, key: string): void;
flush(sendFn?: (payload: import("./httpRequest").Payload) => void): void;
flush(flushReason: FlushReason, sendFn?: (payload: import("./httpRequest").Payload) => void): void;
private addOrUpdate;

@@ -28,0 +29,0 @@ private process;

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

this.bufferMessagesCount = 0;
pageExitObservable.subscribe(function () { return _this.flush(_this.request.sendOnExit); });
pageExitObservable.subscribe(function (event) { return _this.flush(event.reason, _this.request.sendOnExit); });
this.flushPeriodically();

@@ -32,3 +32,3 @@ }

};
Batch.prototype.flush = function (sendFn) {
Batch.prototype.flush = function (flushReason, sendFn) {
if (sendFn === void 0) { sendFn = this.request.send; }

@@ -46,3 +46,3 @@ if (this.bufferMessagesCount !== 0) {

this.bufferMessagesCount = 0;
sendFn({ data: messages.join('\n'), bytesCount: bytesCount });
sendFn({ data: messages.join('\n'), bytesCount: bytesCount, flushReason: flushReason });
}

@@ -60,7 +60,7 @@ };

if (this.willReachedBytesLimitWith(messageBytesCount)) {
this.flush();
this.flush('batch_bytes_limit');
}
this.push(processedMessage, messageBytesCount, key);
if (this.isFull()) {
this.flush();
this.flush('batch_bytes_limit');
}

@@ -110,3 +110,3 @@ };

setTimeout((0, monitor_1.monitor)(function () {
_this.flush();
_this.flush('batch_duration_limit');
_this.flushPeriodically();

@@ -113,0 +113,0 @@ }), this.flushTimeout);

import type { EndpointBuilder } from '../domain/configuration';
import type { Context } from '../tools/context';
import type { RawError } from '../tools/error';
import type { FlushReason } from './batch';
/**

@@ -21,2 +22,3 @@ * Use POST request without content type to:

retry?: RetryInfo;
flushReason?: FlushReason;
}

@@ -35,3 +37,3 @@ export interface RetryInfo {

};
export declare function fetchKeepAliveStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, { data, bytesCount, retry }: Payload, onResponse?: (r: HttpResponse) => void): void;
export declare function fetchKeepAliveStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, { data, bytesCount, flushReason, retry }: Payload, onResponse?: (r: HttpResponse) => void): void;
export declare function sendXHR(url: string, data: Payload['data'], onResponse?: (r: HttpResponse) => void): void;

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

function sendBeaconStrategy(endpointBuilder, bytesLimit, _a) {
var data = _a.data, bytesCount = _a.bytesCount;
var data = _a.data, bytesCount = _a.bytesCount, flushReason = _a.flushReason;
var canUseBeacon = !!navigator.sendBeacon && bytesCount < bytesLimit;
if (canUseBeacon) {
try {
var beaconUrl = endpointBuilder.build('beacon');
var beaconUrl = endpointBuilder.build('beacon', flushReason);
var isQueued = navigator.sendBeacon(beaconUrl, data);

@@ -42,3 +42,3 @@ if (isQueued) {

}
var xhrUrl = endpointBuilder.build('xhr');
var xhrUrl = endpointBuilder.build('xhr', flushReason);
sendXHR(xhrUrl, data);

@@ -54,8 +54,8 @@ }

function fetchKeepAliveStrategy(endpointBuilder, bytesLimit, _a, onResponse) {
var data = _a.data, bytesCount = _a.bytesCount, retry = _a.retry;
var data = _a.data, bytesCount = _a.bytesCount, flushReason = _a.flushReason, retry = _a.retry;
var canUseKeepAlive = isKeepAliveSupported() && bytesCount < bytesLimit;
if (canUseKeepAlive) {
var fetchUrl = endpointBuilder.build('fetch', retry);
var fetchUrl = endpointBuilder.build('fetch', flushReason, retry);
fetch(fetchUrl, { method: 'POST', body: data, keepalive: true, mode: 'cors' }).then((0, monitor_1.monitor)(function (response) { return onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: response.status, type: response.type }); }), (0, monitor_1.monitor)(function () {
var xhrUrl = endpointBuilder.build('xhr', retry);
var xhrUrl = endpointBuilder.build('xhr', flushReason, retry);
// failed to queue the request

@@ -66,3 +66,3 @@ sendXHR(xhrUrl, data, onResponse);

else {
var xhrUrl = endpointBuilder.build('xhr', retry);
var xhrUrl = endpointBuilder.build('xhr', flushReason, retry);
sendXHR(xhrUrl, data, onResponse);

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

export { HttpRequest, createHttpRequest, Payload, RetryInfo } from './httpRequest';
export { Batch, BatchFlushEvent } from './batch';
export { Batch, BatchFlushEvent, FlushReason } from './batch';
export { canUseEventBridge, getEventBridge, BrowserWindowWithEventBridge } from './eventBridge';
export { startBatchWithReplica } from './startBatchWithReplica';

@@ -6,3 +6,3 @@ import { catchUserErrors } from '../tools/catchUserErrors';

var publicApi = assign({
version: "4.34.1",
version: "4.34.2",
// This API method is intentionally not monitored, since the only thing executed is the

@@ -9,0 +9,0 @@ // user-provided 'callback'. All SDK usages executed in the callback should be monitored, and

@@ -5,2 +5,3 @@ import { Observable } from '../tools/observable';

readonly UNLOADING: "before_unload";
readonly PAGEHIDE: "page_hide";
readonly FROZEN: "page_frozen";

@@ -7,0 +8,0 @@ };

@@ -0,7 +1,9 @@

import { isExperimentalFeatureEnabled } from '../domain/configuration';
import { Observable } from '../tools/observable';
import { includes, objectValues } from '../tools/utils';
import { addEventListener, addEventListeners } from './addEventListener';
import { includes, noop, objectValues } from '../tools/utils';
import { addEventListeners, addEventListener } from './addEventListener';
export var PageExitReason = {
HIDDEN: 'visibility_hidden',
UNLOADING: 'before_unload',
PAGEHIDE: 'page_hide',
FROZEN: 'page_frozen',

@@ -11,5 +13,12 @@ };

var observable = new Observable(function () {
var stopListeners = addEventListeners(window, ["visibilitychange" /* VISIBILITY_CHANGE */, "freeze" /* FREEZE */], function (event) {
if (event.type === "visibilitychange" /* VISIBILITY_CHANGE */ && document.visibilityState === 'hidden') {
var pagehideEnabled = isExperimentalFeatureEnabled('pagehide');
var stopListeners = addEventListeners(window, ["visibilitychange" /* VISIBILITY_CHANGE */, "freeze" /* FREEZE */, "pagehide" /* PAGE_HIDE */], function (event) {
if (event.type === "pagehide" /* PAGE_HIDE */ && pagehideEnabled) {
/**
* Only event that detect page unload events while being compatible with the back/forward cache (bfcache)
*/
observable.notify({ reason: PageExitReason.PAGEHIDE });
}
else if (event.type === "visibilitychange" /* VISIBILITY_CHANGE */ && document.visibilityState === 'hidden') {
/**
* Only event that guarantee to fire on mobile devices when the page transitions to background state

@@ -28,10 +37,8 @@ * (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.

}, { capture: true }).stop;
/**
* Safari does not support yet to send a request during:
* - a visibility change during doc unload (cf: https://bugs.webkit.org/show_bug.cgi?id=194897)
* - a page hide transition (cf: https://bugs.webkit.org/show_bug.cgi?id=188329)
*/
var stopBeforeUnloadListener = addEventListener(window, "beforeunload" /* BEFORE_UNLOAD */, function () {
observable.notify({ reason: PageExitReason.UNLOADING });
}).stop;
var stopBeforeUnloadListener = noop;
if (!pagehideEnabled) {
stopBeforeUnloadListener = addEventListener(window, "beforeunload" /* BEFORE_UNLOAD */, function () {
observable.notify({ reason: PageExitReason.UNLOADING });
}).stop;
}
return function () {

@@ -38,0 +45,0 @@ stopListeners();

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

import type { RetryInfo } from '../../transport';
import type { RetryInfo, FlushReason } from '../../transport';
import type { InitConfiguration } from './configuration';

@@ -11,5 +11,5 @@ export declare const ENDPOINTS: {

export declare function createEndpointBuilder(initConfiguration: InitConfiguration, endpointType: EndpointType, configurationTags: string[]): {
build(api: 'xhr' | 'fetch' | 'beacon', retry?: RetryInfo | undefined): string;
build(api: 'xhr' | 'fetch' | 'beacon', flushReason?: FlushReason | undefined, retry?: RetryInfo | undefined): string;
urlPrefix: string;
endpointType: "logs" | "rum" | "sessionReplay";
};

@@ -5,2 +5,3 @@ import { timeStampNow } from '../../tools/timeUtils';

import { INTAKE_SITE_AP1, INTAKE_SITE_US1 } from './intakeSites';
import { isExperimentalFeatureEnabled } from './experimentalFeatures';
export var ENDPOINTS = {

@@ -19,4 +20,4 @@ logs: 'logs',

return {
build: function (api, retry) {
var parameters = buildEndpointParameters(initConfiguration, endpointType, configurationTags, api, retry);
build: function (api, flushReason, retry) {
var parameters = buildEndpointParameters(initConfiguration, endpointType, configurationTags, api, flushReason, retry);
return buildUrlWithParameters(parameters);

@@ -64,5 +65,8 @@ },

*/
function buildEndpointParameters(_a, endpointType, configurationTags, api, retry) {
function buildEndpointParameters(_a, endpointType, configurationTags, api, flushReason, retry) {
var clientToken = _a.clientToken, internalAnalyticsSubdomain = _a.internalAnalyticsSubdomain;
var tags = ["sdk_version:".concat("4.34.1"), "api:".concat(api)].concat(configurationTags);
var tags = ["sdk_version:".concat("4.34.2"), "api:".concat(api)].concat(configurationTags);
if (flushReason && isExperimentalFeatureEnabled('collect_flush_reason')) {
tags.push("flush_reason:".concat(flushReason));
}
if (retry) {

@@ -75,3 +79,3 @@ tags.push("retry_count:".concat(retry.count), "retry_after:".concat(retry.lastFailureStatus));

"dd-api-key=".concat(clientToken),
"dd-evp-origin-version=".concat(encodeURIComponent("4.34.1")),
"dd-evp-origin-version=".concat(encodeURIComponent("4.34.2")),
'dd-evp-origin=browser',

@@ -78,0 +82,0 @@ "dd-request-id=".concat(generateUUID()),

@@ -44,3 +44,3 @@ import { ConsoleApiName } from '../../tools/display';

service: telemetryService,
version: "4.34.1",
version: "4.34.2",
source: 'browser',

@@ -47,0 +47,0 @@ _dd: {

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

import { getZoneJsOriginalValue } from './getZoneJsOriginalValue';
import { callMonitored, monitor } from './monitor';

@@ -51,2 +52,5 @@ import { noop } from './utils';

}
// Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular
// component, see issue RUMF-1443
var setTimeout = getZoneJsOriginalValue(window, 'setTimeout');
var instrumentation = function (thisObject, value) {

@@ -53,0 +57,0 @@ // put hooked setter into event loop to avoid of set latency

@@ -9,2 +9,3 @@ import type { Context } from '../tools/context';

}
export declare type FlushReason = 'batch_duration_limit' | 'batch_bytes_limit' | 'before_unload' | 'page_hide' | 'visibility_hidden' | 'page_frozen';
export declare class Batch {

@@ -25,3 +26,3 @@ private request;

upsert(message: Context, key: string): void;
flush(sendFn?: (payload: import("./httpRequest").Payload) => void): void;
flush(flushReason: FlushReason, sendFn?: (payload: import("./httpRequest").Payload) => void): void;
private addOrUpdate;

@@ -28,0 +29,0 @@ private process;

@@ -19,3 +19,3 @@ import { display } from '../tools/display';

this.bufferMessagesCount = 0;
pageExitObservable.subscribe(function () { return _this.flush(_this.request.sendOnExit); });
pageExitObservable.subscribe(function (event) { return _this.flush(event.reason, _this.request.sendOnExit); });
this.flushPeriodically();

@@ -29,3 +29,3 @@ }

};
Batch.prototype.flush = function (sendFn) {
Batch.prototype.flush = function (flushReason, sendFn) {
if (sendFn === void 0) { sendFn = this.request.send; }

@@ -43,3 +43,3 @@ if (this.bufferMessagesCount !== 0) {

this.bufferMessagesCount = 0;
sendFn({ data: messages.join('\n'), bytesCount: bytesCount });
sendFn({ data: messages.join('\n'), bytesCount: bytesCount, flushReason: flushReason });
}

@@ -57,7 +57,7 @@ };

if (this.willReachedBytesLimitWith(messageBytesCount)) {
this.flush();
this.flush('batch_bytes_limit');
}
this.push(processedMessage, messageBytesCount, key);
if (this.isFull()) {
this.flush();
this.flush('batch_bytes_limit');
}

@@ -107,3 +107,3 @@ };

setTimeout(monitor(function () {
_this.flush();
_this.flush('batch_duration_limit');
_this.flushPeriodically();

@@ -110,0 +110,0 @@ }), this.flushTimeout);

import type { EndpointBuilder } from '../domain/configuration';
import type { Context } from '../tools/context';
import type { RawError } from '../tools/error';
import type { FlushReason } from './batch';
/**

@@ -21,2 +22,3 @@ * Use POST request without content type to:

retry?: RetryInfo;
flushReason?: FlushReason;
}

@@ -35,3 +37,3 @@ export interface RetryInfo {

};
export declare function fetchKeepAliveStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, { data, bytesCount, retry }: Payload, onResponse?: (r: HttpResponse) => void): void;
export declare function fetchKeepAliveStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, { data, bytesCount, flushReason, retry }: Payload, onResponse?: (r: HttpResponse) => void): void;
export declare function sendXHR(url: string, data: Payload['data'], onResponse?: (r: HttpResponse) => void): void;

@@ -23,7 +23,7 @@ import { addTelemetryError } from '../domain/telemetry';

function sendBeaconStrategy(endpointBuilder, bytesLimit, _a) {
var data = _a.data, bytesCount = _a.bytesCount;
var data = _a.data, bytesCount = _a.bytesCount, flushReason = _a.flushReason;
var canUseBeacon = !!navigator.sendBeacon && bytesCount < bytesLimit;
if (canUseBeacon) {
try {
var beaconUrl = endpointBuilder.build('beacon');
var beaconUrl = endpointBuilder.build('beacon', flushReason);
var isQueued = navigator.sendBeacon(beaconUrl, data);

@@ -38,3 +38,3 @@ if (isQueued) {

}
var xhrUrl = endpointBuilder.build('xhr');
var xhrUrl = endpointBuilder.build('xhr', flushReason);
sendXHR(xhrUrl, data);

@@ -50,8 +50,8 @@ }

export function fetchKeepAliveStrategy(endpointBuilder, bytesLimit, _a, onResponse) {
var data = _a.data, bytesCount = _a.bytesCount, retry = _a.retry;
var data = _a.data, bytesCount = _a.bytesCount, flushReason = _a.flushReason, retry = _a.retry;
var canUseKeepAlive = isKeepAliveSupported() && bytesCount < bytesLimit;
if (canUseKeepAlive) {
var fetchUrl = endpointBuilder.build('fetch', retry);
var fetchUrl = endpointBuilder.build('fetch', flushReason, retry);
fetch(fetchUrl, { method: 'POST', body: data, keepalive: true, mode: 'cors' }).then(monitor(function (response) { return onResponse === null || onResponse === void 0 ? void 0 : onResponse({ status: response.status, type: response.type }); }), monitor(function () {
var xhrUrl = endpointBuilder.build('xhr', retry);
var xhrUrl = endpointBuilder.build('xhr', flushReason, retry);
// failed to queue the request

@@ -62,3 +62,3 @@ sendXHR(xhrUrl, data, onResponse);

else {
var xhrUrl = endpointBuilder.build('xhr', retry);
var xhrUrl = endpointBuilder.build('xhr', flushReason, retry);
sendXHR(xhrUrl, data, onResponse);

@@ -65,0 +65,0 @@ }

export { HttpRequest, createHttpRequest, Payload, RetryInfo } from './httpRequest';
export { Batch, BatchFlushEvent } from './batch';
export { Batch, BatchFlushEvent, FlushReason } from './batch';
export { canUseEventBridge, getEventBridge, BrowserWindowWithEventBridge } from './eventBridge';
export { startBatchWithReplica } from './startBatchWithReplica';
{
"name": "@datadog/browser-core",
"version": "4.34.1",
"version": "4.34.2",
"license": "Apache-2.0",

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

},
"gitHead": "963c6de2a0ecd461f6926a873bf905e3185808e2"
"gitHead": "2b8ddef938217fceb252f520693a2c48c5b4db8e"
}
import { createNewEvent, restorePageVisibility, setPageVisibility } from '../../test/specHelper'
import { resetExperimentalFeatures, updateExperimentalFeatures } from '../domain/configuration'
import type { Subscription } from '../tools/observable'

@@ -18,7 +19,20 @@ import type { PageExitEvent } from './pageExitObservable'

restorePageVisibility()
resetExperimentalFeatures()
})
it('notifies when the page is unloading', () => {
it('notifies when the page fires pagehide if ff pagehide is enabled', () => {
updateExperimentalFeatures(['pagehide'])
onExitSpy = jasmine.createSpy()
pageExitSubscription = createPageExitObservable().subscribe(onExitSpy)
window.dispatchEvent(createNewEvent('pagehide'))
window.dispatchEvent(createNewEvent('beforeunload'))
expect(onExitSpy).toHaveBeenCalledOnceWith({ reason: PageExitReason.PAGEHIDE })
})
it('notifies when the page fires beforeunload if ff pagehide is disabled', () => {
window.dispatchEvent(createNewEvent('pagehide'))
window.dispatchEvent(createNewEvent('beforeunload'))
expect(onExitSpy).toHaveBeenCalledOnceWith({ reason: PageExitReason.UNLOADING })

@@ -25,0 +39,0 @@ })

@@ -0,4 +1,5 @@

import { isExperimentalFeatureEnabled } from '../domain/configuration'
import { Observable } from '../tools/observable'
import { includes, objectValues } from '../tools/utils'
import { addEventListener, addEventListeners, DOM_EVENT } from './addEventListener'
import { includes, noop, objectValues } from '../tools/utils'
import { addEventListeners, addEventListener, DOM_EVENT } from './addEventListener'

@@ -8,2 +9,3 @@ export const PageExitReason = {

UNLOADING: 'before_unload',
PAGEHIDE: 'page_hide',
FROZEN: 'page_frozen',

@@ -20,8 +22,14 @@ } as const

const observable = new Observable<PageExitEvent>(() => {
const pagehideEnabled = isExperimentalFeatureEnabled('pagehide')
const { stop: stopListeners } = addEventListeners(
window,
[DOM_EVENT.VISIBILITY_CHANGE, DOM_EVENT.FREEZE],
[DOM_EVENT.VISIBILITY_CHANGE, DOM_EVENT.FREEZE, DOM_EVENT.PAGE_HIDE],
(event) => {
if (event.type === DOM_EVENT.VISIBILITY_CHANGE && document.visibilityState === 'hidden') {
if (event.type === DOM_EVENT.PAGE_HIDE && pagehideEnabled) {
/**
* Only event that detect page unload events while being compatible with the back/forward cache (bfcache)
*/
observable.notify({ reason: PageExitReason.PAGEHIDE })
} else if (event.type === DOM_EVENT.VISIBILITY_CHANGE && document.visibilityState === 'hidden') {
/**
* Only event that guarantee to fire on mobile devices when the page transitions to background state

@@ -42,10 +50,8 @@ * (e.g. when user switches to a different application, goes to homescreen, etc), or is being unloaded.

/**
* Safari does not support yet to send a request during:
* - a visibility change during doc unload (cf: https://bugs.webkit.org/show_bug.cgi?id=194897)
* - a page hide transition (cf: https://bugs.webkit.org/show_bug.cgi?id=188329)
*/
const { stop: stopBeforeUnloadListener } = addEventListener(window, DOM_EVENT.BEFORE_UNLOAD, () => {
observable.notify({ reason: PageExitReason.UNLOADING })
})
let stopBeforeUnloadListener = noop
if (!pagehideEnabled) {
stopBeforeUnloadListener = addEventListener(window, DOM_EVENT.BEFORE_UNLOAD, () => {
observable.notify({ reason: PageExitReason.UNLOADING })
}).stop
}

@@ -52,0 +58,0 @@ return () => {

@@ -5,2 +5,3 @@ import type { BuildEnvWindow } from '../../../test/specHelper'

import { createEndpointBuilder } from './endpointBuilder'
import { resetExperimentalFeatures, updateExperimentalFeatures } from './experimentalFeatures'

@@ -14,2 +15,3 @@ describe('endpointBuilder', () => {

;(window as unknown as BuildEnvWindow).__BUILD_ENV__SDK_VERSION__ = 'some_version'
resetExperimentalFeatures()
})

@@ -121,6 +123,22 @@

expect(
createEndpointBuilder(initConfiguration, 'rum', []).build('xhr', { count: 5, lastFailureStatus: 408 })
createEndpointBuilder(initConfiguration, 'rum', []).build('xhr', 'batch_bytes_limit', {
count: 5,
lastFailureStatus: 408,
})
).toContain('retry_count%3A5%2Cretry_after%3A408')
})
it('should contain flush reason when ff collect_flush_reason is enabled', () => {
updateExperimentalFeatures(['collect_flush_reason'])
expect(createEndpointBuilder(initConfiguration, 'rum', []).build('xhr', 'batch_bytes_limit')).toContain(
'flush_reason%3Abatch_bytes_limit'
)
})
it('should not contain flush reason when ff collect_flush_reason is disnabled', () => {
expect(createEndpointBuilder(initConfiguration, 'rum', []).build('xhr', 'batch_bytes_limit')).not.toContain(
'flush_reason'
)
})
})
})

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

import type { RetryInfo } from '../../transport'
import type { RetryInfo, FlushReason } from '../../transport'
import { timeStampNow } from '../../tools/timeUtils'

@@ -7,2 +7,3 @@ import { normalizeUrl } from '../../tools/urlPolyfill'

import { INTAKE_SITE_AP1, INTAKE_SITE_US1 } from './intakeSites'
import { isExperimentalFeatureEnabled } from './experimentalFeatures'

@@ -36,4 +37,11 @@ // replaced at build time

return {
build(api: 'xhr' | 'fetch' | 'beacon', retry?: RetryInfo) {
const parameters = buildEndpointParameters(initConfiguration, endpointType, configurationTags, api, retry)
build(api: 'xhr' | 'fetch' | 'beacon', flushReason?: FlushReason, retry?: RetryInfo) {
const parameters = buildEndpointParameters(
initConfiguration,
endpointType,
configurationTags,
api,
flushReason,
retry
)
return buildUrlWithParameters(parameters)

@@ -97,5 +105,9 @@ },

api: 'xhr' | 'fetch' | 'beacon',
flushReason: FlushReason | undefined,
retry: RetryInfo | undefined
) {
const tags = [`sdk_version:${__BUILD_ENV__SDK_VERSION__}`, `api:${api}`].concat(configurationTags)
if (flushReason && isExperimentalFeatureEnabled('collect_flush_reason')) {
tags.push(`flush_reason:${flushReason}`)
}
if (retry) {

@@ -102,0 +114,0 @@ tags.push(`retry_count:${retry.count}`, `retry_after:${retry.lastFailureStatus}`)

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

import { stubZoneJs } from '../../test/stubZoneJs'
import type { Clock } from '../../test/specHelper'

@@ -127,6 +128,10 @@ import { mockClock } from '../../test/specHelper'

let clock: Clock
let zoneJsStub: ReturnType<typeof stubZoneJs>
beforeEach(() => {
clock = mockClock()
zoneJsStub = stubZoneJs()
})
afterEach(() => {
zoneJsStub.restore()
clock.cleanup()

@@ -192,2 +197,17 @@ })

it('does not use the Zone.js setTimeout function', () => {
const zoneJsSetTimeoutSpy = jasmine.createSpy()
zoneJsStub.replaceProperty(window, 'setTimeout', zoneJsSetTimeoutSpy)
const object = {} as { foo: number }
Object.defineProperty(object, 'foo', { set: noop, configurable: true })
instrumentSetter(object, 'foo', noop)
object.foo = 2
clock.tick(0)
expect(zoneJsSetTimeoutSpy).not.toHaveBeenCalled()
})
it('allows other instrumentations from third parties', () => {

@@ -194,0 +214,0 @@ const object = {} as { foo: number }

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

import { getZoneJsOriginalValue } from './getZoneJsOriginalValue'
import { callMonitored, monitor } from './monitor'

@@ -83,2 +84,5 @@ import { noop } from './utils'

// Using the patched `setTimeout` from Zone.js triggers a rendering loop in some Angular
// component, see issue RUMF-1443
const setTimeout = getZoneJsOriginalValue(window, 'setTimeout')
let instrumentation = (thisObject: OBJECT, value: OBJECT[PROPERTY]) => {

@@ -85,0 +89,0 @@ // put hooked setter into event loop to avoid of set latency

@@ -6,2 +6,3 @@ import sinon from 'sinon'

import { noop } from '../tools/utils'
import type { FlushReason } from './batch'
import { Batch } from './batch'

@@ -20,2 +21,3 @@ import type { HttpRequest } from './httpRequest'

let flushNotifySpy: jasmine.Spy
const flushReason: FlushReason = 'batch_bytes_limit'

@@ -40,3 +42,3 @@ beforeEach(() => {

batch.flush()
batch.flush(flushReason)

@@ -46,2 +48,3 @@ expect(sendSpy.calls.mostRecent().args[0]).toEqual({

bytesCount: jasmine.any(Number),
flushReason,
})

@@ -53,5 +56,5 @@ })

batch.flush()
batch.flush(flushReason)
sendSpy.calls.reset()
batch.flush()
batch.flush(flushReason)

@@ -68,2 +71,3 @@ expect(transport.send).not.toHaveBeenCalled()

bytesCount: jasmine.any(Number),
flushReason,
})

@@ -77,8 +81,13 @@ })

batch.add({ message: '60 bytes - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' })
expect(sendSpy).toHaveBeenCalledWith({ data: '{"message":"50 bytes - xxxxxxxxxxxxxxxxxxxxxxxxx"}', bytesCount: 50 })
expect(sendSpy).toHaveBeenCalledWith({
data: '{"message":"50 bytes - xxxxxxxxxxxxxxxxxxxxxxxxx"}',
bytesCount: 50,
flushReason,
})
batch.flush()
batch.flush(flushReason)
expect(sendSpy).toHaveBeenCalledWith({
data: '{"message":"60 bytes - xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"}',
bytesCount: 60,
flushReason,
})

@@ -95,2 +104,3 @@ })

bytesCount: 61,
flushReason,
})

@@ -102,3 +112,3 @@ })

batch.add({ message })
expect(sendSpy).toHaveBeenCalledWith({ data: `{"message":"${message}"}`, bytesCount: 101 })
expect(sendSpy).toHaveBeenCalledWith({ data: `{"message":"${message}"}`, bytesCount: 101, flushReason })
})

@@ -149,2 +159,3 @@

bytesCount: jasmine.any(Number),
flushReason,
})

@@ -159,2 +170,3 @@

bytesCount: jasmine.any(Number),
flushReason,
})

@@ -166,3 +178,3 @@

batch.upsert({ message: '11' }, 'b')
batch.flush()
batch.flush(flushReason)

@@ -172,2 +184,3 @@ expect(sendSpy.calls.mostRecent().args[0]).toEqual({

bytesCount: jasmine.any(Number),
flushReason,
})

@@ -180,3 +193,3 @@ })

addTelemetryDebugFake()
transport.send({ data, bytesCount: BATCH_BYTES_LIMIT })
transport.send({ data, bytesCount: BATCH_BYTES_LIMIT, flushReason })
},

@@ -195,5 +208,5 @@ } as unknown as HttpRequest

batch.add({ message: 'normal message' })
batch.flush()
batch.flush(flushReason)
expect(sendSpy).toHaveBeenCalledTimes(1)
batch.flush()
batch.flush(flushReason)
expect(sendSpy).toHaveBeenCalledTimes(2)

@@ -204,5 +217,5 @@ })

batch.add({})
batch.flush()
batch.flush(flushReason)
expect(flushNotifySpy).toHaveBeenCalledOnceWith({ bufferBytesCount: 2, bufferMessagesCount: 1 })
})
})

@@ -14,2 +14,10 @@ import { display } from '../tools/display'

export type FlushReason =
| 'batch_duration_limit'
| 'batch_bytes_limit'
| 'before_unload'
| 'page_hide'
| 'visibility_hidden'
| 'page_frozen'
export class Batch {

@@ -31,3 +39,3 @@ flushObservable = new Observable<BatchFlushEvent>()

) {
pageExitObservable.subscribe(() => this.flush(this.request.sendOnExit))
pageExitObservable.subscribe((event) => this.flush(event.reason, this.request.sendOnExit))
this.flushPeriodically()

@@ -44,3 +52,3 @@ }

flush(sendFn = this.request.send) {
flush(flushReason: FlushReason, sendFn = this.request.send) {
if (this.bufferMessagesCount !== 0) {

@@ -60,3 +68,3 @@ const messages = this.pushOnlyBuffer.concat(objectValues(this.upsertBuffer))

sendFn({ data: messages.join('\n'), bytesCount })
sendFn({ data: messages.join('\n'), bytesCount, flushReason })
}

@@ -77,3 +85,3 @@ }

if (this.willReachedBytesLimitWith(messageBytesCount)) {
this.flush()
this.flush('batch_bytes_limit')
}

@@ -83,3 +91,3 @@

if (this.isFull()) {
this.flush()
this.flush('batch_bytes_limit')
}

@@ -135,3 +143,3 @@ }

monitor(() => {
this.flush()
this.flush('batch_duration_limit')
this.flushPeriodically()

@@ -138,0 +146,0 @@ }),

@@ -7,2 +7,3 @@ import type { EndpointBuilder } from '../domain/configuration'

import { newRetryState, sendWithRetryStrategy } from './sendWithRetryStrategy'
import type { FlushReason } from './batch'

@@ -29,2 +30,3 @@ /**

retry?: RetryInfo
flushReason?: FlushReason
}

@@ -60,7 +62,11 @@

function sendBeaconStrategy(endpointBuilder: EndpointBuilder, bytesLimit: number, { data, bytesCount }: Payload) {
function sendBeaconStrategy(
endpointBuilder: EndpointBuilder,
bytesLimit: number,
{ data, bytesCount, flushReason }: Payload
) {
const canUseBeacon = !!navigator.sendBeacon && bytesCount < bytesLimit
if (canUseBeacon) {
try {
const beaconUrl = endpointBuilder.build('beacon')
const beaconUrl = endpointBuilder.build('beacon', flushReason)
const isQueued = navigator.sendBeacon(beaconUrl, data)

@@ -76,3 +82,3 @@

const xhrUrl = endpointBuilder.build('xhr')
const xhrUrl = endpointBuilder.build('xhr', flushReason)
sendXHR(xhrUrl, data)

@@ -93,3 +99,3 @@ }

bytesLimit: number,
{ data, bytesCount, retry }: Payload,
{ data, bytesCount, flushReason, retry }: Payload,
onResponse?: (r: HttpResponse) => void

@@ -99,7 +105,7 @@ ) {

if (canUseKeepAlive) {
const fetchUrl = endpointBuilder.build('fetch', retry)
const fetchUrl = endpointBuilder.build('fetch', flushReason, retry)
fetch(fetchUrl, { method: 'POST', body: data, keepalive: true, mode: 'cors' }).then(
monitor((response: Response) => onResponse?.({ status: response.status, type: response.type })),
monitor(() => {
const xhrUrl = endpointBuilder.build('xhr', retry)
const xhrUrl = endpointBuilder.build('xhr', flushReason, retry)
// failed to queue the request

@@ -110,3 +116,3 @@ sendXHR(xhrUrl, data, onResponse)

} else {
const xhrUrl = endpointBuilder.build('xhr', retry)
const xhrUrl = endpointBuilder.build('xhr', flushReason, retry)
sendXHR(xhrUrl, data, onResponse)

@@ -113,0 +119,0 @@ }

export { HttpRequest, createHttpRequest, Payload, RetryInfo } from './httpRequest'
export { Batch, BatchFlushEvent } from './batch'
export { Batch, BatchFlushEvent, FlushReason } from './batch'
export { canUseEventBridge, getEventBridge, BrowserWindowWithEventBridge } from './eventBridge'
export { startBatchWithReplica } from './startBatchWithReplica'

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

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

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc