@newrelic/browser-agent 1.252.0 → 1.253.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/CHANGELOG.md +18 -0
- package/README.md +6 -6
- package/dist/cjs/cdn/experimental.js +6 -2
- package/dist/cjs/cdn/spa.js +5 -3
- package/dist/cjs/common/aggregate/aggregator.js +1 -8
- package/dist/cjs/common/config/state/init.js +7 -0
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/context/observation-context-manager.js +56 -0
- package/dist/cjs/common/event-emitter/contextual-ee.js +12 -9
- package/dist/cjs/common/session/constants.js +2 -1
- package/dist/cjs/common/session/session-entity.js +3 -1
- package/dist/cjs/common/timing/nav-timing.js +8 -3
- package/dist/cjs/common/timing/now.js +1 -1
- package/dist/cjs/common/util/feature-flags.js +1 -1
- package/dist/cjs/common/wrap/index.js +0 -7
- package/dist/cjs/common/wrap/wrap-events.js +2 -2
- package/dist/cjs/common/wrap/wrap-fetch.js +2 -1
- package/dist/cjs/common/wrap/wrap-function.js +5 -7
- package/dist/cjs/common/wrap/wrap-promise.js +2 -1
- package/dist/cjs/features/ajax/aggregate/index.js +34 -16
- package/dist/cjs/features/jserrors/aggregate/index.js +77 -66
- package/dist/cjs/features/page_view_event/aggregate/index.js +1 -1
- package/dist/cjs/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/dist/cjs/features/session_replay/aggregate/index.js +96 -94
- package/dist/cjs/features/session_replay/constants.js +5 -1
- package/dist/cjs/features/session_replay/instrument/index.js +24 -8
- package/dist/cjs/features/session_replay/shared/recorder.js +5 -4
- package/dist/cjs/features/session_replay/shared/stylesheet-evaluator.js +8 -7
- package/dist/cjs/features/session_replay/shared/utils.js +26 -0
- package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +50 -0
- package/dist/cjs/features/soft_navigations/aggregate/bel-node.js +29 -0
- package/dist/cjs/features/soft_navigations/aggregate/index.js +263 -0
- package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +62 -0
- package/dist/cjs/features/soft_navigations/aggregate/interaction.js +146 -0
- package/dist/cjs/features/soft_navigations/constants.js +31 -0
- package/dist/cjs/features/soft_navigations/index.js +12 -0
- package/dist/cjs/features/soft_navigations/instrument/index.js +79 -0
- package/dist/cjs/features/spa/aggregate/index.js +4 -4
- package/dist/cjs/features/utils/agent-session.js +2 -1
- package/dist/cjs/features/utils/instrument-base.js +6 -9
- package/dist/cjs/features/utils/lazy-feature-loader.js +2 -0
- package/dist/cjs/loaders/agent-base.js +18 -3
- package/dist/cjs/loaders/agent.js +15 -18
- package/dist/cjs/loaders/api/api-methods.js +9 -0
- package/dist/cjs/loaders/api/api.js +17 -18
- package/dist/cjs/loaders/configure/configure.js +5 -2
- package/dist/cjs/loaders/features/enabled-features.js +1 -1
- package/dist/cjs/loaders/features/features.js +3 -1
- package/dist/esm/cdn/experimental.js +5 -2
- package/dist/esm/cdn/spa.js +3 -1
- package/dist/esm/common/aggregate/aggregator.js +1 -8
- package/dist/esm/common/config/state/init.js +7 -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/context/observation-context-manager.js +49 -0
- package/dist/esm/common/event-emitter/contextual-ee.js +12 -9
- package/dist/esm/common/session/constants.js +1 -0
- package/dist/esm/common/session/session-entity.js +3 -1
- package/dist/esm/common/timing/nav-timing.js +8 -3
- package/dist/esm/common/timing/now.js +1 -1
- package/dist/esm/common/util/feature-flags.js +1 -1
- package/dist/esm/common/wrap/index.js +1 -2
- package/dist/esm/common/wrap/wrap-events.js +3 -3
- package/dist/esm/common/wrap/wrap-fetch.js +3 -2
- package/dist/esm/common/wrap/wrap-function.js +4 -5
- package/dist/esm/common/wrap/wrap-promise.js +3 -2
- package/dist/esm/features/ajax/aggregate/index.js +36 -18
- package/dist/esm/features/jserrors/aggregate/index.js +77 -66
- package/dist/esm/features/page_view_event/aggregate/index.js +1 -1
- package/dist/esm/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/dist/esm/features/session_replay/aggregate/index.js +97 -95
- package/dist/esm/features/session_replay/constants.js +4 -0
- package/dist/esm/features/session_replay/instrument/index.js +25 -9
- package/dist/esm/features/session_replay/shared/recorder.js +5 -4
- package/dist/esm/features/session_replay/shared/stylesheet-evaluator.js +8 -7
- package/dist/esm/features/session_replay/shared/utils.js +17 -0
- package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +43 -0
- package/dist/esm/features/soft_navigations/aggregate/bel-node.js +22 -0
- package/dist/esm/features/soft_navigations/aggregate/index.js +256 -0
- package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +55 -0
- package/dist/esm/features/soft_navigations/aggregate/interaction.js +140 -0
- package/dist/esm/features/soft_navigations/constants.js +25 -0
- package/dist/esm/features/soft_navigations/index.js +1 -0
- package/dist/esm/features/soft_navigations/instrument/index.js +73 -0
- package/dist/esm/features/spa/aggregate/index.js +4 -4
- package/dist/esm/features/utils/agent-session.js +2 -1
- package/dist/esm/features/utils/instrument-base.js +7 -10
- package/dist/esm/features/utils/lazy-feature-loader.js +2 -0
- package/dist/esm/loaders/agent-base.js +18 -3
- package/dist/esm/loaders/agent.js +15 -18
- package/dist/esm/loaders/api/api-methods.js +3 -0
- package/dist/esm/loaders/api/api.js +17 -17
- package/dist/esm/loaders/configure/configure.js +5 -2
- package/dist/esm/loaders/features/enabled-features.js +1 -1
- package/dist/esm/loaders/features/features.js +3 -1
- package/dist/types/common/aggregate/aggregator.d.ts.map +1 -1
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/context/event-context.d.ts.map +1 -0
- package/dist/types/common/context/observation-context-manager.d.ts +28 -0
- package/dist/types/common/context/observation-context-manager.d.ts.map +1 -0
- package/dist/types/common/event-emitter/contextual-ee.d.ts +2 -2
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/session/constants.d.ts +1 -0
- package/dist/types/common/session/constants.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts +0 -1
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/timing/nav-timing.d.ts.map +1 -1
- package/dist/types/common/wrap/index.d.ts +1 -2
- package/dist/types/common/wrap/index.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-function.d.ts +0 -1
- package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +4 -3
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/initialized-features.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/constants.d.ts +4 -0
- package/dist/types/features/session_replay/constants.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/stylesheet-evaluator.d.ts.map +1 -1
- package/dist/types/features/session_replay/shared/utils.d.ts +4 -0
- package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +19 -0
- package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts +16 -0
- package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +36 -0
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts +12 -0
- package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +50 -0
- package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/constants.d.ts +20 -0
- package/dist/types/features/soft_navigations/constants.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/index.d.ts +2 -0
- package/dist/types/features/soft_navigations/index.d.ts.map +1 -0
- package/dist/types/features/soft_navigations/instrument/index.d.ts +7 -0
- package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -0
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +1 -7
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +5 -1
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts +2 -2
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/api-methods.d.ts +3 -0
- package/dist/types/loaders/api/api-methods.d.ts.map +1 -0
- package/dist/types/loaders/api/api.d.ts +3 -6
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +1 -0
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/dist/types/loaders/micro-agent.d.ts +0 -1
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cdn/experimental.js +4 -2
- package/src/cdn/spa.js +3 -1
- package/src/common/aggregate/aggregator.js +2 -11
- package/src/common/config/state/init.js +3 -1
- package/src/common/context/observation-context-manager.js +55 -0
- package/src/common/event-emitter/contextual-ee.js +20 -10
- package/src/common/session/constants.js +1 -0
- package/src/common/session/session-entity.js +3 -1
- package/src/common/timing/nav-timing.js +7 -3
- package/src/common/timing/now.js +1 -1
- package/src/common/util/feature-flags.js +1 -1
- package/src/common/wrap/index.js +1 -2
- package/src/common/wrap/wrap-events.js +3 -3
- package/src/common/wrap/wrap-fetch.js +3 -2
- package/src/common/wrap/wrap-function.js +4 -6
- package/src/common/wrap/wrap-promise.js +3 -2
- package/src/features/ajax/aggregate/index.js +36 -18
- package/src/features/jserrors/aggregate/index.js +70 -73
- package/src/features/page_view_event/aggregate/index.js +1 -1
- package/src/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/src/features/session_replay/aggregate/index.js +92 -95
- package/src/features/session_replay/constants.js +5 -0
- package/src/features/session_replay/instrument/index.js +24 -9
- package/src/features/session_replay/shared/recorder.js +5 -4
- package/src/features/session_replay/shared/stylesheet-evaluator.js +8 -7
- package/src/features/session_replay/shared/utils.js +19 -0
- package/src/features/soft_navigations/aggregate/ajax-node.js +57 -0
- package/src/features/soft_navigations/aggregate/bel-node.js +26 -0
- package/src/features/soft_navigations/aggregate/index.js +254 -0
- package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +53 -0
- package/src/features/soft_navigations/aggregate/interaction.js +159 -0
- package/src/features/soft_navigations/constants.js +29 -0
- package/src/features/soft_navigations/index.js +1 -0
- package/src/features/soft_navigations/instrument/index.js +67 -0
- package/src/features/spa/aggregate/index.js +5 -4
- package/src/features/utils/agent-session.js +2 -1
- package/src/features/utils/instrument-base.js +7 -10
- package/src/features/utils/lazy-feature-loader.js +2 -0
- package/src/loaders/agent-base.js +18 -3
- package/src/loaders/agent.js +18 -17
- package/src/loaders/api/api-methods.js +12 -0
- package/src/loaders/api/api.js +17 -28
- package/src/loaders/configure/configure.js +4 -1
- package/src/loaders/features/enabled-features.js +1 -1
- package/src/loaders/features/features.js +3 -1
- package/dist/cjs/common/wrap/wrap-raf.js +0 -55
- package/dist/esm/common/wrap/wrap-raf.js +0 -48
- package/dist/types/common/event-emitter/event-context.d.ts.map +0 -1
- package/dist/types/common/wrap/wrap-raf.d.ts +0 -16
- package/dist/types/common/wrap/wrap-raf.d.ts.map +0 -1
- package/src/common/wrap/wrap-raf.js +0 -52
- /package/dist/cjs/common/{event-emitter → context}/event-context.js +0 -0
- /package/dist/esm/common/{event-emitter → context}/event-context.js +0 -0
- /package/dist/types/common/{event-emitter → context}/event-context.d.ts +0 -0
- /package/src/common/{event-emitter → context}/event-context.js +0 -0
|
@@ -19,6 +19,7 @@ var _runtime = require("../../../common/constants/runtime");
|
|
|
19
19
|
var _constants = require("../constants");
|
|
20
20
|
var _features = require("../../../loaders/features/features");
|
|
21
21
|
var _aggregateBase = require("../../utils/aggregate-base");
|
|
22
|
+
var _nreum = require("../../../common/window/nreum");
|
|
22
23
|
/*
|
|
23
24
|
* Copyright 2020 New Relic Corporation. All rights reserved.
|
|
24
25
|
* SPDX-License-Identifier: Apache-2.0
|
|
@@ -37,21 +38,20 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
37
38
|
this.stackReported = {};
|
|
38
39
|
this.observedAt = {};
|
|
39
40
|
this.pageviewReported = {};
|
|
40
|
-
this.
|
|
41
|
+
this.bufferedErrorsUnderSpa = {};
|
|
41
42
|
this.currentBody = undefined;
|
|
42
43
|
this.errorOnPage = false;
|
|
43
44
|
|
|
44
45
|
// this will need to change to match whatever ee we use in the instrument
|
|
45
|
-
this.ee.on('
|
|
46
|
-
|
|
47
|
-
// this will need to change to match whatever ee we use in the instrument
|
|
48
|
-
this.ee.on('interactionDiscarded', interaction => this.onInteractionDiscarded(interaction));
|
|
46
|
+
this.ee.on('interactionDone', (interaction, wasSaved) => this.onInteractionDone(interaction, wasSaved));
|
|
49
47
|
(0, _registerHandler.registerHandler)('err', function () {
|
|
50
48
|
return _this.storeError(...arguments);
|
|
51
49
|
}, this.featureName, this.ee);
|
|
52
50
|
(0, _registerHandler.registerHandler)('ierr', function () {
|
|
53
51
|
return _this.storeError(...arguments);
|
|
54
52
|
}, this.featureName, this.ee);
|
|
53
|
+
(0, _registerHandler.registerHandler)('softNavFlush', (interactionId, wasFinished, softNavAttrs) => this.onSoftNavNotification(interactionId, wasFinished, softNavAttrs), this.featureName, this.ee); // when an ixn is done or cancelled
|
|
54
|
+
|
|
55
55
|
const harvestTimeSeconds = (0, _config.getConfigurationValue)(this.agentIdentifier, 'jserrors.harvestTimeSeconds') || 10;
|
|
56
56
|
const scheduler = new _harvestScheduler.HarvestScheduler('jserrors', {
|
|
57
57
|
onFinished: function () {
|
|
@@ -193,82 +193,93 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
193
193
|
time
|
|
194
194
|
};
|
|
195
195
|
|
|
196
|
-
//
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
(0, _handle.handle)('errorAgg',
|
|
200
|
-
(0, _handle.handle)('errorAgg', msg, undefined, _features.FEATURE_NAMES.spa, this.ee);
|
|
201
|
-
(0, _handle.handle)('errorAgg', msg, undefined, _features.FEATURE_NAMES.sessionReplay, this.ee);
|
|
202
|
-
|
|
196
|
+
// Trace sends the error in its payload, and both trace & replay simply listens for any error to occur.
|
|
197
|
+
const jsErrorEvent = [type, bucketHash, params, newMetrics, customAttributes];
|
|
198
|
+
(0, _handle.handle)('errorAgg', jsErrorEvent, undefined, _features.FEATURE_NAMES.sessionTrace, this.ee);
|
|
199
|
+
(0, _handle.handle)('errorAgg', jsErrorEvent, undefined, _features.FEATURE_NAMES.sessionReplay, this.ee);
|
|
203
200
|
// still send EE events for other features such as above, but stop this one from aggregating internal data
|
|
204
201
|
if (this.blocked) return;
|
|
205
|
-
|
|
206
|
-
if
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
202
|
+
const softNavInUse = Boolean((0, _nreum.getNREUMInitializedAgent)(this.agentIdentifier)?.features[_features.FEATURE_NAMES.softNav]);
|
|
203
|
+
// Note: the following are subject to potential race cond wherein if the other feature aren't fully initialized, it'll be treated as there being no associated interaction.
|
|
204
|
+
// They each will also tack on their respective properties to the params object as part of the decision flow.
|
|
205
|
+
if (softNavInUse) (0, _handle.handle)('jserror', [params, time], undefined, _features.FEATURE_NAMES.softNav, this.ee);else (0, _handle.handle)('errorAgg', jsErrorEvent, undefined, _features.FEATURE_NAMES.spa, this.ee);
|
|
206
|
+
if (params.browserInteractionId && !params._softNavFinished) {
|
|
207
|
+
// hold onto the error until the in-progress interaction is done, eithered saved or discarded
|
|
208
|
+
this.bufferedErrorsUnderSpa[params.browserInteractionId] ??= [];
|
|
209
|
+
this.bufferedErrorsUnderSpa[params.browserInteractionId].push(jsErrorEvent);
|
|
210
|
+
} else if (params._interactionId != null) {
|
|
211
|
+
// same as above, except tailored for the way old spa does it
|
|
212
|
+
this.bufferedErrorsUnderSpa[params._interactionId] = this.bufferedErrorsUnderSpa[params._interactionId] || [];
|
|
213
|
+
this.bufferedErrorsUnderSpa[params._interactionId].push(jsErrorEvent);
|
|
210
214
|
} else {
|
|
211
|
-
//
|
|
212
|
-
|
|
213
|
-
(
|
|
214
|
-
if (customAttributes) {
|
|
215
|
-
(0, _mapOwn.mapOwn)(customAttributes, setCustom);
|
|
216
|
-
}
|
|
217
|
-
var jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(customParams));
|
|
218
|
-
var aggregateHash = bucketHash + ':' + jsAttributesHash;
|
|
219
|
-
this.aggregator.store(type, aggregateHash, params, newMetrics, customParams);
|
|
215
|
+
// Either there is no interaction (then all these params properties will be undefined) OR there's a related soft navigation that's already completed.
|
|
216
|
+
// The old spa does not look up completed interactions at all, so there's no need to consider it.
|
|
217
|
+
this.#storeJserrorForHarvest(jsErrorEvent, params.browserInteractionId !== undefined, params._softNavAttributes);
|
|
220
218
|
}
|
|
219
|
+
}
|
|
220
|
+
#storeJserrorForHarvest(errorInfoArr, softNavOccurredFinished) {
|
|
221
|
+
let softNavCustomAttrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
222
|
+
let [type, bucketHash, params, newMetrics, localAttrs] = errorInfoArr;
|
|
223
|
+
const allCustomAttrs = {};
|
|
224
|
+
if (softNavOccurredFinished) {
|
|
225
|
+
Object.entries(softNavCustomAttrs).forEach(_ref => {
|
|
226
|
+
let [k, v] = _ref;
|
|
227
|
+
return setCustom(k, v);
|
|
228
|
+
}); // when an ixn finishes, it'll include stuff in jsAttributes + attrs specific to the ixn
|
|
229
|
+
bucketHash += params.browserInteractionId;
|
|
230
|
+
delete params._softNavAttributes; // cleanup temp properties from synchronous evaluation; this is harmless when async from soft nav (properties DNE)
|
|
231
|
+
delete params._softNavFinished;
|
|
232
|
+
} else {
|
|
233
|
+
// interaction was cancelled -> error should not be associated OR there was no interaction
|
|
234
|
+
Object.entries((0, _config.getInfo)(this.agentIdentifier).jsAttributes).forEach(_ref2 => {
|
|
235
|
+
let [k, v] = _ref2;
|
|
236
|
+
return setCustom(k, v);
|
|
237
|
+
});
|
|
238
|
+
delete params.browserInteractionId;
|
|
239
|
+
}
|
|
240
|
+
if (localAttrs) Object.entries(localAttrs).forEach(_ref3 => {
|
|
241
|
+
let [k, v] = _ref3;
|
|
242
|
+
return setCustom(k, v);
|
|
243
|
+
}); // local custom attrs are applied in either case with the highest precedence
|
|
244
|
+
|
|
245
|
+
const jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(allCustomAttrs));
|
|
246
|
+
const aggregateHash = bucketHash + ':' + jsAttributesHash;
|
|
247
|
+
this.aggregator.store(type, aggregateHash, params, newMetrics, allCustomAttrs);
|
|
221
248
|
function setCustom(key, val) {
|
|
222
|
-
|
|
249
|
+
allCustomAttrs[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
|
|
223
250
|
}
|
|
224
251
|
}
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
var
|
|
231
|
-
|
|
232
|
-
(0, _mapOwn.mapOwn)(interaction.root.attrs.custom, setCustom);
|
|
233
|
-
(0, _mapOwn.mapOwn)(
|
|
252
|
+
|
|
253
|
+
// TO-DO: Remove this function when old spa is taken out. #storeJserrorForHarvest handles the work with the softnav feature.
|
|
254
|
+
onInteractionDone(interaction, wasSaved) {
|
|
255
|
+
if (!this.bufferedErrorsUnderSpa[interaction.id] || this.blocked) return;
|
|
256
|
+
this.bufferedErrorsUnderSpa[interaction.id].forEach(item => {
|
|
257
|
+
var allCustomAttrs = {};
|
|
258
|
+
const localCustomAttrs = item[4];
|
|
259
|
+
(0, _mapOwn.mapOwn)(interaction.root.attrs.custom, setCustom); // tack on custom attrs from the interaction
|
|
260
|
+
(0, _mapOwn.mapOwn)(localCustomAttrs, setCustom);
|
|
234
261
|
var params = item[2];
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
params.parentNodeId = params._interactionNodeId.toString();
|
|
239
|
-
delete params._interactionNodeId;
|
|
240
|
-
}
|
|
241
|
-
var hash = item[1] + interaction.root.attrs.id;
|
|
242
|
-
var jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(customParams));
|
|
243
|
-
var aggregateHash = hash + ':' + jsAttributesHash;
|
|
244
|
-
this.aggregator.store(item[0], aggregateHash, params, item[3], customParams);
|
|
245
|
-
function setCustom(key, val) {
|
|
246
|
-
customParams[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
|
|
262
|
+
if (wasSaved) {
|
|
263
|
+
params.browserInteractionId = interaction.root.attrs.id;
|
|
264
|
+
if (params._interactionNodeId) params.parentNodeId = params._interactionNodeId.toString();
|
|
247
265
|
}
|
|
248
|
-
});
|
|
249
|
-
delete this.errorCache[interaction.id];
|
|
250
|
-
}
|
|
251
|
-
onInteractionDiscarded(interaction) {
|
|
252
|
-
if (!this.errorCache || !this.errorCache[interaction.id] || this.blocked) return;
|
|
253
|
-
this.errorCache[interaction.id].forEach(item => {
|
|
254
|
-
var customParams = {};
|
|
255
|
-
var globalCustomParams = item[4];
|
|
256
|
-
var localCustomParams = item[5];
|
|
257
|
-
(0, _mapOwn.mapOwn)(globalCustomParams, setCustom);
|
|
258
|
-
(0, _mapOwn.mapOwn)(interaction.root.attrs.custom, setCustom);
|
|
259
|
-
(0, _mapOwn.mapOwn)(localCustomParams, setCustom);
|
|
260
|
-
var params = item[2];
|
|
261
266
|
delete params._interactionId;
|
|
262
267
|
delete params._interactionNodeId;
|
|
263
|
-
var hash = item[1];
|
|
264
|
-
var jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(
|
|
268
|
+
var hash = wasSaved ? item[1] + interaction.root.attrs.id : item[1];
|
|
269
|
+
var jsAttributesHash = (0, _stringHashCode.stringHashCode)((0, _stringify.stringify)(allCustomAttrs));
|
|
265
270
|
var aggregateHash = hash + ':' + jsAttributesHash;
|
|
266
|
-
this.aggregator.store(item[0], aggregateHash,
|
|
271
|
+
this.aggregator.store(item[0], aggregateHash, params, item[3], allCustomAttrs);
|
|
267
272
|
function setCustom(key, val) {
|
|
268
|
-
|
|
273
|
+
allCustomAttrs[key] = val && typeof val === 'object' ? (0, _stringify.stringify)(val) : val;
|
|
269
274
|
}
|
|
270
275
|
});
|
|
271
|
-
delete this.
|
|
276
|
+
delete this.bufferedErrorsUnderSpa[interaction.id];
|
|
277
|
+
}
|
|
278
|
+
onSoftNavNotification(interactionId, wasFinished, softNavAttrs) {
|
|
279
|
+
if (this.blocked) return;
|
|
280
|
+
this.bufferedErrorsUnderSpa[interactionId]?.forEach(jsErrorEvent => this.#storeJserrorForHarvest(jsErrorEvent, wasFinished, softNavAttrs) // this should not modify the re-used softNavAttrs contents
|
|
281
|
+
);
|
|
282
|
+
delete this.bufferedErrorsUnderSpa[interactionId]; // wipe the list of jserrors so they aren't duplicated by another call to the same id
|
|
272
283
|
}
|
|
273
284
|
}
|
|
274
285
|
exports.Aggregate = Aggregate;
|
|
@@ -137,7 +137,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
137
137
|
this.drain();
|
|
138
138
|
} catch (err) {
|
|
139
139
|
this.ee.abort();
|
|
140
|
-
(0, _console.warn)('RUM call failed. Agent shutting down.');
|
|
140
|
+
(0, _console.warn)('RUM call failed. Agent shutting down.', err);
|
|
141
141
|
}
|
|
142
142
|
}
|
|
143
143
|
});
|
|
@@ -58,103 +58,100 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
58
58
|
this.recorder = args?.recorder;
|
|
59
59
|
if (this.recorder) this.recorder.parent = this;
|
|
60
60
|
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/Enabled'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
61
|
-
const shouldSetup = (0, _config.getConfigurationValue)(agentIdentifier, 'privacy.cookies_enabled') === true && (0, _config.getConfigurationValue)(agentIdentifier, 'session_trace.enabled') === true;
|
|
62
|
-
if (shouldSetup) {
|
|
63
|
-
// The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
|
|
64
|
-
this.ee.on(_constants3.SESSION_EVENTS.RESET, () => {
|
|
65
|
-
this.scheduler.runHarvest();
|
|
66
|
-
this.abort(_constants.ABORT_REASONS.RESET);
|
|
67
|
-
});
|
|
68
|
-
|
|
69
|
-
// The SessionEntity class can emit a message indicating the session was paused (visibility change). This feature must stop recording if that occurs.
|
|
70
|
-
this.ee.on(_constants3.SESSION_EVENTS.PAUSE, () => {
|
|
71
|
-
this.recorder?.stopRecording();
|
|
72
|
-
});
|
|
73
|
-
// The SessionEntity class can emit a message indicating the session was resumed (visibility change). This feature must start running again (if already running) if that occurs.
|
|
74
|
-
this.ee.on(_constants3.SESSION_EVENTS.RESUME, () => {
|
|
75
|
-
if (!this.recorder) return;
|
|
76
|
-
// if the mode changed on a different tab, it needs to update this instance to match
|
|
77
|
-
const {
|
|
78
|
-
session
|
|
79
|
-
} = (0, _config.getRuntime)(this.agentIdentifier);
|
|
80
|
-
this.mode = session.state.sessionReplayMode;
|
|
81
|
-
if (!this.initialized || this.mode === _constants3.MODE.OFF) return;
|
|
82
|
-
this.recorder?.startRecording();
|
|
83
|
-
});
|
|
84
|
-
this.ee.on(_constants3.SESSION_EVENTS.UPDATE, (type, data) => {
|
|
85
|
-
if (!this.recorder || !this.initialized || this.blocked || type !== _constants3.SESSION_EVENT_TYPES.CROSS_TAB) return;
|
|
86
|
-
if (this.mode !== _constants3.MODE.OFF && data.sessionReplayMode === _constants3.MODE.OFF) this.abort(_constants.ABORT_REASONS.CROSS_TAB);
|
|
87
|
-
this.mode = data.sessionReplay;
|
|
88
|
-
});
|
|
89
61
|
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
raw: true
|
|
96
|
-
}, this);
|
|
97
|
-
if (this.recorder?.getEvents().type === 'preloaded') {
|
|
98
|
-
this.prepUtils().then(() => {
|
|
99
|
-
this.scheduler.runHarvest();
|
|
100
|
-
});
|
|
101
|
-
}
|
|
102
|
-
(0, _registerHandler.registerHandler)('recordReplay', () => {
|
|
103
|
-
// if it has aborted or BCS returned bad entitlements, do not allow
|
|
104
|
-
if (this.blocked || !this.entitled) return;
|
|
105
|
-
// if it isnt already (fully) initialized... initialize it
|
|
106
|
-
if (!this.recorder) this.initializeRecording(false, true, true);
|
|
107
|
-
// its been initialized and imported the recorder but its not recording (mode === off || error)
|
|
108
|
-
else if (this.mode !== _constants3.MODE.FULL) this.switchToFull();
|
|
109
|
-
// if it gets all the way to here, that means a full session is already recording... do nothing
|
|
110
|
-
}, this.featureName, this.ee);
|
|
111
|
-
(0, _registerHandler.registerHandler)('pauseReplay', () => {
|
|
112
|
-
this.forceStop(this.mode !== _constants3.MODE.ERROR);
|
|
113
|
-
}, this.featureName, this.ee);
|
|
62
|
+
// The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
|
|
63
|
+
this.ee.on(_constants3.SESSION_EVENTS.RESET, () => {
|
|
64
|
+
this.scheduler.runHarvest();
|
|
65
|
+
this.abort(_constants.ABORT_REASONS.RESET);
|
|
66
|
+
});
|
|
114
67
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
(
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
124
|
-
}, this.featureName, this.ee);
|
|
68
|
+
// The SessionEntity class can emit a message indicating the session was paused (visibility change). This feature must stop recording if that occurs.
|
|
69
|
+
this.ee.on(_constants3.SESSION_EVENTS.PAUSE, () => {
|
|
70
|
+
this.recorder?.stopRecording();
|
|
71
|
+
});
|
|
72
|
+
// The SessionEntity class can emit a message indicating the session was resumed (visibility change). This feature must start running again (if already running) if that occurs.
|
|
73
|
+
this.ee.on(_constants3.SESSION_EVENTS.RESUME, () => {
|
|
74
|
+
if (!this.recorder) return;
|
|
75
|
+
// if the mode changed on a different tab, it needs to update this instance to match
|
|
125
76
|
const {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
let [flagOn] = _ref;
|
|
138
|
-
this.entitled = flagOn;
|
|
139
|
-
if (!this.entitled && this.recorder?.recording) {
|
|
140
|
-
this.recorder.abort(_constants.ABORT_REASONS.ENTITLEMENTS);
|
|
141
|
-
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/EnabledNotEntitled/Detected'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
142
|
-
}
|
|
143
|
-
this.initializeRecording(Math.random() * 100 < error_sampling_rate, Math.random() * 100 < sampling_rate);
|
|
144
|
-
}).then(() => _sharedChannel.sharedChannel.onReplayReady(this.mode)); // notify watchers that replay started with the mode
|
|
77
|
+
session
|
|
78
|
+
} = (0, _config.getRuntime)(this.agentIdentifier);
|
|
79
|
+
this.mode = session.state.sessionReplayMode;
|
|
80
|
+
if (!this.initialized || this.mode === _constants3.MODE.OFF) return;
|
|
81
|
+
this.recorder?.startRecording();
|
|
82
|
+
});
|
|
83
|
+
this.ee.on(_constants3.SESSION_EVENTS.UPDATE, (type, data) => {
|
|
84
|
+
if (!this.recorder || !this.initialized || this.blocked || type !== _constants3.SESSION_EVENT_TYPES.CROSS_TAB) return;
|
|
85
|
+
if (this.mode !== _constants3.MODE.OFF && data.sessionReplayMode === _constants3.MODE.OFF) this.abort(_constants.ABORT_REASONS.CROSS_TAB);
|
|
86
|
+
this.mode = data.sessionReplay;
|
|
87
|
+
});
|
|
145
88
|
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
89
|
+
// Bespoke logic for blobs endpoint.
|
|
90
|
+
this.scheduler = new _harvestScheduler.HarvestScheduler('browser/blobs', {
|
|
91
|
+
onFinished: this.onHarvestFinished.bind(this),
|
|
92
|
+
retryDelay: this.harvestTimeSeconds,
|
|
93
|
+
getPayload: this.prepareHarvest.bind(this),
|
|
94
|
+
raw: true
|
|
95
|
+
}, this);
|
|
96
|
+
(0, _registerHandler.registerHandler)(_constants.SR_EVENT_EMITTER_TYPES.RECORD, () => {
|
|
97
|
+
// if it has aborted or BCS returned bad entitlements, do not allow
|
|
98
|
+
if (this.blocked || !this.entitled) return;
|
|
99
|
+
// if it isnt already (fully) initialized... initialize it
|
|
100
|
+
if (!this.recorder) this.initializeRecording(false, true, true);
|
|
101
|
+
// its been initialized and imported the recorder but its not recording (mode === off || error)
|
|
102
|
+
else if (this.mode !== _constants3.MODE.FULL) this.switchToFull();
|
|
103
|
+
// if it gets all the way to here, that means a full session is already recording... do nothing
|
|
104
|
+
}, this.featureName, this.ee);
|
|
105
|
+
(0, _registerHandler.registerHandler)(_constants.SR_EVENT_EMITTER_TYPES.PAUSE, () => {
|
|
106
|
+
this.forceStop(this.mode !== _constants3.MODE.ERROR);
|
|
107
|
+
}, this.featureName, this.ee);
|
|
108
|
+
|
|
109
|
+
// Wait for an error to be reported. This currently is wrapped around the "Error" feature. This is a feature-feature dependency.
|
|
110
|
+
// This was to ensure that all errors, including those on the page before load and those handled with "noticeError" are accounted for. Needs evalulation
|
|
111
|
+
(0, _registerHandler.registerHandler)('errorAgg', e => {
|
|
112
|
+
this.errorNoticed = true;
|
|
113
|
+
if (this.recorder) this.recorder.currentBufferTarget.hasError = true;
|
|
114
|
+
// run once
|
|
115
|
+
if (this.mode === _constants3.MODE.ERROR && _runtime.globalScope?.document.visibilityState === 'visible') {
|
|
116
|
+
this.switchToFull();
|
|
117
|
+
}
|
|
118
|
+
}, this.featureName, this.ee);
|
|
119
|
+
const {
|
|
120
|
+
error_sampling_rate,
|
|
121
|
+
sampling_rate,
|
|
122
|
+
autoStart,
|
|
123
|
+
block_selector,
|
|
124
|
+
mask_text_selector,
|
|
125
|
+
mask_all_inputs,
|
|
126
|
+
inline_stylesheet,
|
|
127
|
+
inline_images,
|
|
128
|
+
collect_fonts
|
|
129
|
+
} = (0, _config.getConfigurationValue)(this.agentIdentifier, 'session_replay');
|
|
130
|
+
this.waitForFlags(['sr']).then(_ref => {
|
|
131
|
+
let [flagOn] = _ref;
|
|
132
|
+
this.entitled = flagOn;
|
|
133
|
+
if (!this.entitled && this.recorder?.recording) {
|
|
134
|
+
this.abort(_constants.ABORT_REASONS.ENTITLEMENTS);
|
|
135
|
+
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/EnabledNotEntitled/Detected'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
this.initializeRecording(Math.random() * 100 < error_sampling_rate, Math.random() * 100 < sampling_rate);
|
|
139
|
+
}).then(() => {
|
|
140
|
+
if (this.mode === _constants3.MODE.OFF) args?.recorder?.stopRecording(); // stop any conservative preload recording launched by instrument
|
|
141
|
+
_sharedChannel.sharedChannel.onReplayReady(this.mode); // notify watchers that replay started with the mode
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
/** Detect if the default configs have been altered and report a SM. This is useful to evaluate what the reasonable defaults are across a customer base over time */
|
|
145
|
+
if (!autoStart) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/AutoStart/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
146
|
+
if (collect_fonts === true) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/CollectFonts/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
147
|
+
if (inline_stylesheet !== true) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/InlineStylesheet/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
148
|
+
if (inline_images === true) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/InlineImages/Modifed'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
149
|
+
if (mask_all_inputs !== true) (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/MaskAllInputs/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
150
|
+
if (block_selector !== '[data-nr-block]') (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/BlockSelector/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
151
|
+
if (mask_text_selector !== '*') (0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/MaskTextSelector/Modified'], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
152
|
+
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/SamplingRate/Value', sampling_rate], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
153
|
+
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ['Config/SessionReplay/ErrorSamplingRate/Value', error_sampling_rate], undefined, _features.FEATURE_NAMES.metrics, this.ee);
|
|
154
|
+
this.drain();
|
|
158
155
|
}
|
|
159
156
|
switchToFull() {
|
|
160
157
|
this.mode = _constants3.MODE.FULL;
|
|
@@ -202,6 +199,11 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
202
199
|
return;
|
|
203
200
|
}
|
|
204
201
|
}
|
|
202
|
+
if (this.recorder?.getEvents().type === 'preloaded') {
|
|
203
|
+
this.prepUtils().then(() => {
|
|
204
|
+
this.scheduler.runHarvest();
|
|
205
|
+
});
|
|
206
|
+
}
|
|
205
207
|
if (!this.recorder) {
|
|
206
208
|
try {
|
|
207
209
|
// Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
|
|
@@ -394,7 +396,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
394
396
|
});
|
|
395
397
|
this.recorder?.clearTimestamps?.();
|
|
396
398
|
this.ee.emit('REPLAY_ABORTED');
|
|
397
|
-
this.recorder?.clearBuffer?.();
|
|
399
|
+
while (this.recorder?.getEvents().events.length) this.recorder?.clearBuffer?.();
|
|
398
400
|
}
|
|
399
401
|
syncWithSessionManager() {
|
|
400
402
|
let state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
@@ -3,10 +3,14 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
-
exports.RRWEB_EVENT_TYPES = exports.QUERY_PARAM_PADDING = exports.MAX_PAYLOAD_SIZE = exports.IDEAL_PAYLOAD_SIZE = exports.FEATURE_NAME = exports.CHECKOUT_MS = exports.AVG_COMPRESSION = exports.ABORT_REASONS = void 0;
|
|
6
|
+
exports.SR_EVENT_EMITTER_TYPES = exports.RRWEB_EVENT_TYPES = exports.QUERY_PARAM_PADDING = exports.MAX_PAYLOAD_SIZE = exports.IDEAL_PAYLOAD_SIZE = exports.FEATURE_NAME = exports.CHECKOUT_MS = exports.AVG_COMPRESSION = exports.ABORT_REASONS = void 0;
|
|
7
7
|
var _constants = require("../../common/session/constants");
|
|
8
8
|
var _features = require("../../loaders/features/features");
|
|
9
9
|
const FEATURE_NAME = exports.FEATURE_NAME = _features.FEATURE_NAMES.sessionReplay;
|
|
10
|
+
const SR_EVENT_EMITTER_TYPES = exports.SR_EVENT_EMITTER_TYPES = {
|
|
11
|
+
RECORD: 'recordReplay',
|
|
12
|
+
PAUSE: 'pauseReplay'
|
|
13
|
+
};
|
|
10
14
|
const AVG_COMPRESSION = exports.AVG_COMPRESSION = 0.12;
|
|
11
15
|
const RRWEB_EVENT_TYPES = exports.RRWEB_EVENT_TYPES = {
|
|
12
16
|
DomContentLoaded: 0,
|
|
@@ -7,6 +7,7 @@ exports.Instrument = void 0;
|
|
|
7
7
|
var _constants = require("../../../common/session/constants");
|
|
8
8
|
var _instrumentBase = require("../../utils/instrument-base");
|
|
9
9
|
var _constants2 = require("../constants");
|
|
10
|
+
var _utils = require("../shared/utils");
|
|
10
11
|
function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
|
|
11
12
|
function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && Object.prototype.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /*
|
|
12
13
|
* Copyright 2023 New Relic Corporation. All rights reserved.
|
|
@@ -23,15 +24,29 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
23
24
|
constructor(agentIdentifier, aggregator) {
|
|
24
25
|
let auto = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
|
|
25
26
|
super(agentIdentifier, aggregator, _constants2.FEATURE_NAME, auto);
|
|
27
|
+
let session;
|
|
26
28
|
try {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
}
|
|
34
|
-
|
|
29
|
+
session = JSON.parse(localStorage.getItem("".concat(_constants.PREFIX, "_").concat(_constants.DEFAULT_KEY)));
|
|
30
|
+
} catch (err) {}
|
|
31
|
+
if (this.#canPreloadRecorder(session)) {
|
|
32
|
+
this.#startRecording(session?.sessionReplayMode);
|
|
33
|
+
} else {
|
|
34
|
+
this.importAggregator();
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// At this point wherein session state exists already but we haven't init SessionEntity aka verify timers.
|
|
39
|
+
#canPreloadRecorder(session) {
|
|
40
|
+
if (!session) {
|
|
41
|
+
// this might be a new session if entity initializes: conservatively start recording if first-time config allows
|
|
42
|
+
// Note: users with SR enabled, as well as these other configs enabled by-default, will be penalized by the recorder overhead EVEN IF they don't actually have or get
|
|
43
|
+
// entitlement or sampling decision, or otherwise intentionally opted-in for the feature.
|
|
44
|
+
return (0, _utils.isPreloadAllowed)(this.agentIdentifier);
|
|
45
|
+
} else if (session.sessionReplayMode === _constants.MODE.FULL || session.sessionReplayMode === _constants.MODE.ERROR) {
|
|
46
|
+
return true; // existing sessions get to continue recording, regardless of this page's configs or if it has expired (conservatively)
|
|
47
|
+
} else {
|
|
48
|
+
// SR mode was OFF but may potentially be turned on if session resets and configs allows the new session to have replay...
|
|
49
|
+
return (0, _utils.isPreloadAllowed)(this.agentIdentifier);
|
|
35
50
|
}
|
|
36
51
|
}
|
|
37
52
|
async #startRecording(mode) {
|
|
@@ -43,6 +58,7 @@ class Instrument extends _instrumentBase.InstrumentBase {
|
|
|
43
58
|
agentIdentifier: this.agentIdentifier
|
|
44
59
|
});
|
|
45
60
|
this.recorder.startRecording();
|
|
61
|
+
this.abortHandler = this.recorder.stopRecording;
|
|
46
62
|
this.importAggregator({
|
|
47
63
|
recorder: this.recorder
|
|
48
64
|
});
|
|
@@ -115,14 +115,15 @@ class Recorder {
|
|
|
115
115
|
const incompletes = _stylesheetEvaluator.stylesheetEvaluator.evaluate();
|
|
116
116
|
/** Only stop ignoring data if already ignoring and a new valid snapshap is taking place (0 incompletes and we get a meta node for the snap) */
|
|
117
117
|
if (!incompletes && this.#fixing && event.type === _constants.RRWEB_EVENT_TYPES.Meta) this.#fixing = false;
|
|
118
|
-
if (incompletes) {
|
|
118
|
+
if (incompletes > 0) {
|
|
119
119
|
/** wait for the evaluator to download/replace the incompletes' src code and then take a new snap */
|
|
120
120
|
_stylesheetEvaluator.stylesheetEvaluator.fix().then(failedToFix => {
|
|
121
|
-
if (failedToFix) {
|
|
121
|
+
if (failedToFix > 0) {
|
|
122
122
|
this.currentBufferTarget.inlinedAllStylesheets = false;
|
|
123
123
|
this.shouldFix = false;
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
}
|
|
125
|
+
(0, _handle.handle)(_constants3.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Failed', failedToFix], undefined, _features.FEATURE_NAMES.metrics, this.parent.ee);
|
|
126
|
+
(0, _handle.handle)(_constants3.SUPPORTABILITY_METRIC_CHANNEL, ['SessionReplay/Payload/Missing-Inline-Css/Fixed', incompletes - failedToFix], undefined, _features.FEATURE_NAMES.metrics, this.parent.ee);
|
|
126
127
|
this.takeFullSnapshot();
|
|
127
128
|
});
|
|
128
129
|
/** Only start ignoring data if got a faulty snapshot */
|
|
@@ -24,15 +24,15 @@ class StylesheetEvaluator {
|
|
|
24
24
|
let incompletes = 0;
|
|
25
25
|
if (_runtime.isBrowserScope) {
|
|
26
26
|
for (let i = 0; i < Object.keys(document.styleSheets).length; i++) {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
this.#evaluated.add(ss);
|
|
27
|
+
if (!this.#evaluated.has(document.styleSheets[i])) {
|
|
28
|
+
this.#evaluated.add(document.styleSheets[i]);
|
|
30
29
|
try {
|
|
31
30
|
// eslint-disable-next-line
|
|
32
|
-
const temp =
|
|
31
|
+
const temp = document.styleSheets[i].cssRules;
|
|
33
32
|
} catch (err) {
|
|
33
|
+
if (!document.styleSheets[i].href) return;
|
|
34
34
|
incompletes++;
|
|
35
|
-
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]
|
|
35
|
+
this.#fetchProms.push(this.#fetchAndOverride(document.styleSheets[i]));
|
|
36
36
|
}
|
|
37
37
|
}
|
|
38
38
|
}
|
|
@@ -59,9 +59,10 @@ class StylesheetEvaluator {
|
|
|
59
59
|
* @param {*} href - The asset href to fetch
|
|
60
60
|
* @returns {Promise}
|
|
61
61
|
*/
|
|
62
|
-
async #fetchAndOverride(target
|
|
62
|
+
async #fetchAndOverride(target) {
|
|
63
|
+
if (!target?.href) return;
|
|
63
64
|
try {
|
|
64
|
-
const stylesheetContents = await _config.originals.FETCH.bind(window)(href);
|
|
65
|
+
const stylesheetContents = await _config.originals.FETCH.bind(window)(target.href);
|
|
65
66
|
if (!stylesheetContents.ok) {
|
|
66
67
|
this.failedToFix++;
|
|
67
68
|
return;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.canImportReplayAgg = canImportReplayAgg;
|
|
7
|
+
exports.enableSessionTracking = void 0;
|
|
8
|
+
exports.isPreloadAllowed = isPreloadAllowed;
|
|
9
|
+
var _config = require("../../../common/config/config");
|
|
10
|
+
var _runtime = require("../../../common/constants/runtime");
|
|
11
|
+
const enableSessionTracking = agentId => _runtime.isBrowserScope && (0, _config.getConfigurationValue)(agentId, 'privacy.cookies_enabled') === true;
|
|
12
|
+
exports.enableSessionTracking = enableSessionTracking;
|
|
13
|
+
function hasReplayPrerequisite(agentId) {
|
|
14
|
+
return _config.originals.MO &&
|
|
15
|
+
// Session Replay cannot work without Mutation Observer
|
|
16
|
+
enableSessionTracking &&
|
|
17
|
+
// requires session tracking to be running (hence "session" replay...)
|
|
18
|
+
(0, _config.getConfigurationValue)(agentId, 'session_trace.enabled') === true; // Session Replay as of now is tightly coupled with Session Trace in the UI
|
|
19
|
+
}
|
|
20
|
+
function isPreloadAllowed(agentId) {
|
|
21
|
+
return (0, _config.getConfigurationValue)(agentId, 'session_replay.preload') === true && hasReplayPrerequisite(agentId);
|
|
22
|
+
}
|
|
23
|
+
function canImportReplayAgg(agentId, sessionMgr) {
|
|
24
|
+
if (!hasReplayPrerequisite(agentId)) return false;
|
|
25
|
+
return !!sessionMgr?.isNew || !!sessionMgr?.state.sessionReplayMode; // Session Replay should only try to run if already running from a previous page, or at the beginning of a session
|
|
26
|
+
}
|