@newrelic/browser-agent 1.252.1 → 1.254.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 +25 -0
- package/README.md +2 -2
- package/dist/cjs/cdn/experimental.js +6 -2
- package/dist/cjs/cdn/polyfills.js +2 -1
- 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/config/state/runtime.js +4 -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/drain/drain.js +41 -27
- package/dist/cjs/common/event-emitter/contextual-ee.js +17 -12
- package/dist/cjs/common/harvest/harvest.js +5 -1
- package/dist/cjs/common/session/constants.js +2 -1
- package/dist/cjs/common/timing/nav-timing.js +8 -3
- package/dist/cjs/common/timing/now.js +1 -1
- package/dist/cjs/common/timing/time-keeper.js +94 -0
- package/dist/cjs/common/util/feature-flags.js +14 -31
- package/dist/cjs/common/wrap/index.js +0 -7
- package/dist/cjs/features/ajax/aggregate/index.js +41 -29
- package/dist/cjs/features/jserrors/aggregate/index.js +96 -84
- package/dist/cjs/features/metrics/aggregate/index.js +25 -24
- package/dist/cjs/features/page_action/aggregate/index.js +6 -4
- package/dist/cjs/features/page_view_event/aggregate/index.js +23 -3
- package/dist/cjs/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/dist/cjs/features/page_view_timing/aggregate/index.js +15 -16
- package/dist/cjs/features/session_replay/aggregate/index.js +102 -92
- 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/utils.js +26 -0
- package/dist/cjs/features/session_trace/aggregate/index.js +11 -8
- 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 +268 -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 +23 -18
- package/dist/cjs/features/utils/agent-session.js +2 -1
- package/dist/cjs/features/utils/aggregate-base.js +18 -5
- package/dist/cjs/features/utils/feature-base.js +2 -0
- package/dist/cjs/features/utils/instrument-base.js +7 -9
- package/dist/cjs/features/utils/lazy-feature-loader.js +2 -0
- package/dist/cjs/loaders/agent-base.js +13 -3
- package/dist/cjs/loaders/agent.js +19 -22
- package/dist/cjs/loaders/api/api-methods.js +2 -1
- package/dist/cjs/loaders/api/api.js +15 -12
- package/dist/cjs/loaders/configure/configure.js +5 -2
- package/dist/cjs/loaders/configure/nonce.cdn.js +13 -0
- package/dist/cjs/loaders/configure/nonce.js +2 -13
- package/dist/cjs/loaders/configure/public-path.cdn.js +16 -0
- package/dist/cjs/loaders/configure/public-path.js +2 -8
- 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/polyfills.js +2 -1
- 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/config/state/runtime.js +4 -1
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/drain/drain.js +40 -27
- package/dist/esm/common/event-emitter/contextual-ee.js +17 -12
- package/dist/esm/common/harvest/harvest.js +5 -1
- package/dist/esm/common/session/constants.js +1 -0
- package/dist/esm/common/timing/nav-timing.js +8 -3
- package/dist/esm/common/timing/now.js +1 -1
- package/dist/esm/common/timing/time-keeper.js +88 -0
- package/dist/esm/common/util/feature-flags.js +14 -31
- package/dist/esm/common/wrap/index.js +1 -2
- package/dist/esm/features/ajax/aggregate/index.js +43 -31
- package/dist/esm/features/jserrors/aggregate/index.js +96 -84
- package/dist/esm/features/metrics/aggregate/index.js +25 -24
- package/dist/esm/features/page_action/aggregate/index.js +6 -4
- package/dist/esm/features/page_view_event/aggregate/index.js +23 -3
- package/dist/esm/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/dist/esm/features/page_view_timing/aggregate/index.js +15 -16
- package/dist/esm/features/session_replay/aggregate/index.js +103 -93
- 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/utils.js +17 -0
- package/dist/esm/features/session_trace/aggregate/index.js +11 -8
- 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 +261 -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 +23 -18
- package/dist/esm/features/utils/agent-session.js +2 -1
- package/dist/esm/features/utils/aggregate-base.js +18 -5
- package/dist/esm/features/utils/feature-base.js +2 -0
- package/dist/esm/features/utils/instrument-base.js +8 -10
- package/dist/esm/features/utils/lazy-feature-loader.js +2 -0
- package/dist/esm/loaders/agent-base.js +13 -3
- package/dist/esm/loaders/agent.js +19 -22
- package/dist/esm/loaders/api/api-methods.js +2 -1
- package/dist/esm/loaders/api/api.js +15 -12
- package/dist/esm/loaders/configure/configure.js +5 -2
- package/dist/esm/loaders/configure/nonce.cdn.js +11 -0
- package/dist/esm/loaders/configure/nonce.js +1 -11
- package/dist/esm/loaders/configure/public-path.cdn.js +9 -0
- package/dist/esm/loaders/configure/public-path.js +2 -8
- 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/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/drain/drain.d.ts +6 -0
- package/dist/types/common/drain/drain.d.ts.map +1 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts +2 -1
- package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.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/timing/nav-timing.d.ts.map +1 -1
- package/dist/types/common/timing/time-keeper.d.ts +31 -0
- package/dist/types/common/timing/time-keeper.d.ts.map +1 -0
- package/dist/types/common/util/feature-flags.d.ts +11 -2
- package/dist/types/common/util/feature-flags.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/features/ajax/aggregate/index.d.ts +5 -5
- 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/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/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/page_view_timing/aggregate/index.d.ts +0 -2
- package/dist/types/features/page_view_timing/aggregate/index.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/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 +34 -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 +2 -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/aggregate-base.d.ts +2 -2
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
- package/dist/types/features/utils/feature-base.d.ts +1 -0
- package/dist/types/features/utils/feature-base.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.map +1 -1
- package/dist/types/loaders/api/api.d.ts +3 -5
- 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/configure/public-path.d.ts +1 -1
- package/dist/types/loaders/configure/public-path.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/polyfills.js +1 -0
- 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/config/state/runtime.js +4 -1
- package/src/common/drain/drain.js +41 -28
- package/src/common/event-emitter/contextual-ee.js +21 -13
- package/src/common/harvest/harvest.js +4 -1
- package/src/common/session/constants.js +1 -0
- package/src/common/timing/nav-timing.js +7 -3
- package/src/common/timing/now.js +1 -1
- package/src/common/timing/time-keeper.js +96 -0
- package/src/common/util/feature-flags.js +13 -31
- package/src/common/wrap/index.js +1 -2
- package/src/features/ajax/aggregate/index.js +43 -33
- package/src/features/jserrors/aggregate/index.js +82 -87
- package/src/features/metrics/aggregate/index.js +18 -17
- package/src/features/page_action/aggregate/index.js +6 -5
- package/src/features/page_view_event/aggregate/index.js +19 -3
- package/src/features/page_view_event/aggregate/initialized-features.js +1 -0
- package/src/features/page_view_timing/aggregate/index.js +15 -15
- package/src/features/session_replay/aggregate/index.js +95 -92
- 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/utils.js +19 -0
- package/src/features/session_trace/aggregate/index.js +2 -2
- 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 +256 -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 +20 -17
- package/src/features/utils/agent-session.js +2 -1
- package/src/features/utils/aggregate-base.js +16 -8
- package/src/features/utils/feature-base.js +3 -0
- package/src/features/utils/instrument-base.js +8 -10
- package/src/features/utils/lazy-feature-loader.js +2 -0
- package/src/loaders/agent-base.js +13 -3
- package/src/loaders/agent.js +20 -19
- package/src/loaders/api/api-methods.js +4 -1
- package/src/loaders/api/api.js +15 -13
- package/src/loaders/configure/configure.js +4 -1
- package/src/loaders/configure/nonce.cdn.js +12 -0
- package/src/loaders/configure/nonce.js +1 -12
- package/src/loaders/configure/public-path.cdn.js +9 -0
- package/src/loaders/configure/public-path.js +2 -8
- 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/cjs/loaders/configure/nonce.npm.js +0 -2
- package/dist/cjs/loaders/configure/public-path.npm.js +0 -10
- package/dist/esm/common/wrap/wrap-raf.js +0 -48
- package/dist/esm/loaders/configure/nonce.npm.js +0 -1
- package/dist/esm/loaders/configure/public-path.npm.js +0 -3
- package/dist/types/common/wrap/wrap-raf.d.ts +0 -16
- package/dist/types/common/wrap/wrap-raf.d.ts.map +0 -1
- package/dist/types/loaders/configure/nonce.npm.d.ts +0 -1
- package/dist/types/loaders/configure/nonce.npm.d.ts.map +0 -1
- package/dist/types/loaders/configure/public-path.npm.d.ts +0 -2
- package/dist/types/loaders/configure/public-path.npm.d.ts.map +0 -1
- package/src/common/wrap/wrap-raf.js +0 -52
- package/src/loaders/configure/nonce.npm.js +0 -1
- package/src/loaders/configure/public-path.npm.js +0 -3
|
@@ -18,6 +18,8 @@ import { globalScope } from '../../../common/constants/runtime';
|
|
|
18
18
|
import { FEATURE_NAME } from '../constants';
|
|
19
19
|
import { FEATURE_NAMES } from '../../../loaders/features/features';
|
|
20
20
|
import { AggregateBase } from '../../utils/aggregate-base';
|
|
21
|
+
import { getNREUMInitializedAgent } from '../../../common/window/nreum';
|
|
22
|
+
import { deregisterDrain } from '../../../common/drain/drain';
|
|
21
23
|
|
|
22
24
|
/**
|
|
23
25
|
* @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
|
|
@@ -32,42 +34,41 @@ export class Aggregate extends AggregateBase {
|
|
|
32
34
|
this.stackReported = {};
|
|
33
35
|
this.observedAt = {};
|
|
34
36
|
this.pageviewReported = {};
|
|
35
|
-
this.
|
|
37
|
+
this.bufferedErrorsUnderSpa = {};
|
|
36
38
|
this.currentBody = undefined;
|
|
37
39
|
this.errorOnPage = false;
|
|
38
40
|
|
|
39
41
|
// this will need to change to match whatever ee we use in the instrument
|
|
40
|
-
this.ee.on('
|
|
41
|
-
|
|
42
|
-
// this will need to change to match whatever ee we use in the instrument
|
|
43
|
-
this.ee.on('interactionDiscarded', interaction => this.onInteractionDiscarded(interaction));
|
|
42
|
+
this.ee.on('interactionDone', (interaction, wasSaved) => this.onInteractionDone(interaction, wasSaved));
|
|
44
43
|
register('err', function () {
|
|
45
44
|
return _this.storeError(...arguments);
|
|
46
45
|
}, this.featureName, this.ee);
|
|
47
46
|
register('ierr', function () {
|
|
48
47
|
return _this.storeError(...arguments);
|
|
49
48
|
}, this.featureName, this.ee);
|
|
49
|
+
register('softNavFlush', (interactionId, wasFinished, softNavAttrs) => this.onSoftNavNotification(interactionId, wasFinished, softNavAttrs), this.featureName, this.ee); // when an ixn is done or cancelled
|
|
50
|
+
|
|
50
51
|
const harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'jserrors.harvestTimeSeconds') || 10;
|
|
51
|
-
const scheduler = new HarvestScheduler('jserrors', {
|
|
52
|
-
onFinished: function () {
|
|
53
|
-
return _this.onHarvestFinished(...arguments);
|
|
54
|
-
}
|
|
55
|
-
}, this);
|
|
56
|
-
scheduler.harvest.on('jserrors', function () {
|
|
57
|
-
return _this.onHarvestStarted(...arguments);
|
|
58
|
-
});
|
|
59
52
|
|
|
60
|
-
//
|
|
61
|
-
this.
|
|
62
|
-
|
|
53
|
+
// 0 == off, 1 == on
|
|
54
|
+
this.waitForFlags(['err']).then(_ref => {
|
|
55
|
+
let [errFlag] = _ref;
|
|
56
|
+
if (errFlag) {
|
|
57
|
+
const scheduler = new HarvestScheduler('jserrors', {
|
|
58
|
+
onFinished: function () {
|
|
59
|
+
return _this.onHarvestFinished(...arguments);
|
|
60
|
+
}
|
|
61
|
+
}, this);
|
|
62
|
+
scheduler.harvest.on('jserrors', function () {
|
|
63
|
+
return _this.onHarvestStarted(...arguments);
|
|
64
|
+
});
|
|
65
|
+
scheduler.startTimer(harvestTimeSeconds);
|
|
66
|
+
this.drain();
|
|
67
|
+
} else {
|
|
68
|
+
this.blocked = true; // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
|
|
69
|
+
deregisterDrain(this.agentIdentifier, this.featureName);
|
|
70
|
+
}
|
|
63
71
|
});
|
|
64
|
-
|
|
65
|
-
// If RUM-call's response determines that customer lacks entitlements for the /jserror ingest endpoint, don't harvest at all.
|
|
66
|
-
register('block-err', () => {
|
|
67
|
-
this.blocked = true;
|
|
68
|
-
scheduler.stopTimer(true);
|
|
69
|
-
}, this.featureName, this.ee);
|
|
70
|
-
this.drain();
|
|
71
72
|
}
|
|
72
73
|
onHarvestStarted(options) {
|
|
73
74
|
// this gets rid of dependency in AJAX module
|
|
@@ -188,81 +189,92 @@ export class Aggregate extends AggregateBase {
|
|
|
188
189
|
time
|
|
189
190
|
};
|
|
190
191
|
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
handle('errorAgg',
|
|
195
|
-
handle('errorAgg', msg, undefined, FEATURE_NAMES.spa, this.ee);
|
|
196
|
-
handle('errorAgg', msg, undefined, FEATURE_NAMES.sessionReplay, this.ee);
|
|
197
|
-
|
|
192
|
+
// Trace sends the error in its payload, and both trace & replay simply listens for any error to occur.
|
|
193
|
+
const jsErrorEvent = [type, bucketHash, params, newMetrics, customAttributes];
|
|
194
|
+
handle('errorAgg', jsErrorEvent, undefined, FEATURE_NAMES.sessionTrace, this.ee);
|
|
195
|
+
handle('errorAgg', jsErrorEvent, undefined, FEATURE_NAMES.sessionReplay, this.ee);
|
|
198
196
|
// still send EE events for other features such as above, but stop this one from aggregating internal data
|
|
199
197
|
if (this.blocked) return;
|
|
200
|
-
|
|
201
|
-
if
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
198
|
+
const softNavInUse = Boolean(getNREUMInitializedAgent(this.agentIdentifier)?.features[FEATURE_NAMES.softNav]);
|
|
199
|
+
// 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.
|
|
200
|
+
// They each will also tack on their respective properties to the params object as part of the decision flow.
|
|
201
|
+
if (softNavInUse) handle('jserror', [params, time], undefined, FEATURE_NAMES.softNav, this.ee);else handle('errorAgg', jsErrorEvent, undefined, FEATURE_NAMES.spa, this.ee);
|
|
202
|
+
if (params.browserInteractionId && !params._softNavFinished) {
|
|
203
|
+
// hold onto the error until the in-progress interaction is done, eithered saved or discarded
|
|
204
|
+
this.bufferedErrorsUnderSpa[params.browserInteractionId] ??= [];
|
|
205
|
+
this.bufferedErrorsUnderSpa[params.browserInteractionId].push(jsErrorEvent);
|
|
206
|
+
} else if (params._interactionId != null) {
|
|
207
|
+
// same as above, except tailored for the way old spa does it
|
|
208
|
+
this.bufferedErrorsUnderSpa[params._interactionId] = this.bufferedErrorsUnderSpa[params._interactionId] || [];
|
|
209
|
+
this.bufferedErrorsUnderSpa[params._interactionId].push(jsErrorEvent);
|
|
205
210
|
} else {
|
|
206
|
-
//
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
if (customAttributes) {
|
|
210
|
-
mapOwn(customAttributes, setCustom);
|
|
211
|
-
}
|
|
212
|
-
var jsAttributesHash = stringHashCode(stringify(customParams));
|
|
213
|
-
var aggregateHash = bucketHash + ':' + jsAttributesHash;
|
|
214
|
-
this.aggregator.store(type, aggregateHash, params, newMetrics, customParams);
|
|
211
|
+
// Either there is no interaction (then all these params properties will be undefined) OR there's a related soft navigation that's already completed.
|
|
212
|
+
// The old spa does not look up completed interactions at all, so there's no need to consider it.
|
|
213
|
+
this.#storeJserrorForHarvest(jsErrorEvent, params.browserInteractionId !== undefined, params._softNavAttributes);
|
|
215
214
|
}
|
|
215
|
+
}
|
|
216
|
+
#storeJserrorForHarvest(errorInfoArr, softNavOccurredFinished) {
|
|
217
|
+
let softNavCustomAttrs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
|
|
218
|
+
let [type, bucketHash, params, newMetrics, localAttrs] = errorInfoArr;
|
|
219
|
+
const allCustomAttrs = {};
|
|
220
|
+
if (softNavOccurredFinished) {
|
|
221
|
+
Object.entries(softNavCustomAttrs).forEach(_ref2 => {
|
|
222
|
+
let [k, v] = _ref2;
|
|
223
|
+
return setCustom(k, v);
|
|
224
|
+
}); // when an ixn finishes, it'll include stuff in jsAttributes + attrs specific to the ixn
|
|
225
|
+
bucketHash += params.browserInteractionId;
|
|
226
|
+
delete params._softNavAttributes; // cleanup temp properties from synchronous evaluation; this is harmless when async from soft nav (properties DNE)
|
|
227
|
+
delete params._softNavFinished;
|
|
228
|
+
} else {
|
|
229
|
+
// interaction was cancelled -> error should not be associated OR there was no interaction
|
|
230
|
+
Object.entries(getInfo(this.agentIdentifier).jsAttributes).forEach(_ref3 => {
|
|
231
|
+
let [k, v] = _ref3;
|
|
232
|
+
return setCustom(k, v);
|
|
233
|
+
});
|
|
234
|
+
delete params.browserInteractionId;
|
|
235
|
+
}
|
|
236
|
+
if (localAttrs) Object.entries(localAttrs).forEach(_ref4 => {
|
|
237
|
+
let [k, v] = _ref4;
|
|
238
|
+
return setCustom(k, v);
|
|
239
|
+
}); // local custom attrs are applied in either case with the highest precedence
|
|
240
|
+
|
|
241
|
+
const jsAttributesHash = stringHashCode(stringify(allCustomAttrs));
|
|
242
|
+
const aggregateHash = bucketHash + ':' + jsAttributesHash;
|
|
243
|
+
this.aggregator.store(type, aggregateHash, params, newMetrics, allCustomAttrs);
|
|
216
244
|
function setCustom(key, val) {
|
|
217
|
-
|
|
245
|
+
allCustomAttrs[key] = val && typeof val === 'object' ? stringify(val) : val;
|
|
218
246
|
}
|
|
219
247
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
var
|
|
226
|
-
|
|
227
|
-
mapOwn(interaction.root.attrs.custom, setCustom);
|
|
228
|
-
mapOwn(
|
|
248
|
+
|
|
249
|
+
// TO-DO: Remove this function when old spa is taken out. #storeJserrorForHarvest handles the work with the softnav feature.
|
|
250
|
+
onInteractionDone(interaction, wasSaved) {
|
|
251
|
+
if (!this.bufferedErrorsUnderSpa[interaction.id] || this.blocked) return;
|
|
252
|
+
this.bufferedErrorsUnderSpa[interaction.id].forEach(item => {
|
|
253
|
+
var allCustomAttrs = {};
|
|
254
|
+
const localCustomAttrs = item[4];
|
|
255
|
+
mapOwn(interaction.root.attrs.custom, setCustom); // tack on custom attrs from the interaction
|
|
256
|
+
mapOwn(localCustomAttrs, setCustom);
|
|
229
257
|
var params = item[2];
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
params.parentNodeId = params._interactionNodeId.toString();
|
|
234
|
-
delete params._interactionNodeId;
|
|
235
|
-
}
|
|
236
|
-
var hash = item[1] + interaction.root.attrs.id;
|
|
237
|
-
var jsAttributesHash = stringHashCode(stringify(customParams));
|
|
238
|
-
var aggregateHash = hash + ':' + jsAttributesHash;
|
|
239
|
-
this.aggregator.store(item[0], aggregateHash, params, item[3], customParams);
|
|
240
|
-
function setCustom(key, val) {
|
|
241
|
-
customParams[key] = val && typeof val === 'object' ? stringify(val) : val;
|
|
258
|
+
if (wasSaved) {
|
|
259
|
+
params.browserInteractionId = interaction.root.attrs.id;
|
|
260
|
+
if (params._interactionNodeId) params.parentNodeId = params._interactionNodeId.toString();
|
|
242
261
|
}
|
|
243
|
-
});
|
|
244
|
-
delete this.errorCache[interaction.id];
|
|
245
|
-
}
|
|
246
|
-
onInteractionDiscarded(interaction) {
|
|
247
|
-
if (!this.errorCache || !this.errorCache[interaction.id] || this.blocked) return;
|
|
248
|
-
this.errorCache[interaction.id].forEach(item => {
|
|
249
|
-
var customParams = {};
|
|
250
|
-
var globalCustomParams = item[4];
|
|
251
|
-
var localCustomParams = item[5];
|
|
252
|
-
mapOwn(globalCustomParams, setCustom);
|
|
253
|
-
mapOwn(interaction.root.attrs.custom, setCustom);
|
|
254
|
-
mapOwn(localCustomParams, setCustom);
|
|
255
|
-
var params = item[2];
|
|
256
262
|
delete params._interactionId;
|
|
257
263
|
delete params._interactionNodeId;
|
|
258
|
-
var hash = item[1];
|
|
259
|
-
var jsAttributesHash = stringHashCode(stringify(
|
|
264
|
+
var hash = wasSaved ? item[1] + interaction.root.attrs.id : item[1];
|
|
265
|
+
var jsAttributesHash = stringHashCode(stringify(allCustomAttrs));
|
|
260
266
|
var aggregateHash = hash + ':' + jsAttributesHash;
|
|
261
|
-
this.aggregator.store(item[0], aggregateHash,
|
|
267
|
+
this.aggregator.store(item[0], aggregateHash, params, item[3], allCustomAttrs);
|
|
262
268
|
function setCustom(key, val) {
|
|
263
|
-
|
|
269
|
+
allCustomAttrs[key] = val && typeof val === 'object' ? stringify(val) : val;
|
|
264
270
|
}
|
|
265
271
|
});
|
|
266
|
-
delete this.
|
|
272
|
+
delete this.bufferedErrorsUnderSpa[interaction.id];
|
|
273
|
+
}
|
|
274
|
+
onSoftNavNotification(interactionId, wasFinished, softNavAttrs) {
|
|
275
|
+
if (this.blocked) return;
|
|
276
|
+
this.bufferedErrorsUnderSpa[interactionId]?.forEach(jsErrorEvent => this.#storeJserrorForHarvest(jsErrorEvent, wasFinished, softNavAttrs) // this should not modify the re-used softNavAttrs contents
|
|
277
|
+
);
|
|
278
|
+
delete this.bufferedErrorsUnderSpa[interactionId]; // wipe the list of jserrors so they aren't duplicated by another call to the same id
|
|
267
279
|
}
|
|
268
280
|
}
|
|
@@ -9,35 +9,34 @@ import { onDOMContentLoaded } from '../../../common/window/load';
|
|
|
9
9
|
import { windowAddEventListener } from '../../../common/event-listener/event-listener-opts';
|
|
10
10
|
import { isBrowserScope, isWorkerScope } from '../../../common/constants/runtime';
|
|
11
11
|
import { AggregateBase } from '../../utils/aggregate-base';
|
|
12
|
+
import { deregisterDrain } from '../../../common/drain/drain';
|
|
12
13
|
export class Aggregate extends AggregateBase {
|
|
13
14
|
static featureName = FEATURE_NAME;
|
|
14
15
|
constructor(agentIdentifier, aggregator) {
|
|
15
16
|
super(agentIdentifier, aggregator, FEATURE_NAME);
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
17
|
+
this.waitForFlags(['err']).then(_ref => {
|
|
18
|
+
let [errFlag] = _ref;
|
|
19
|
+
if (errFlag) {
|
|
20
|
+
// *cli, Mar 23 - Per NR-94597, this feature should only harvest ONCE at the (potential) EoL time of the page.
|
|
21
|
+
const scheduler = new HarvestScheduler('jserrors', {
|
|
22
|
+
onUnload: () => this.unload()
|
|
23
|
+
}, this);
|
|
24
|
+
// this is needed to ensure EoL is "on" and sent
|
|
25
|
+
scheduler.harvest.on('jserrors', () => ({
|
|
26
|
+
body: this.aggregator.take(['cm', 'sm'])
|
|
27
|
+
}));
|
|
28
|
+
this.drain();
|
|
29
|
+
} else {
|
|
30
|
+
this.blocked = true; // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
|
|
31
|
+
deregisterDrain(this.agentIdentifier, this.featureName);
|
|
32
|
+
}
|
|
33
|
+
});
|
|
23
34
|
|
|
24
35
|
// Allow features external to the metrics feature to capture SMs and CMs through the event emitter
|
|
25
36
|
registerHandler(SUPPORTABILITY_METRIC_CHANNEL, this.storeSupportabilityMetrics.bind(this), this.featureName, this.ee);
|
|
26
37
|
registerHandler(CUSTOM_METRIC_CHANNEL, this.storeEventMetrics.bind(this), this.featureName, this.ee);
|
|
27
38
|
this.singleChecks(); // checks that are run only one time, at script load
|
|
28
39
|
this.eachSessionChecks(); // the start of every time user engages with page
|
|
29
|
-
|
|
30
|
-
this.ee.on("drain-".concat(this.featureName), () => {
|
|
31
|
-
// *cli, Mar 23 - Per NR-94597, this feature should only harvest ONCE at the (potential) EoL time of the page.
|
|
32
|
-
scheduler = new HarvestScheduler('jserrors', {
|
|
33
|
-
onUnload: () => this.unload()
|
|
34
|
-
}, this);
|
|
35
|
-
scheduler.harvest.on('jserrors', () => ({
|
|
36
|
-
body: this.aggregator.take(['cm', 'sm'])
|
|
37
|
-
}));
|
|
38
|
-
}); // this is needed to ensure EoL is "on" and sent
|
|
39
|
-
|
|
40
|
-
this.drain();
|
|
41
40
|
}
|
|
42
41
|
storeSupportabilityMetrics(name, value) {
|
|
43
42
|
if (this.blocked) return;
|
|
@@ -61,6 +60,11 @@ export class Aggregate extends AggregateBase {
|
|
|
61
60
|
distMethod,
|
|
62
61
|
loaderType
|
|
63
62
|
} = getRuntime(this.agentIdentifier);
|
|
63
|
+
const {
|
|
64
|
+
proxy,
|
|
65
|
+
privacy,
|
|
66
|
+
page_view_timing
|
|
67
|
+
} = getConfiguration(this.agentIdentifier);
|
|
64
68
|
if (loaderType) this.storeSupportabilityMetrics("Generic/LoaderType/".concat(loaderType, "/Detected"));
|
|
65
69
|
if (distMethod) this.storeSupportabilityMetrics("Generic/DistMethod/".concat(distMethod, "/Detected"));
|
|
66
70
|
if (isBrowserScope) {
|
|
@@ -76,6 +80,8 @@ export class Aggregate extends AggregateBase {
|
|
|
76
80
|
this.storeSupportabilityMetrics('Framework/' + framework + '/Detected');
|
|
77
81
|
});
|
|
78
82
|
});
|
|
83
|
+
if (!privacy.cookies_enabled) this.storeSupportabilityMetrics('Config/SessionTracking/Disabled');
|
|
84
|
+
if (page_view_timing.long_task) this.storeSupportabilityMetrics('Config/LongTask/Enabled');
|
|
79
85
|
} else if (isWorkerScope) {
|
|
80
86
|
this.storeSupportabilityMetrics('Generic/Runtime/Worker/Detected');
|
|
81
87
|
} else {
|
|
@@ -94,13 +100,8 @@ export class Aggregate extends AggregateBase {
|
|
|
94
100
|
if (rules.length > 0 && !validateRules(rules)) this.storeSupportabilityMetrics('Generic/Obfuscate/Invalid');
|
|
95
101
|
|
|
96
102
|
// Check if proxy for either chunks or beacon is being used
|
|
97
|
-
const {
|
|
98
|
-
proxy,
|
|
99
|
-
privacy
|
|
100
|
-
} = getConfiguration(this.agentIdentifier);
|
|
101
103
|
if (proxy.assets) this.storeSupportabilityMetrics('Config/AssetsUrl/Changed');
|
|
102
104
|
if (proxy.beacon) this.storeSupportabilityMetrics('Config/BeaconUrl/Changed');
|
|
103
|
-
if (!(isBrowserScope && privacy.cookies_enabled)) this.storeSupportabilityMetrics('Config/SessionTracking/Disabled');
|
|
104
105
|
}
|
|
105
106
|
eachSessionChecks() {
|
|
106
107
|
if (!isBrowserScope) return;
|
|
@@ -12,6 +12,7 @@ import { getConfigurationValue, getInfo, getRuntime } from '../../../common/conf
|
|
|
12
12
|
import { FEATURE_NAME } from '../constants';
|
|
13
13
|
import { isBrowserScope } from '../../../common/constants/runtime';
|
|
14
14
|
import { AggregateBase } from '../../utils/aggregate-base';
|
|
15
|
+
import { deregisterDrain } from '../../../common/drain/drain';
|
|
15
16
|
export class Aggregate extends AggregateBase {
|
|
16
17
|
static featureName = FEATURE_NAME;
|
|
17
18
|
constructor(agentIdentifier, aggregator) {
|
|
@@ -31,8 +32,8 @@ export class Aggregate extends AggregateBase {
|
|
|
31
32
|
return _this.addPageAction(...arguments);
|
|
32
33
|
}, this.featureName, this.ee);
|
|
33
34
|
this.waitForFlags(['ins']).then(_ref => {
|
|
34
|
-
let [
|
|
35
|
-
if (
|
|
35
|
+
let [insFlag] = _ref;
|
|
36
|
+
if (insFlag) {
|
|
36
37
|
const scheduler = new HarvestScheduler('ins', {
|
|
37
38
|
onFinished: function () {
|
|
38
39
|
return _this.onHarvestFinished(...arguments);
|
|
@@ -42,11 +43,12 @@ export class Aggregate extends AggregateBase {
|
|
|
42
43
|
return _this.onHarvestStarted(...arguments);
|
|
43
44
|
});
|
|
44
45
|
scheduler.startTimer(this.harvestTimeSeconds, 0);
|
|
46
|
+
this.drain();
|
|
45
47
|
} else {
|
|
46
|
-
this.blocked = true;
|
|
48
|
+
this.blocked = true; // if rum response determines that customer lacks entitlements for ins endpoint, this feature shouldn't harvest
|
|
49
|
+
deregisterDrain(this.agentIdentifier, this.featureName);
|
|
47
50
|
}
|
|
48
51
|
});
|
|
49
|
-
this.drain();
|
|
50
52
|
}
|
|
51
53
|
onHarvestStarted(options) {
|
|
52
54
|
const {
|
|
@@ -11,6 +11,10 @@ import { AggregateBase } from '../../utils/aggregate-base';
|
|
|
11
11
|
import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint';
|
|
12
12
|
import { firstPaint } from '../../../common/vitals/first-paint';
|
|
13
13
|
import { timeToFirstByte } from '../../../common/vitals/time-to-first-byte';
|
|
14
|
+
import { drain } from '../../../common/drain/drain';
|
|
15
|
+
import { FEATURE_NAMES } from '../../../loaders/features/features';
|
|
16
|
+
import { handle } from '../../../common/event-emitter/handle';
|
|
17
|
+
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
|
|
14
18
|
export class Aggregate extends AggregateBase {
|
|
15
19
|
static featureName = CONSTANTS.FEATURE_NAME;
|
|
16
20
|
constructor(agentIdentifier, aggregator) {
|
|
@@ -117,7 +121,9 @@ export class Aggregate extends AggregateBase {
|
|
|
117
121
|
cbFinished: _ref3 => {
|
|
118
122
|
let {
|
|
119
123
|
status,
|
|
120
|
-
responseText
|
|
124
|
+
responseText,
|
|
125
|
+
xhr,
|
|
126
|
+
fullUrl
|
|
121
127
|
} = _ref3;
|
|
122
128
|
if (status >= 400 || status === 0) {
|
|
123
129
|
// Adding retry logic for the rum call will be a separate change
|
|
@@ -125,11 +131,25 @@ export class Aggregate extends AggregateBase {
|
|
|
125
131
|
return;
|
|
126
132
|
}
|
|
127
133
|
try {
|
|
128
|
-
|
|
134
|
+
this.timeKeeper.processRumRequest(xhr, fullUrl);
|
|
135
|
+
} catch (error) {
|
|
136
|
+
handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, FEATURE_NAMES.metrics, this.ee);
|
|
137
|
+
drain(this.agentIdentifier, FEATURE_NAMES.metrics, true);
|
|
138
|
+
this.ee.abort();
|
|
139
|
+
warn('Could not calculate New Relic server time. Agent shutting down.');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
try {
|
|
143
|
+
const {
|
|
144
|
+
app,
|
|
145
|
+
...flags
|
|
146
|
+
} = JSON.parse(responseText);
|
|
147
|
+
agentRuntime.appMetadata = app;
|
|
148
|
+
activateFeatures(flags, this.agentIdentifier);
|
|
129
149
|
this.drain();
|
|
130
150
|
} catch (err) {
|
|
131
151
|
this.ee.abort();
|
|
132
|
-
warn('RUM call failed. Agent shutting down.');
|
|
152
|
+
warn('RUM call failed. Agent shutting down.', err);
|
|
133
153
|
}
|
|
134
154
|
}
|
|
135
155
|
});
|
|
@@ -37,17 +37,6 @@ export class Aggregate extends AggregateBase {
|
|
|
37
37
|
this.timings = [];
|
|
38
38
|
this.timingsSent = [];
|
|
39
39
|
this.curSessEndRecorded = false;
|
|
40
|
-
firstPaint.subscribe(this.#handleVitalMetric);
|
|
41
|
-
firstContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
42
|
-
firstInputDelay.subscribe(this.#handleVitalMetric);
|
|
43
|
-
largestContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
44
|
-
interactionToNextPaint.subscribe(this.#handleVitalMetric);
|
|
45
|
-
timeToFirstByte.subscribe(_ref2 => {
|
|
46
|
-
let {
|
|
47
|
-
entries
|
|
48
|
-
} = _ref2;
|
|
49
|
-
this.addTiming('load', Math.round(entries[0].loadEventEnd));
|
|
50
|
-
});
|
|
51
40
|
if (getConfigurationValue(this.agentIdentifier, 'page_view_timing.long_task') === true) longTask.subscribe(this.#handleVitalMetric);
|
|
52
41
|
|
|
53
42
|
/* It's important that CWV api, like "onLCP", is called before this scheduler is initialized. The reason is because they listen to the same
|
|
@@ -57,9 +46,19 @@ export class Aggregate extends AggregateBase {
|
|
|
57
46
|
registerHandler('winPagehide', msTimestamp => this.recordPageUnload(msTimestamp), this.featureName, this.ee);
|
|
58
47
|
const initialHarvestSeconds = getConfigurationValue(this.agentIdentifier, 'page_view_timing.initialHarvestSeconds') || 10;
|
|
59
48
|
const harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'page_view_timing.harvestTimeSeconds') || 30;
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
49
|
+
this.waitForFlags([]).then(() => {
|
|
50
|
+
firstPaint.subscribe(this.#handleVitalMetric);
|
|
51
|
+
firstContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
52
|
+
firstInputDelay.subscribe(this.#handleVitalMetric);
|
|
53
|
+
largestContentfulPaint.subscribe(this.#handleVitalMetric);
|
|
54
|
+
interactionToNextPaint.subscribe(this.#handleVitalMetric);
|
|
55
|
+
timeToFirstByte.subscribe(_ref2 => {
|
|
56
|
+
let {
|
|
57
|
+
entries
|
|
58
|
+
} = _ref2;
|
|
59
|
+
this.addTiming('load', Math.round(entries[0].loadEventEnd));
|
|
60
|
+
});
|
|
61
|
+
const scheduler = new HarvestScheduler('events', {
|
|
63
62
|
onFinished: function () {
|
|
64
63
|
return _this.onHarvestFinished(...arguments);
|
|
65
64
|
},
|
|
@@ -67,9 +66,9 @@ export class Aggregate extends AggregateBase {
|
|
|
67
66
|
return _this.prepareHarvest(...arguments);
|
|
68
67
|
}
|
|
69
68
|
}, this);
|
|
70
|
-
|
|
69
|
+
scheduler.startTimer(harvestTimeSeconds, initialHarvestSeconds);
|
|
70
|
+
this.drain();
|
|
71
71
|
});
|
|
72
|
-
this.drain();
|
|
73
72
|
}
|
|
74
73
|
|
|
75
74
|
/**
|