@newrelic/browser-agent 1.234.0 → 1.235.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/constants/shared-channel.js +19 -0
- package/dist/cjs/common/harvest/harvest-scheduler.js +21 -5
- package/dist/cjs/common/session/{session-entity.test.js → session-entity.component-test.js} +79 -42
- package/dist/cjs/common/session/session-entity.js +19 -11
- package/dist/cjs/common/timer/interaction-timer.js +1 -1
- package/dist/cjs/common/url/canonicalize-url.test.js +26 -30
- package/dist/cjs/common/util/data-size.test.js +37 -20
- package/dist/cjs/common/util/feature-flags.js +23 -12
- package/dist/cjs/common/util/feature-flags.test.js +84 -0
- package/dist/cjs/common/util/global-scope.js +1 -32
- package/dist/cjs/common/util/global-scope.test.js +72 -0
- package/dist/cjs/common/util/obfuscate.component-test.js +129 -0
- package/dist/cjs/common/util/obfuscate.js +2 -2
- package/dist/cjs/common/util/submit-data.js +3 -3
- package/dist/cjs/common/util/submit-data.test.js +145 -121
- package/dist/cjs/common/wrap/wrap-raf.js +1 -1
- package/dist/cjs/common/wrap/wrap-timer.js +1 -1
- package/dist/cjs/features/jserrors/aggregate/index.js +4 -0
- package/dist/cjs/features/jserrors/instrument/index.js +2 -15
- package/dist/cjs/features/session_replay/aggregate/index.component-test.js +457 -0
- package/dist/cjs/features/session_replay/aggregate/index.js +99 -82
- package/dist/cjs/features/session_replay/replay-mode.js +28 -0
- package/dist/cjs/features/session_trace/aggregate/index.js +222 -99
- package/dist/cjs/features/session_trace/constants.js +1 -3
- package/dist/cjs/features/session_trace/instrument/index.js +0 -16
- package/dist/cjs/features/spa/constants.js +0 -1
- package/dist/cjs/features/utils/agent-session.js +20 -36
- package/dist/cjs/features/utils/agent-session.test.js +211 -0
- package/dist/cjs/features/utils/aggregate-base.js +7 -12
- package/dist/cjs/features/utils/aggregate-base.test.js +110 -0
- package/dist/cjs/features/utils/feature-base.test.js +42 -0
- package/dist/cjs/features/utils/handler-cache.js +28 -23
- package/dist/cjs/features/utils/handler-cache.test.js +53 -0
- package/dist/cjs/features/utils/instrument-base.js +58 -39
- package/dist/cjs/features/utils/instrument-base.test.js +179 -0
- package/dist/cjs/features/utils/lazy-feature-loader.test.js +30 -0
- package/dist/cjs/loaders/agent.js +0 -1
- package/dist/cjs/loaders/api/api.js +1 -1
- package/dist/cjs/loaders/features/featureDependencies.js +2 -0
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/constants/shared-channel.js +12 -0
- package/dist/esm/common/harvest/harvest-scheduler.js +21 -5
- package/dist/esm/common/session/{session-entity.test.js → session-entity.component-test.js} +77 -40
- package/dist/esm/common/session/session-entity.js +17 -11
- package/dist/esm/common/timer/interaction-timer.js +1 -1
- package/dist/esm/common/url/canonicalize-url.test.js +25 -29
- package/dist/esm/common/util/data-size.test.js +35 -20
- package/dist/esm/common/util/feature-flags.js +23 -12
- package/dist/esm/common/util/feature-flags.test.js +80 -0
- package/dist/esm/common/util/global-scope.js +1 -29
- package/dist/esm/common/util/global-scope.test.js +70 -0
- package/dist/esm/common/util/obfuscate.component-test.js +125 -0
- package/dist/esm/common/util/obfuscate.js +2 -2
- package/dist/esm/common/util/submit-data.js +3 -3
- package/dist/esm/common/util/submit-data.test.js +143 -121
- package/dist/esm/common/wrap/wrap-raf.js +1 -1
- package/dist/esm/common/wrap/wrap-timer.js +1 -1
- package/dist/esm/features/jserrors/aggregate/index.js +4 -0
- package/dist/esm/features/jserrors/instrument/index.js +2 -15
- package/dist/esm/features/session_replay/aggregate/index.component-test.js +453 -0
- package/dist/esm/features/session_replay/aggregate/index.js +92 -78
- package/dist/esm/features/session_replay/replay-mode.js +23 -0
- package/dist/esm/features/session_trace/aggregate/index.js +223 -100
- package/dist/esm/features/session_trace/constants.js +0 -1
- package/dist/esm/features/session_trace/instrument/index.js +1 -17
- package/dist/esm/features/spa/constants.js +0 -1
- package/dist/esm/features/utils/agent-session.js +21 -37
- package/dist/esm/features/utils/agent-session.test.js +207 -0
- package/dist/esm/features/utils/aggregate-base.js +7 -12
- package/dist/esm/features/utils/aggregate-base.test.js +108 -0
- package/dist/esm/features/utils/feature-base.test.js +40 -0
- package/dist/esm/features/utils/handler-cache.js +28 -23
- package/dist/esm/features/utils/handler-cache.test.js +51 -0
- package/dist/esm/features/utils/instrument-base.js +58 -39
- package/dist/esm/features/utils/instrument-base.test.js +175 -0
- package/dist/esm/features/utils/lazy-feature-loader.test.js +29 -0
- package/dist/esm/loaders/agent.js +0 -1
- package/dist/esm/loaders/api/api.js +2 -2
- package/dist/esm/loaders/features/featureDependencies.js +2 -0
- package/dist/types/common/constants/shared-channel.d.ts +5 -0
- package/dist/types/common/constants/shared-channel.d.ts.map +1 -0
- package/dist/types/common/harvest/harvest-scheduler.component-test.d.ts +2 -0
- package/dist/types/common/harvest/harvest-scheduler.component-test.d.ts.map +1 -0
- package/dist/types/common/harvest/harvest-scheduler.d.ts +4 -0
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.component-test.d.ts +2 -0
- package/dist/types/common/harvest/harvest.component-test.d.ts.map +1 -0
- package/dist/types/common/session/session-entity.component-test.d.ts +2 -0
- package/dist/types/common/session/session-entity.component-test.d.ts.map +1 -0
- package/dist/types/common/session/session-entity.d.ts +9 -5
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/timer/interaction-timer.component-test.d.ts +2 -0
- package/dist/types/common/timer/interaction-timer.component-test.d.ts.map +1 -0
- package/dist/types/common/url/encode.component-test.d.ts +2 -0
- package/dist/types/common/url/encode.component-test.d.ts.map +1 -0
- package/dist/types/common/url/protocol.component-test.d.ts +2 -0
- package/dist/types/common/url/protocol.component-test.d.ts.map +1 -0
- package/dist/types/common/util/feature-flags.d.ts +1 -0
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/util/global-scope.d.ts +0 -9
- package/dist/types/common/util/global-scope.d.ts.map +1 -1
- package/dist/types/common/util/obfuscate.component-test.d.ts +2 -0
- package/dist/types/common/util/obfuscate.component-test.d.ts.map +1 -0
- package/dist/types/features/jserrors/aggregate/index.d.ts +1 -0
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.component-test.d.ts +2 -0
- package/dist/types/features/session_replay/aggregate/index.component-test.d.ts.map +1 -0
- package/dist/types/features/session_replay/aggregate/index.d.ts +14 -5
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/replay-mode.d.ts +9 -0
- package/dist/types/features/session_replay/replay-mode.d.ts.map +1 -0
- package/dist/types/features/session_trace/aggregate/index.d.ts +21 -3
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/constants.d.ts +0 -1
- package/dist/types/features/session_trace/constants.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts +0 -2
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/spa/constants.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +6 -1
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/handler-cache.d.ts +12 -11
- package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +17 -1
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
- package/package.json +9 -7
- package/src/common/constants/shared-channel.js +13 -0
- package/src/common/harvest/harvest-scheduler.js +17 -6
- package/src/common/session/{session-entity.test.js → session-entity.component-test.js} +70 -47
- package/src/common/session/session-entity.js +15 -12
- package/src/common/timer/interaction-timer.js +1 -1
- package/src/common/url/canonicalize-url.test.js +32 -21
- package/src/common/util/data-size.test.js +27 -20
- package/src/common/util/feature-flags.js +24 -12
- package/src/common/util/feature-flags.test.js +98 -0
- package/src/common/util/global-scope.js +0 -26
- package/src/common/util/global-scope.test.js +87 -0
- package/src/common/util/obfuscate.component-test.js +173 -0
- package/src/common/util/obfuscate.js +2 -2
- package/src/common/util/submit-data.js +3 -3
- package/src/common/util/submit-data.test.js +123 -115
- package/src/common/wrap/wrap-raf.js +1 -1
- package/src/common/wrap/wrap-timer.js +1 -1
- package/src/features/jserrors/aggregate/index.js +5 -0
- package/src/features/jserrors/instrument/index.js +2 -15
- package/src/features/session_replay/aggregate/index.component-test.js +368 -0
- package/src/features/session_replay/aggregate/index.js +96 -71
- package/src/features/session_replay/instrument/index.js +0 -1
- package/src/features/session_replay/replay-mode.js +23 -0
- package/src/features/session_trace/aggregate/index.js +198 -79
- package/src/features/session_trace/constants.js +0 -1
- package/src/features/session_trace/instrument/index.js +2 -19
- package/src/features/spa/constants.js +0 -1
- package/src/features/utils/agent-session.js +22 -34
- package/src/features/utils/agent-session.test.js +194 -0
- package/src/features/utils/aggregate-base.js +12 -9
- package/src/features/utils/aggregate-base.test.js +122 -0
- package/src/features/utils/feature-base.test.js +45 -0
- package/src/features/utils/handler-cache.js +29 -23
- package/src/features/utils/handler-cache.test.js +72 -0
- package/src/features/utils/instrument-base.js +45 -29
- package/src/features/utils/instrument-base.test.js +190 -0
- package/src/features/utils/lazy-feature-loader.test.js +37 -0
- package/src/loaders/agent.js +0 -1
- package/src/loaders/api/api.js +2 -2
- package/src/loaders/features/featureDependencies.js +2 -0
- package/dist/cjs/common/storage/local-memory.js +0 -35
- package/dist/cjs/common/storage/local-memory.test.js +0 -20
- package/dist/esm/common/storage/local-memory.js +0 -28
- package/dist/esm/common/storage/local-memory.test.js +0 -18
- package/dist/types/common/storage/local-memory.d.ts +0 -8
- package/dist/types/common/storage/local-memory.d.ts.map +0 -1
- package/src/common/storage/local-memory.js +0 -30
- package/src/common/storage/local-memory.test.js +0 -19
- /package/dist/cjs/common/harvest/{harvest-scheduler.test.js → harvest-scheduler.component-test.js} +0 -0
- /package/dist/cjs/common/harvest/{harvest.test.js → harvest.component-test.js} +0 -0
- /package/dist/cjs/common/timer/{interaction-timer.test.js → interaction-timer.component-test.js} +0 -0
- /package/dist/cjs/common/url/{encode.test.js → encode.component-test.js} +0 -0
- /package/dist/cjs/common/url/{protocol.test.js → protocol.component-test.js} +0 -0
- /package/dist/esm/common/harvest/{harvest-scheduler.test.js → harvest-scheduler.component-test.js} +0 -0
- /package/dist/esm/common/harvest/{harvest.test.js → harvest.component-test.js} +0 -0
- /package/dist/esm/common/timer/{interaction-timer.test.js → interaction-timer.component-test.js} +0 -0
- /package/dist/esm/common/url/{encode.test.js → encode.component-test.js} +0 -0
- /package/dist/esm/common/url/{protocol.test.js → protocol.component-test.js} +0 -0
- /package/src/common/harvest/{harvest-scheduler.test.js → harvest-scheduler.component-test.js} +0 -0
- /package/src/common/harvest/{harvest.test.js → harvest.component-test.js} +0 -0
- /package/src/common/timer/{interaction-timer.test.js → interaction-timer.component-test.js} +0 -0
- /package/src/common/url/{encode.test.js → encode.component-test.js} +0 -0
- /package/src/common/url/{protocol.test.js → protocol.component-test.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAMA;IACE,4BAGC;IAED,
|
|
1
|
+
{"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAMA;IACE,4BAGC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,kBAWlB;IAED;;;OAGG;IACH,2BAqBC;CACF;4BApD2B,gBAAgB"}
|
|
@@ -3,20 +3,21 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export class HandlerCache {
|
|
5
5
|
/**
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
* Wrap callback functions with this method to defer their execution until a decision has been reached
|
|
7
|
+
* @param {Function} handler
|
|
8
|
+
* @returns {void}
|
|
9
|
+
*/
|
|
10
10
|
settle(handler: Function): void;
|
|
11
11
|
/**
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
12
|
+
* Make a decision about what to do with the cache of callbacks.
|
|
13
|
+
* --- if true: tell the handlerCache that its ok to immediately execute the callbacks that are triggered by the ee from this moment on
|
|
14
|
+
* and execute all the storage callbacks saved up in the handlerCache ---
|
|
15
|
+
* --- if false: tell the handlerCache not to execute any of the storage callbacks
|
|
16
|
+
* and wipe out all the storage callbacks saved up in the handlerCache
|
|
17
|
+
* @param {boolean} decision
|
|
18
|
+
*/
|
|
19
19
|
decide(decision: boolean): void;
|
|
20
|
+
permanentlyDecide(decision: any): void;
|
|
20
21
|
#private;
|
|
21
22
|
}
|
|
22
23
|
//# sourceMappingURL=handler-cache.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler-cache.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/handler-cache.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IA6BE;;;;
|
|
1
|
+
{"version":3,"file":"handler-cache.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/handler-cache.js"],"names":[],"mappings":"AAAA;;GAEG;AACH;IA6BE;;;;OAIG;IACH,2BAFa,IAAI,CAMhB;IAED;;;;;;;OAOG;IACH,iBAFW,OAAO,QAOjB;IAED,uCAIC;;CACF"}
|
|
@@ -13,10 +13,19 @@ export class InstrumentBase extends FeatureBase {
|
|
|
13
13
|
* immediately. Primarily useful for fine-grained control in tests.
|
|
14
14
|
*/
|
|
15
15
|
constructor(agentIdentifier: string, aggregator: Aggregator, featureName: string, auto?: boolean | undefined);
|
|
16
|
-
hasAggregator: boolean;
|
|
17
16
|
auto: boolean;
|
|
18
17
|
/** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
|
|
19
18
|
abortHandler: Function | undefined;
|
|
19
|
+
/**
|
|
20
|
+
* @type {Class} Holds the reference to the feature's aggregate module counterpart, if and after it has been initialized. This may not be assigned until after page loads!
|
|
21
|
+
* The only purpose of this for now is to expose it to the NREUM interface, as the feature's instrument instance is already exposed.
|
|
22
|
+
*/
|
|
23
|
+
featAggregate: Class;
|
|
24
|
+
/**
|
|
25
|
+
* @type {Promise} Assigned immediately after @see importAggregator runs. Serves as a signal for when the inner async fn finishes execution. Useful for features to await
|
|
26
|
+
* one another if there are inter-features dependencies.
|
|
27
|
+
*/
|
|
28
|
+
onAggregateImported: Promise<any>;
|
|
20
29
|
/**
|
|
21
30
|
* Lazy-load the latter part of the feature: its aggregator. This method is called by the first part of the feature
|
|
22
31
|
* (the instrumentation) when instrumentation is complete.
|
|
@@ -24,6 +33,13 @@ export class InstrumentBase extends FeatureBase {
|
|
|
24
33
|
* @returns void
|
|
25
34
|
*/
|
|
26
35
|
importAggregator(argsObjFromInstrument?: Object | undefined): void;
|
|
36
|
+
/**
|
|
37
|
+
* Make a determination if an aggregate class should even be imported
|
|
38
|
+
* @param {string} featureName
|
|
39
|
+
* @param {SessionEntity} session
|
|
40
|
+
* @returns
|
|
41
|
+
*/
|
|
42
|
+
shouldImportAgg(featureName: string, session: SessionEntity): boolean;
|
|
27
43
|
}
|
|
28
44
|
import { FeatureBase } from './feature-base';
|
|
29
45
|
//# sourceMappingURL=instrument-base.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"instrument-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/instrument-base.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH;IACE;;;;;;;;OAQG;IACH,6BAPW,MAAM,uCAEN,MAAM,
|
|
1
|
+
{"version":3,"file":"instrument-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/instrument-base.js"],"names":[],"mappings":"AAcA;;;GAGG;AACH;IACE;;;;;;;;OAQG;IACH,6BAPW,MAAM,uCAEN,MAAM,8BAuBhB;IAhBC,cAAgB;IAEhB,8IAA8I;IAC9I,cADW,WAAW,SAAS,CACd;IACjB;;;MAGE;IACF,qBAAkB;IAClB;;;MAGE;IACF,kCAAwB;IAK1B;;;;;OAKG;IACH,mEA4CC;IAED;;;;;KAKC;IACD,6BAJS,MAAM,mCAed;CACF;4BA/G2B,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH;IACE,
|
|
1
|
+
{"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAeA;;;GAGG;AACH;IACE,oDAcC;IAbC,wBAAsC;IACtC,6BAAiF;IACjF,aAAkB;IAElB,0BAAsD;IAWxD;;;;;MAOC;IAED,2BAgCC;CACF;2BAtE0B,gCAAgC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"featureDependencies.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/featureDependencies.js"],"names":[],"mappings":"AAEA,
|
|
1
|
+
{"version":3,"file":"featureDependencies.d.ts","sourceRoot":"","sources":["../../../../src/loaders/features/featureDependencies.js"],"names":[],"mappings":"AAEA,kEAaC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@newrelic/browser-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.235.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
|
|
6
6
|
"description": "Tests for the New Relic JavaScript agent",
|
|
@@ -89,9 +89,8 @@
|
|
|
89
89
|
"scripts": {
|
|
90
90
|
"wdio": "node --max-old-space-size=8192 tools/wdio/bin/cli.js",
|
|
91
91
|
"start": "npm-run-all --parallel cdn:watch test-server",
|
|
92
|
-
"test": "jest",
|
|
93
|
-
"test:
|
|
94
|
-
"test:coverage": "jest --coverage",
|
|
92
|
+
"test:unit": "jest",
|
|
93
|
+
"test:component": "jest --config jest.component-config.js",
|
|
95
94
|
"build:all": "npm run cdn:build:local && npm run build:npm && npm run tools:test-builds",
|
|
96
95
|
"build:npm": "npm run npm:build:esm && npm run npm:build:cjs && npm run npm:build:types && npm run npm:pack",
|
|
97
96
|
"build:browser-tests": "npm --prefix ./tools/test-builds/browser-tests run build",
|
|
@@ -196,10 +195,13 @@
|
|
|
196
195
|
"gzip-size": "^7.0.0",
|
|
197
196
|
"html-webpack-plugin": "^5.5.0",
|
|
198
197
|
"husky": "^8.0.0",
|
|
199
|
-
"
|
|
200
|
-
"
|
|
198
|
+
"istanbul-lib-coverage": "^3.2.0",
|
|
199
|
+
"istanbul-lib-instrument": "^5.2.1",
|
|
200
|
+
"istanbul-lib-report": "^3.0.0",
|
|
201
|
+
"istanbul-reports": "^3.1.5",
|
|
202
|
+
"jest": "^29.5.0",
|
|
203
|
+
"jest-environment-jsdom": "29.5.0",
|
|
201
204
|
"jest-extended": "^3.2.4",
|
|
202
|
-
"jquery": "1.11.3",
|
|
203
205
|
"jung": "^2.1.0",
|
|
204
206
|
"just-debounce": "^1.0.0",
|
|
205
207
|
"mime-types": "^2.1.11",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Keeps an object alive that is passed to all feature aggregate modules.
|
|
3
|
+
* The purpose is to have a way for communication and signals to relay across features at runtime.
|
|
4
|
+
* This object can hold any arbitrary values and should be treated as on-the-fly dynamic.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
let onReplayReady
|
|
8
|
+
const sessionReplayInitialized = new Promise(resolve => onReplayReady = resolve)
|
|
9
|
+
|
|
10
|
+
export const sharedChannel = Object.freeze({
|
|
11
|
+
onReplayReady,
|
|
12
|
+
sessionReplayInitialized
|
|
13
|
+
})
|
|
@@ -8,6 +8,7 @@ import { SharedContext } from '../context/shared-context'
|
|
|
8
8
|
import { Harvest, getSubmitMethod } from './harvest'
|
|
9
9
|
import { subscribeToEOL } from '../unload/eol'
|
|
10
10
|
import { getConfigurationValue } from '../config/config'
|
|
11
|
+
import { SESSION_EVENTS } from '../session/session-entity'
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* Periodically invokes harvest calls and handles retries
|
|
@@ -37,10 +38,16 @@ export class HarvestScheduler extends SharedContext {
|
|
|
37
38
|
// unload if EOL mechanism fires
|
|
38
39
|
subscribeToEOL(this.unload.bind(this), getConfigurationValue(this.sharedContext.agentIdentifier, 'allow_bfcache')) // TO DO: remove feature flag after rls stable
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
41
|
+
/* Flush all buffered data if session resets and give up retries. This should be synchronous to ensure that the correct `session` value is sent.
|
|
42
|
+
Since session-reset generates a new session ID and the ID is grabbed at send-time, any delays or retries would cause the payload to be sent under
|
|
43
|
+
the wrong session ID. */
|
|
44
|
+
this.sharedContext?.ee.on(SESSION_EVENTS.RESET, () => this.runHarvest({ forceNoRetry: true }))
|
|
42
45
|
}
|
|
43
46
|
|
|
47
|
+
/**
|
|
48
|
+
* This function is only meant for the last outgoing harvest cycle of a page. It trickles down to using sendBeacon, which should not be used
|
|
49
|
+
* to send payloads while the page is still active, due to limitations on how much data can be buffered in the API at any one time.
|
|
50
|
+
*/
|
|
44
51
|
unload () {
|
|
45
52
|
if (this.aborted) return
|
|
46
53
|
// If opts.onUnload is defined, these are special actions to execute before attempting to send the final payload.
|
|
@@ -118,7 +125,7 @@ export class HarvestScheduler extends SharedContext {
|
|
|
118
125
|
payload,
|
|
119
126
|
opts,
|
|
120
127
|
submitMethod,
|
|
121
|
-
cbFinished:
|
|
128
|
+
cbFinished: cbRanAfterSend,
|
|
122
129
|
customUrl: this.opts.customUrl,
|
|
123
130
|
raw: this.opts.raw
|
|
124
131
|
})
|
|
@@ -129,9 +136,13 @@ export class HarvestScheduler extends SharedContext {
|
|
|
129
136
|
}
|
|
130
137
|
return
|
|
131
138
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
139
|
+
/**
|
|
140
|
+
* This is executed immediately after harvest sends the data via XHR, or if there's nothing to send. Note that this excludes on unloading / sendBeacon.
|
|
141
|
+
* @param {Object} result
|
|
142
|
+
*/
|
|
143
|
+
function cbRanAfterSend (result) {
|
|
144
|
+
if (opts?.forceNoRetry) result.retry = false // discard unsent data rather than re-queuing for next harvest attempt
|
|
145
|
+
scheduler.onHarvestFinished(opts, result)
|
|
135
146
|
}
|
|
136
147
|
}
|
|
137
148
|
|
|
@@ -1,12 +1,39 @@
|
|
|
1
|
-
import { LocalMemory } from '../storage/local-memory'
|
|
2
|
-
import { LocalStorage } from '../storage/local-storage'
|
|
3
|
-
|
|
4
1
|
import { PREFIX } from './constants'
|
|
5
2
|
import { SessionEntity } from './session-entity'
|
|
6
3
|
|
|
7
4
|
const agentIdentifier = 'test_agent_identifier'
|
|
8
5
|
const key = 'test_key'
|
|
9
6
|
const value = 'test_value'
|
|
7
|
+
class LocalMemory {
|
|
8
|
+
constructor (initialState = {}) {
|
|
9
|
+
this.state = initialState
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get (key) {
|
|
13
|
+
try {
|
|
14
|
+
return this.state[key]
|
|
15
|
+
} catch (err) {
|
|
16
|
+
return ''
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
set (key, value) {
|
|
21
|
+
try {
|
|
22
|
+
if (value === undefined || value === null) return this.remove(key)
|
|
23
|
+
this.state[key] = value
|
|
24
|
+
} catch (err) {
|
|
25
|
+
return
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
remove (key) {
|
|
30
|
+
try {
|
|
31
|
+
delete this.state[key]
|
|
32
|
+
} catch (err) {
|
|
33
|
+
return
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
10
37
|
|
|
11
38
|
jest.mock('../timer/timer')
|
|
12
39
|
jest.mock('../timer/interaction-timer')
|
|
@@ -23,9 +50,11 @@ jest.mock('../util/global-scope', () => ({
|
|
|
23
50
|
}
|
|
24
51
|
}))
|
|
25
52
|
|
|
53
|
+
let storage
|
|
26
54
|
beforeEach(() => {
|
|
27
55
|
jest.restoreAllMocks()
|
|
28
56
|
mockBrowserScope.mockReturnValue(true)
|
|
57
|
+
storage = new LocalMemory()
|
|
29
58
|
})
|
|
30
59
|
|
|
31
60
|
describe('constructor', () => {
|
|
@@ -36,7 +65,7 @@ describe('constructor', () => {
|
|
|
36
65
|
})
|
|
37
66
|
|
|
38
67
|
test('top-level properties are set and exposed', () => {
|
|
39
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
68
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
40
69
|
expect(session).toMatchObject({
|
|
41
70
|
agentIdentifier: expect.any(String),
|
|
42
71
|
key: expect.any(String),
|
|
@@ -51,119 +80,113 @@ describe('constructor', () => {
|
|
|
51
80
|
expiresAt: expect.any(Number),
|
|
52
81
|
inactiveAt: expect.any(Number),
|
|
53
82
|
sessionReplay: expect.any(Number),
|
|
54
|
-
|
|
83
|
+
sessionTraceMode: expect.any(Number)
|
|
55
84
|
})
|
|
56
85
|
})
|
|
57
86
|
})
|
|
58
87
|
|
|
59
88
|
test('can use sane defaults', () => {
|
|
60
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
89
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
61
90
|
expect(session.state).toEqual(expect.objectContaining({
|
|
62
91
|
value: expect.any(String),
|
|
63
92
|
expiresAt: expect.any(Number),
|
|
64
93
|
inactiveAt: expect.any(Number),
|
|
65
94
|
updatedAt: expect.any(Number),
|
|
66
95
|
sessionReplay: expect.any(Number),
|
|
67
|
-
|
|
96
|
+
sessionTraceMode: expect.any(Number)
|
|
68
97
|
}))
|
|
69
98
|
})
|
|
70
99
|
|
|
71
|
-
test('Workers are forced to use local memory', () => {
|
|
72
|
-
mockBrowserScope.mockReturnValueOnce(false)
|
|
73
|
-
const session = new SessionEntity({ agentIdentifier, key, storageAPI: new LocalStorage() })
|
|
74
|
-
expect(session.storage instanceof LocalMemory).toEqual(true)
|
|
75
|
-
})
|
|
76
|
-
|
|
77
100
|
test('expiresAt is the correct future timestamp - new session', () => {
|
|
78
101
|
const now = Date.now()
|
|
79
102
|
jest.setSystemTime(now)
|
|
80
|
-
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 100 })
|
|
103
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, expiresMs: 100 })
|
|
81
104
|
expect(session.state.expiresAt).toEqual(now + 100)
|
|
82
105
|
})
|
|
83
106
|
|
|
84
107
|
test('expiresAt is the correct future timestamp - existing session', () => {
|
|
85
108
|
const now = Date.now()
|
|
86
109
|
jest.setSystemTime(now)
|
|
87
|
-
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: now + 5000, inactiveAt: Infinity, updatedAt: now, sessionReplay: 0,
|
|
88
|
-
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 100,
|
|
110
|
+
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: now + 5000, inactiveAt: Infinity, updatedAt: now, sessionReplay: 0, sessionTraceMode: 0, custom: {} } })
|
|
111
|
+
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 100, storage: existingData })
|
|
89
112
|
expect(session.state.expiresAt).toEqual(now + 5000)
|
|
90
113
|
})
|
|
91
114
|
|
|
92
115
|
test('expiresAt never expires if 0', () => {
|
|
93
|
-
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 0 })
|
|
116
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, expiresMs: 0 })
|
|
94
117
|
expect(session.state.expiresAt).toEqual(Infinity)
|
|
95
118
|
})
|
|
96
119
|
|
|
97
120
|
test('inactiveAt is the correct future timestamp - new session', () => {
|
|
98
121
|
const now = Date.now()
|
|
99
122
|
jest.setSystemTime(now)
|
|
100
|
-
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100 })
|
|
123
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, inactiveMs: 100 })
|
|
101
124
|
expect(session.state.inactiveAt).toEqual(now + 100)
|
|
102
125
|
})
|
|
103
126
|
|
|
104
127
|
test('inactiveAt is the correct future timestamp - existing session', () => {
|
|
105
128
|
const now = Date.now()
|
|
106
129
|
jest.setSystemTime(now)
|
|
107
|
-
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, inactiveAt: now + 5000, expiresAt: Infinity, updatedAt: now, sessionReplay: 0,
|
|
108
|
-
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100,
|
|
130
|
+
const existingData = new LocalMemory({ [`${PREFIX}_${key}`]: { value, inactiveAt: now + 5000, expiresAt: Infinity, updatedAt: now, sessionReplay: 0, sessionTraceMode: 0, custom: {} } })
|
|
131
|
+
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100, storage: existingData })
|
|
109
132
|
expect(session.state.inactiveAt).toEqual(now + 5000)
|
|
110
133
|
})
|
|
111
134
|
|
|
112
135
|
test('inactiveAt never expires if 0', () => {
|
|
113
|
-
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 0 })
|
|
136
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, inactiveMs: 0 })
|
|
114
137
|
expect(session.state.inactiveAt).toEqual(Infinity)
|
|
115
138
|
})
|
|
116
139
|
|
|
117
140
|
test('should handle isNew', () => {
|
|
118
|
-
const newSession = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
141
|
+
const newSession = new SessionEntity({ agentIdentifier, key, storage, expiresMs: 10 })
|
|
119
142
|
expect(newSession.isNew).toBeTruthy()
|
|
120
143
|
|
|
121
|
-
const
|
|
122
|
-
const existingSession = new SessionEntity({ agentIdentifier, key, expiresMs: 10,
|
|
144
|
+
const newStorage = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: Infinity, inactiveAt: Infinity, updatedAt: Date.now(), sessionReplay: 0, sessionTraceMode: 0, custom: {} } })
|
|
145
|
+
const existingSession = new SessionEntity({ agentIdentifier, key, expiresMs: 10, storage: newStorage })
|
|
123
146
|
expect(existingSession.isNew).toBeFalsy()
|
|
124
147
|
})
|
|
125
148
|
|
|
126
149
|
test('invalid stored values sets new defaults', () => {
|
|
127
150
|
// missing required fields
|
|
128
|
-
const
|
|
129
|
-
const session = new SessionEntity({ agentIdentifier, key,
|
|
151
|
+
const storage = new LocalMemory({ [`${PREFIX}_${key}`]: { invalid_fields: true } })
|
|
152
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
130
153
|
expect(session.state).toEqual(expect.objectContaining({
|
|
131
154
|
value: expect.any(String),
|
|
132
155
|
expiresAt: expect.any(Number),
|
|
133
156
|
inactiveAt: expect.any(Number),
|
|
134
157
|
updatedAt: expect.any(Number),
|
|
135
158
|
sessionReplay: expect.any(Number),
|
|
136
|
-
|
|
159
|
+
sessionTraceMode: expect.any(Number)
|
|
137
160
|
}))
|
|
138
161
|
})
|
|
139
162
|
|
|
140
163
|
test('expired expiresAt value in storage sets new defaults', () => {
|
|
141
164
|
const now = Date.now()
|
|
142
165
|
jest.setSystemTime(now)
|
|
143
|
-
const
|
|
144
|
-
const session = new SessionEntity({ agentIdentifier, key,
|
|
166
|
+
const storage = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: now - 100, inactiveAt: Infinity } })
|
|
167
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
145
168
|
expect(session.state).toEqual(expect.objectContaining({
|
|
146
169
|
value: expect.any(String),
|
|
147
170
|
expiresAt: expect.any(Number),
|
|
148
171
|
inactiveAt: expect.any(Number),
|
|
149
172
|
updatedAt: expect.any(Number),
|
|
150
173
|
sessionReplay: expect.any(Number),
|
|
151
|
-
|
|
174
|
+
sessionTraceMode: expect.any(Number)
|
|
152
175
|
}))
|
|
153
176
|
})
|
|
154
177
|
|
|
155
178
|
test('expired inactiveAt value in storage sets new defaults', () => {
|
|
156
179
|
const now = Date.now()
|
|
157
180
|
jest.setSystemTime(now)
|
|
158
|
-
const
|
|
159
|
-
const session = new SessionEntity({ agentIdentifier, key,
|
|
181
|
+
const storage = new LocalMemory({ [`${PREFIX}_${key}`]: { value, inactiveAt: now - 100, expiresAt: Infinity } })
|
|
182
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
160
183
|
expect(session.state).toEqual(expect.objectContaining({
|
|
161
184
|
value: expect.any(String),
|
|
162
185
|
expiresAt: expect.any(Number),
|
|
163
186
|
inactiveAt: expect.any(Number),
|
|
164
187
|
updatedAt: expect.any(Number),
|
|
165
188
|
sessionReplay: expect.any(Number),
|
|
166
|
-
|
|
189
|
+
sessionTraceMode: expect.any(Number)
|
|
167
190
|
}))
|
|
168
191
|
})
|
|
169
192
|
})
|
|
@@ -172,7 +195,7 @@ describe('reset()', () => {
|
|
|
172
195
|
test('should create new default values when resetting', () => {
|
|
173
196
|
const now = Date.now()
|
|
174
197
|
jest.setSystemTime(now)
|
|
175
|
-
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
198
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, expiresMs: 10 })
|
|
176
199
|
const sessionVal = session.value
|
|
177
200
|
expect(session.state.value).toBeTruthy()
|
|
178
201
|
session.reset()
|
|
@@ -183,7 +206,7 @@ describe('reset()', () => {
|
|
|
183
206
|
test('custom data should be wiped on reset', () => {
|
|
184
207
|
const now = Date.now()
|
|
185
208
|
jest.setSystemTime(now)
|
|
186
|
-
const session = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
209
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, expiresMs: 10 })
|
|
187
210
|
session.syncCustomAttribute('test', 123)
|
|
188
211
|
expect(session.state.custom.test).toEqual(123)
|
|
189
212
|
expect(session.read().custom.test).toEqual(123)
|
|
@@ -197,7 +220,7 @@ describe('reset()', () => {
|
|
|
197
220
|
|
|
198
221
|
describe('read()', () => {
|
|
199
222
|
test('"new" sessions get data from read()', () => {
|
|
200
|
-
const newSession = new SessionEntity({ agentIdentifier, key, expiresMs: 10 })
|
|
223
|
+
const newSession = new SessionEntity({ agentIdentifier, key, storage, expiresMs: 10 })
|
|
201
224
|
expect(newSession.isNew).toBeTruthy()
|
|
202
225
|
|
|
203
226
|
expect(newSession.read()).toEqual(expect.objectContaining({
|
|
@@ -205,13 +228,13 @@ describe('read()', () => {
|
|
|
205
228
|
expiresAt: expect.any(Number),
|
|
206
229
|
inactiveAt: expect.any(Number),
|
|
207
230
|
sessionReplay: expect.any(Number),
|
|
208
|
-
|
|
231
|
+
sessionTraceMode: expect.any(Number)
|
|
209
232
|
}))
|
|
210
233
|
})
|
|
211
234
|
|
|
212
235
|
test('"pre-existing" sessions get data from read()', () => {
|
|
213
|
-
const
|
|
214
|
-
const session = new SessionEntity({ agentIdentifier, key,
|
|
236
|
+
const storage = new LocalMemory({ [`${PREFIX}_${key}`]: { value, expiresAt: Infinity, inactiveAt: Infinity, updatedAt: Date.now(), sessionReplay: 0, sessionTraceMode: 0, custom: {} } })
|
|
237
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
215
238
|
expect(session.isNew).toBeFalsy()
|
|
216
239
|
expect(session.read()).toEqual(expect.objectContaining({
|
|
217
240
|
value,
|
|
@@ -223,7 +246,7 @@ describe('read()', () => {
|
|
|
223
246
|
|
|
224
247
|
describe('write()', () => {
|
|
225
248
|
test('write() sets data to top-level wrapper', () => {
|
|
226
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
249
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
227
250
|
expect(session.state.value).not.toEqual(value)
|
|
228
251
|
expect(session.state.expiresAt).not.toEqual(Infinity)
|
|
229
252
|
expect(session.state.inactiveAt).not.toEqual(Infinity)
|
|
@@ -236,7 +259,7 @@ describe('write()', () => {
|
|
|
236
259
|
test('write() sets data that read() can access', () => {
|
|
237
260
|
const now = Date.now()
|
|
238
261
|
jest.setSystemTime(now)
|
|
239
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
262
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
240
263
|
session.write({ ...session.state, value, expiresAt: now + 100, inactiveAt: now + 100 })
|
|
241
264
|
const read = session.read()
|
|
242
265
|
expect(read.value).toEqual(value)
|
|
@@ -245,7 +268,7 @@ describe('write()', () => {
|
|
|
245
268
|
})
|
|
246
269
|
|
|
247
270
|
test('write() does not run with invalid data', () => {
|
|
248
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
271
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
249
272
|
let out = session.write()
|
|
250
273
|
expect(out).toEqual(undefined)
|
|
251
274
|
out = session.write('string')
|
|
@@ -263,7 +286,7 @@ describe('refresh()', () => {
|
|
|
263
286
|
test('refresh sets inactiveAt to future time', () => {
|
|
264
287
|
const now = Date.now()
|
|
265
288
|
jest.setSystemTime(now)
|
|
266
|
-
const session = new SessionEntity({ agentIdentifier, key, inactiveMs: 100 })
|
|
289
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, inactiveMs: 100 })
|
|
267
290
|
expect(session.state.inactiveAt).toEqual(now + 100)
|
|
268
291
|
jest.setSystemTime(now + 1000)
|
|
269
292
|
session.refresh()
|
|
@@ -273,7 +296,7 @@ describe('refresh()', () => {
|
|
|
273
296
|
test('refresh resets the entity if expiresTimer is invalid', () => {
|
|
274
297
|
const now = Date.now()
|
|
275
298
|
jest.setSystemTime(now)
|
|
276
|
-
const session = new SessionEntity({ agentIdentifier, key, value })
|
|
299
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, value })
|
|
277
300
|
expect(session.state.value).toEqual(value)
|
|
278
301
|
session.write({ ...session.state, expiresAt: now - 1 })
|
|
279
302
|
session.refresh()
|
|
@@ -283,7 +306,7 @@ describe('refresh()', () => {
|
|
|
283
306
|
test('refresh resets the entity if inactiveTimer is invalid', () => {
|
|
284
307
|
const now = Date.now()
|
|
285
308
|
jest.setSystemTime(now)
|
|
286
|
-
const session = new SessionEntity({ agentIdentifier, key, value })
|
|
309
|
+
const session = new SessionEntity({ agentIdentifier, key, storage, value })
|
|
287
310
|
expect(session.state.value).toEqual(value)
|
|
288
311
|
session.write({ ...session.state, inactiveAt: now - 1 })
|
|
289
312
|
session.refresh()
|
|
@@ -293,7 +316,7 @@ describe('refresh()', () => {
|
|
|
293
316
|
|
|
294
317
|
describe('syncCustomAttribute()', () => {
|
|
295
318
|
test('Custom data can be managed by session entity', () => {
|
|
296
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
319
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
297
320
|
|
|
298
321
|
// if custom has never been set, and a "delete" action is triggered, do nothing
|
|
299
322
|
session.syncCustomAttribute('test', null)
|
|
@@ -315,7 +338,7 @@ describe('syncCustomAttribute()', () => {
|
|
|
315
338
|
|
|
316
339
|
test('Only runs in browser scope', () => {
|
|
317
340
|
mockBrowserScope.mockReturnValue(false)
|
|
318
|
-
const session = new SessionEntity({ agentIdentifier, key })
|
|
341
|
+
const session = new SessionEntity({ agentIdentifier, key, storage })
|
|
319
342
|
session.syncCustomAttribute('test', 1)
|
|
320
343
|
expect(session.read().custom?.test).toEqual(undefined)
|
|
321
344
|
})
|
|
@@ -5,7 +5,6 @@ import { ee } from '../event-emitter/contextual-ee'
|
|
|
5
5
|
import { Timer } from '../timer/timer'
|
|
6
6
|
import { isBrowserScope } from '../util/global-scope'
|
|
7
7
|
import { DEFAULT_EXPIRES_MS, DEFAULT_INACTIVE_MS, PREFIX } from './constants'
|
|
8
|
-
import { LocalMemory } from '../storage/local-memory'
|
|
9
8
|
import { InteractionTimer } from '../timer/interaction-timer'
|
|
10
9
|
import { wrapEvents } from '../wrap'
|
|
11
10
|
import { getModeledObject } from '../config/state/configurable'
|
|
@@ -13,6 +12,11 @@ import { handle } from '../event-emitter/handle'
|
|
|
13
12
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants'
|
|
14
13
|
import { FEATURE_NAMES } from '../../loaders/features/features'
|
|
15
14
|
|
|
15
|
+
export const MODE = {
|
|
16
|
+
OFF: 0,
|
|
17
|
+
FULL: 1,
|
|
18
|
+
ERROR: 2
|
|
19
|
+
}
|
|
16
20
|
// this is what can be stored in local storage (not enforced but probably should be)
|
|
17
21
|
// these values should sync between local storage and the parent class props
|
|
18
22
|
const model = {
|
|
@@ -20,11 +24,10 @@ const model = {
|
|
|
20
24
|
inactiveAt: 0,
|
|
21
25
|
expiresAt: 0,
|
|
22
26
|
updatedAt: Date.now(),
|
|
23
|
-
sessionReplay:
|
|
24
|
-
|
|
27
|
+
sessionReplay: MODE.OFF,
|
|
28
|
+
sessionTraceMode: MODE.OFF,
|
|
25
29
|
custom: {}
|
|
26
30
|
}
|
|
27
|
-
|
|
28
31
|
export const SESSION_EVENTS = {
|
|
29
32
|
PAUSE: 'session-pause',
|
|
30
33
|
RESET: 'session-reset',
|
|
@@ -42,16 +45,16 @@ export class SessionEntity {
|
|
|
42
45
|
this.setup(opts)
|
|
43
46
|
}
|
|
44
47
|
|
|
45
|
-
setup ({ agentIdentifier, key, value = generateRandomHexString(16), expiresMs = DEFAULT_EXPIRES_MS, inactiveMs = DEFAULT_INACTIVE_MS
|
|
46
|
-
if (!agentIdentifier || !key
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
48
|
+
setup ({ agentIdentifier, key, storage, value = generateRandomHexString(16), expiresMs = DEFAULT_EXPIRES_MS, inactiveMs = DEFAULT_INACTIVE_MS }) {
|
|
49
|
+
if (!agentIdentifier || !key || !storage) {
|
|
50
|
+
throw new Error(`Missing required field(s):${!agentIdentifier ? ' agentID' : ''}${!key ? ' key' : ''}${!storage ? ' storage' : ''}`)
|
|
51
|
+
}
|
|
52
|
+
this.agentIdentifier = agentIdentifier
|
|
53
|
+
this.storage = storage
|
|
50
54
|
this.state = {}
|
|
51
55
|
|
|
52
56
|
this.sync(model)
|
|
53
57
|
|
|
54
|
-
this.agentIdentifier = agentIdentifier
|
|
55
58
|
// key is intended to act as the k=v pair
|
|
56
59
|
this.key = key
|
|
57
60
|
// value is intended to act as the primary value of the k=v pair
|
|
@@ -183,7 +186,7 @@ export class SessionEntity {
|
|
|
183
186
|
this.sync(data) // update the parent class "state" properties with the local storage values
|
|
184
187
|
//
|
|
185
188
|
// TODO - compression would need happen here if we decide to do it
|
|
186
|
-
this.storage.set(this.lookupKey, stringify(
|
|
189
|
+
this.storage.set(this.lookupKey, stringify(this.state))
|
|
187
190
|
return data
|
|
188
191
|
} catch (e) {
|
|
189
192
|
// storage is inaccessible
|
|
@@ -207,7 +210,7 @@ export class SessionEntity {
|
|
|
207
210
|
this.setup({
|
|
208
211
|
agentIdentifier: this.agentIdentifier,
|
|
209
212
|
key: this.key,
|
|
210
|
-
|
|
213
|
+
storage: this.storage,
|
|
211
214
|
expiresMs: this.expiresMs,
|
|
212
215
|
inactiveMs: this.inactiveMs
|
|
213
216
|
})
|
|
@@ -44,8 +44,8 @@ export class InteractionTimer extends Timer {
|
|
|
44
44
|
if (state === 'hidden') this.pause()
|
|
45
45
|
// vis change --> visible is treated like a new interaction with the page
|
|
46
46
|
else {
|
|
47
|
-
this.onResume()
|
|
48
47
|
this.refresh()
|
|
48
|
+
this.onResume() // emit resume event after state updated
|
|
49
49
|
}
|
|
50
50
|
}, false, false, this.abortController?.signal)
|
|
51
51
|
}
|