@newrelic/browser-agent 1.269.0 → 1.270.1
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/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/constants/runtime.js +1 -2
- package/dist/cjs/common/harvest/harvest-scheduler.js +3 -4
- package/dist/cjs/common/unload/eol.js +2 -5
- package/dist/cjs/common/util/submit-data.js +1 -1
- package/dist/cjs/features/ajax/aggregate/index.js +8 -17
- package/dist/cjs/features/ajax/instrument/index.js +8 -10
- package/dist/cjs/features/generic_events/aggregate/index.js +15 -22
- package/dist/cjs/features/generic_events/instrument/index.js +5 -8
- package/dist/cjs/features/jserrors/aggregate/index.js +17 -22
- package/dist/cjs/features/jserrors/instrument/index.js +3 -3
- package/dist/cjs/features/logging/aggregate/index.js +16 -23
- package/dist/cjs/features/logging/instrument/index.js +3 -3
- package/dist/cjs/features/metrics/aggregate/index.js +13 -16
- package/dist/cjs/features/metrics/instrument/index.js +3 -3
- package/dist/cjs/features/page_view_event/aggregate/index.js +15 -29
- package/dist/cjs/features/page_view_event/instrument/index.js +3 -3
- package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -23
- package/dist/cjs/features/page_view_timing/instrument/index.js +3 -3
- package/dist/cjs/features/session_replay/aggregate/index.js +15 -29
- package/dist/cjs/features/session_replay/instrument/index.js +7 -5
- package/dist/cjs/features/session_trace/aggregate/index.js +25 -31
- package/dist/cjs/features/session_trace/aggregate/trace/storage.js +1 -1
- package/dist/cjs/features/session_trace/instrument/index.js +4 -5
- package/dist/cjs/features/soft_navigations/aggregate/index.js +6 -11
- package/dist/cjs/features/soft_navigations/instrument/index.js +3 -3
- package/dist/cjs/features/spa/aggregate/index.js +19 -30
- package/dist/cjs/features/spa/instrument/index.js +4 -4
- package/dist/cjs/features/utils/aggregate-base.js +11 -12
- package/dist/cjs/features/utils/feature-base.js +5 -3
- package/dist/cjs/features/utils/instrument-base.js +18 -10
- package/dist/cjs/loaders/agent.js +1 -5
- package/dist/cjs/loaders/micro-agent.js +6 -9
- 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/runtime.js +0 -1
- package/dist/esm/common/harvest/harvest-scheduler.js +3 -4
- package/dist/esm/common/unload/eol.js +2 -5
- package/dist/esm/common/util/submit-data.js +2 -2
- package/dist/esm/features/ajax/aggregate/index.js +8 -17
- package/dist/esm/features/ajax/instrument/index.js +8 -10
- package/dist/esm/features/generic_events/aggregate/index.js +11 -18
- package/dist/esm/features/generic_events/instrument/index.js +5 -8
- package/dist/esm/features/jserrors/aggregate/index.js +15 -20
- package/dist/esm/features/jserrors/instrument/index.js +3 -3
- package/dist/esm/features/logging/aggregate/index.js +16 -23
- package/dist/esm/features/logging/instrument/index.js +3 -3
- package/dist/esm/features/metrics/aggregate/index.js +8 -11
- package/dist/esm/features/metrics/instrument/index.js +3 -3
- package/dist/esm/features/page_view_event/aggregate/index.js +16 -30
- package/dist/esm/features/page_view_event/instrument/index.js +3 -3
- package/dist/esm/features/page_view_timing/aggregate/index.js +6 -23
- package/dist/esm/features/page_view_timing/instrument/index.js +3 -3
- package/dist/esm/features/session_replay/aggregate/index.js +13 -27
- package/dist/esm/features/session_replay/instrument/index.js +7 -5
- package/dist/esm/features/session_trace/aggregate/index.js +22 -28
- package/dist/esm/features/session_trace/aggregate/trace/storage.js +1 -1
- package/dist/esm/features/session_trace/instrument/index.js +4 -5
- package/dist/esm/features/soft_navigations/aggregate/index.js +6 -11
- package/dist/esm/features/soft_navigations/instrument/index.js +3 -3
- package/dist/esm/features/spa/aggregate/index.js +17 -28
- package/dist/esm/features/spa/instrument/index.js +4 -4
- package/dist/esm/features/utils/aggregate-base.js +13 -14
- package/dist/esm/features/utils/feature-base.js +5 -3
- package/dist/esm/features/utils/instrument-base.js +18 -10
- package/dist/esm/loaders/agent.js +1 -5
- package/dist/esm/loaders/micro-agent.js +6 -9
- package/dist/types/common/constants/runtime.d.ts +0 -1
- package/dist/types/common/constants/runtime.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/common/unload/eol.d.ts +1 -1
- package/dist/types/common/unload/eol.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts +1 -1
- package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/aggregate/index.d.ts +1 -2
- package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts +1 -1
- package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
- package/dist/types/features/logging/aggregate/index.d.ts +1 -2
- package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/logging/instrument/index.d.ts +1 -1
- package/dist/types/features/logging/instrument/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts +1 -1
- package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_action/instrument/index.d.ts +1 -0
- package/dist/types/features/page_action/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/instrument/index.d.ts +1 -1
- package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -5
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/instrument/index.d.ts +1 -1
- package/dist/types/features/page_view_timing/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +0 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts +1 -1
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts +1 -3
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts +1 -1
- package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/soft_navigations/instrument/index.d.ts +1 -1
- package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/instrument/index.d.ts +1 -1
- package/dist/types/features/spa/instrument/index.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 +2 -3
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +3 -3
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts +0 -2
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/micro-agent.d.ts +0 -2
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/common/constants/__mocks__/runtime.js +0 -1
- package/src/common/constants/runtime.js +0 -2
- package/src/common/harvest/harvest-scheduler.js +3 -4
- package/src/common/unload/eol.js +2 -5
- package/src/common/util/submit-data.js +2 -2
- package/src/features/ajax/aggregate/index.js +8 -18
- package/src/features/ajax/instrument/index.js +8 -10
- package/src/features/generic_events/aggregate/index.js +11 -20
- package/src/features/generic_events/instrument/index.js +7 -10
- package/src/features/jserrors/aggregate/index.js +15 -20
- package/src/features/jserrors/instrument/index.js +3 -4
- package/src/features/logging/aggregate/index.js +15 -23
- package/src/features/logging/instrument/index.js +3 -3
- package/src/features/metrics/aggregate/index.js +8 -11
- package/src/features/metrics/instrument/index.js +3 -3
- package/src/features/page_view_event/aggregate/index.js +16 -22
- package/src/features/page_view_event/instrument/index.js +3 -3
- package/src/features/page_view_timing/aggregate/index.js +6 -23
- package/src/features/page_view_timing/instrument/index.js +3 -3
- package/src/features/session_replay/aggregate/index.js +13 -21
- package/src/features/session_replay/instrument/index.js +7 -5
- package/src/features/session_trace/aggregate/index.js +22 -28
- package/src/features/session_trace/aggregate/trace/storage.js +1 -1
- package/src/features/session_trace/instrument/index.js +4 -5
- package/src/features/soft_navigations/aggregate/index.js +6 -8
- package/src/features/soft_navigations/instrument/index.js +3 -3
- package/src/features/spa/aggregate/index.js +17 -26
- package/src/features/spa/instrument/index.js +4 -4
- package/src/features/utils/__mocks__/feature-base.js +1 -2
- package/src/features/utils/aggregate-base.js +13 -14
- package/src/features/utils/feature-base.js +6 -3
- package/src/features/utils/instrument-base.js +16 -10
- package/src/loaders/agent.js +1 -3
- package/src/loaders/micro-agent.js +7 -9
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
import { registerHandler } from '../../../common/event-emitter/register-handler';
|
|
2
2
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler';
|
|
3
|
-
import { getInfo } from '../../../common/config/info';
|
|
4
|
-
import { getConfigurationValue } from '../../../common/config/init';
|
|
5
|
-
import { getRuntime } from '../../../common/config/runtime';
|
|
6
3
|
import { FEATURE_NAME } from '../constants';
|
|
7
4
|
import { AggregateBase } from '../../utils/aggregate-base';
|
|
8
5
|
import { TraceStorage } from './trace/storage';
|
|
9
6
|
import { obj as encodeObj } from '../../../common/url/encode';
|
|
10
|
-
import { deregisterDrain } from '../../../common/drain/drain';
|
|
11
7
|
import { globalScope } from '../../../common/constants/runtime';
|
|
12
8
|
import { MODE, SESSION_EVENTS } from '../../../common/session/constants';
|
|
13
9
|
import { applyFnToProps } from '../../../common/util/traverse';
|
|
@@ -17,14 +13,12 @@ const ERROR_MODE_SECONDS_WINDOW = 30 * 1000; // sliding window of nodes to track
|
|
|
17
13
|
const QUERY_PARAM_PADDING = 5000;
|
|
18
14
|
export class Aggregate extends AggregateBase {
|
|
19
15
|
static featureName = FEATURE_NAME;
|
|
20
|
-
constructor(
|
|
21
|
-
super(
|
|
22
|
-
this.agentRuntime = getRuntime(agentIdentifier);
|
|
23
|
-
this.agentInfo = getInfo(agentIdentifier);
|
|
16
|
+
constructor(agentRef) {
|
|
17
|
+
super(agentRef, FEATURE_NAME);
|
|
24
18
|
|
|
25
19
|
/** A buffer to hold on to harvested traces in the case that a retry must be made later */
|
|
26
20
|
this.sentTrace = null;
|
|
27
|
-
this.harvestTimeSeconds =
|
|
21
|
+
this.harvestTimeSeconds = agentRef.init.session_trace.harvestTimeSeconds || 30;
|
|
28
22
|
/** Tied to the entitlement flag response from BCS. Will short circuit operations of the agg if false */
|
|
29
23
|
this.entitled = undefined;
|
|
30
24
|
/** A flag used to decide if the 30 node threshold should be ignored on the first harvest to ensure sending on the first payload */
|
|
@@ -40,12 +34,12 @@ export class Aggregate extends AggregateBase {
|
|
|
40
34
|
/** Sets up event listeners, and initializes this module to run in the correct "mode". Can be triggered from a few places, but makes an effort to only set up listeners once */
|
|
41
35
|
initialize(stMode, stEntitled, ignoreSession) {
|
|
42
36
|
this.entitled ??= stEntitled;
|
|
43
|
-
if (this.blocked || !this.entitled) return deregisterDrain(
|
|
37
|
+
if (this.blocked || !this.entitled) return this.deregisterDrain();
|
|
44
38
|
if (!this.initialized) {
|
|
45
39
|
this.initialized = true;
|
|
46
40
|
/** Store session identifiers at initialization time to be cross-checked later at harvest time for session changes that are subject to race conditions */
|
|
47
|
-
this.ptid = this.
|
|
48
|
-
this.sessionId = this.
|
|
41
|
+
this.ptid = this.agentRef.runtime.ptid;
|
|
42
|
+
this.sessionId = this.agentRef.runtime.session?.state.value;
|
|
49
43
|
// 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.
|
|
50
44
|
this.ee.on(SESSION_EVENTS.RESET, () => {
|
|
51
45
|
if (this.blocked) return;
|
|
@@ -69,12 +63,12 @@ export class Aggregate extends AggregateBase {
|
|
|
69
63
|
|
|
70
64
|
/** ST/SR sampling flow in BCS - https://drive.google.com/file/d/19hwt2oft-8Hh4RrjpLqEXfpP_9wYBLcq/view?usp=sharing */
|
|
71
65
|
/** ST will run in the mode provided by BCS if the session IS NEW. If not... it will use the state of the session entity to determine what mode to run in */
|
|
72
|
-
if (!this.
|
|
66
|
+
if (!this.agentRef.runtime.session.isNew && !ignoreSession) this.mode = this.agentRef.runtime.session.state.sessionTraceMode;else this.mode = stMode;
|
|
73
67
|
|
|
74
68
|
/** If the mode is off, we do not want to hold up draining for other features, so we deregister the feature for now.
|
|
75
69
|
* If it drains later (due to a mode change), data and handlers will instantly drain instead of waiting for the registry. */
|
|
76
|
-
if (this.mode === MODE.OFF) return deregisterDrain(
|
|
77
|
-
this.timeKeeper ??= this.
|
|
70
|
+
if (this.mode === MODE.OFF) return this.deregisterDrain();
|
|
71
|
+
this.timeKeeper ??= this.agentRef.runtime.timeKeeper;
|
|
78
72
|
this.scheduler = new HarvestScheduler('browser/blobs', {
|
|
79
73
|
onFinished: this.onHarvestFinished.bind(this),
|
|
80
74
|
retryDelay: this.harvestTimeSeconds,
|
|
@@ -98,7 +92,7 @@ export class Aggregate extends AggregateBase {
|
|
|
98
92
|
if (this.mode === MODE.ERROR) this.switchToFull();
|
|
99
93
|
}, this.featureName, this.ee);
|
|
100
94
|
}
|
|
101
|
-
this.
|
|
95
|
+
this.agentRef.runtime.session.write({
|
|
102
96
|
sessionTraceMode: this.mode
|
|
103
97
|
});
|
|
104
98
|
this.drain();
|
|
@@ -116,7 +110,7 @@ export class Aggregate extends AggregateBase {
|
|
|
116
110
|
this.traceStorage.prevStoredEvents.clear(); // release references to past events for GC
|
|
117
111
|
if (!this.timeKeeper?.ready) return; // this should likely never happen, but just to be safe, we should never harvest if we cant correct time
|
|
118
112
|
if (this.blocked || this.mode !== MODE.FULL || this.traceStorage.nodeCount === 0) return;
|
|
119
|
-
if (this.sessionId !== this.
|
|
113
|
+
if (this.sessionId !== this.agentRef.runtime.session?.state.value || this.ptid !== this.agentRef.runtime.ptid) return this.abort(3); // if something unexpected happened and we somehow still got to the point of harvesting after a session identifier changed, we should force-exit instead of harvesting
|
|
120
114
|
/** Get the ST nodes from the traceStorage buffer. This also returns helpful metadata about the payload. */
|
|
121
115
|
const {
|
|
122
116
|
stns,
|
|
@@ -127,12 +121,12 @@ export class Aggregate extends AggregateBase {
|
|
|
127
121
|
if (options.retry) {
|
|
128
122
|
this.sentTrace = stns;
|
|
129
123
|
}
|
|
130
|
-
const firstSessionHarvest = !this.
|
|
131
|
-
if (firstSessionHarvest) this.
|
|
124
|
+
const firstSessionHarvest = !this.agentRef.runtime.session.state.traceHarvestStarted;
|
|
125
|
+
if (firstSessionHarvest) this.agentRef.runtime.session.write({
|
|
132
126
|
traceHarvestStarted: true
|
|
133
127
|
});
|
|
134
|
-
const hasReplay = this.
|
|
135
|
-
const endUserId = this.
|
|
128
|
+
const hasReplay = this.agentRef.runtime.session?.state.sessionReplayMode === 1;
|
|
129
|
+
const endUserId = this.agentRef.info?.jsAttributes?.['enduser.id'];
|
|
136
130
|
this.everHarvested = true;
|
|
137
131
|
|
|
138
132
|
/** The blob consumer expects the following and will reject if not supplied:
|
|
@@ -144,19 +138,19 @@ export class Aggregate extends AggregateBase {
|
|
|
144
138
|
*
|
|
145
139
|
* For data that does not fit the schema of the above, it should be url-encoded and placed into `attributes`
|
|
146
140
|
*/
|
|
147
|
-
const agentMetadata = this.
|
|
141
|
+
const agentMetadata = this.agentRef.runtime.appMetadata?.agents?.[0] || {};
|
|
148
142
|
return {
|
|
149
143
|
qs: {
|
|
150
|
-
browser_monitoring_key: this.
|
|
144
|
+
browser_monitoring_key: this.agentRef.info.licenseKey,
|
|
151
145
|
type: 'BrowserSessionChunk',
|
|
152
|
-
app_id: this.
|
|
146
|
+
app_id: this.agentRef.info.applicationID,
|
|
153
147
|
protocol_version: '0',
|
|
154
148
|
timestamp: Math.floor(this.timeKeeper.correctRelativeTimestamp(earliestTimeStamp)),
|
|
155
149
|
attributes: encodeObj({
|
|
156
150
|
...(agentMetadata.entityGuid && {
|
|
157
151
|
entityGuid: agentMetadata.entityGuid
|
|
158
152
|
}),
|
|
159
|
-
harvestId: "".concat(this.
|
|
153
|
+
harvestId: "".concat(this.agentRef.runtime.session?.state.value, "_").concat(this.agentRef.runtime.ptid, "_").concat(this.agentRef.runtime.harvestCount),
|
|
160
154
|
// this section of attributes must be controllable and stay below the query param padding limit -- see QUERY_PARAM_PADDING
|
|
161
155
|
// if not, data could be lost to truncation at time of sending, potentially breaking parsing / API behavior in NR1
|
|
162
156
|
// trace payload metadata
|
|
@@ -165,7 +159,7 @@ export class Aggregate extends AggregateBase {
|
|
|
165
159
|
'trace.nodes': stns.length,
|
|
166
160
|
'trace.originTimestamp': this.timeKeeper.correctedOriginTime,
|
|
167
161
|
// other payload metadata
|
|
168
|
-
agentVersion: this.
|
|
162
|
+
agentVersion: this.agentRef.runtime.version,
|
|
169
163
|
...(firstSessionHarvest && {
|
|
170
164
|
firstSessionHarvest
|
|
171
165
|
}),
|
|
@@ -204,7 +198,7 @@ export class Aggregate extends AggregateBase {
|
|
|
204
198
|
if (this.mode === MODE.FULL || !this.entitled || this.blocked) return;
|
|
205
199
|
const prevMode = this.mode;
|
|
206
200
|
this.mode = MODE.FULL;
|
|
207
|
-
this.
|
|
201
|
+
this.agentRef.runtime.session.write({
|
|
208
202
|
sessionTraceMode: this.mode
|
|
209
203
|
});
|
|
210
204
|
if (prevMode === MODE.OFF || !this.initialized) return this.initialize(this.mode, this.entitled);
|
|
@@ -218,7 +212,7 @@ export class Aggregate extends AggregateBase {
|
|
|
218
212
|
abort(reason) {
|
|
219
213
|
this.blocked = true;
|
|
220
214
|
this.mode = MODE.OFF;
|
|
221
|
-
this.
|
|
215
|
+
this.agentRef.runtime.session.write({
|
|
222
216
|
sessionTraceMode: this.mode
|
|
223
217
|
});
|
|
224
218
|
this.scheduler?.stopTimer();
|
|
@@ -46,7 +46,7 @@ export class TraceStorage {
|
|
|
46
46
|
if (this.parent.blocked) return;
|
|
47
47
|
if (this.nodeCount >= MAX_NODES_PER_HARVEST) {
|
|
48
48
|
// limit the amount of pending data awaiting next harvest
|
|
49
|
-
if (this.parent.
|
|
49
|
+
if (this.parent.mode !== MODE.ERROR) return;
|
|
50
50
|
const openedSpace = this.trimSTNs(ERROR_MODE_SECONDS_WINDOW); // but maybe we could make some space by discarding irrelevant nodes if we're in sessioned Error mode
|
|
51
51
|
if (openedSpace === 0) return;
|
|
52
52
|
}
|
|
@@ -8,7 +8,6 @@ import { wrapEvents } from '../../../common/wrap/wrap-events';
|
|
|
8
8
|
import { InstrumentBase } from '../../utils/instrument-base';
|
|
9
9
|
import * as CONSTANTS from '../constants';
|
|
10
10
|
import { FEATURE_NAMES } from '../../../loaders/features/features';
|
|
11
|
-
import { deregisterDrain } from '../../../common/drain/drain';
|
|
12
11
|
import { canEnableSessionTracking } from '../../utils/feature-gates';
|
|
13
12
|
import { now } from '../../../common/timing/now';
|
|
14
13
|
const {
|
|
@@ -23,11 +22,11 @@ const {
|
|
|
23
22
|
} = CONSTANTS;
|
|
24
23
|
export class Instrument extends InstrumentBase {
|
|
25
24
|
static featureName = FEATURE_NAME;
|
|
26
|
-
constructor(
|
|
27
|
-
super(
|
|
25
|
+
constructor(agentRef, auto = true) {
|
|
26
|
+
super(agentRef, FEATURE_NAME, auto);
|
|
28
27
|
const canTrackSession = canEnableSessionTracking(this.agentIdentifier);
|
|
29
28
|
if (!canTrackSession) {
|
|
30
|
-
deregisterDrain(
|
|
29
|
+
this.deregisterDrain();
|
|
31
30
|
return;
|
|
32
31
|
}
|
|
33
32
|
const thisInstrumentEE = this.ee;
|
|
@@ -63,7 +62,7 @@ export class Instrument extends InstrumentBase {
|
|
|
63
62
|
} catch (e) {
|
|
64
63
|
// Per NEWRELIC-8525, we don't have a fallback for capturing resources for older versions that don't support PO at this time.
|
|
65
64
|
}
|
|
66
|
-
this.importAggregator({
|
|
65
|
+
this.importAggregator(agentRef, {
|
|
67
66
|
resourceObserver: observer
|
|
68
67
|
});
|
|
69
68
|
}
|
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
import { getConfigurationValue } from '../../../common/config/init';
|
|
2
|
-
import { deregisterDrain } from '../../../common/drain/drain';
|
|
3
1
|
import { handle } from '../../../common/event-emitter/handle';
|
|
4
2
|
import { registerHandler } from '../../../common/event-emitter/register-handler';
|
|
5
3
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler';
|
|
@@ -15,14 +13,14 @@ import { InitialPageLoadInteraction } from './initial-page-load-interaction';
|
|
|
15
13
|
import { Interaction } from './interaction';
|
|
16
14
|
export class Aggregate extends AggregateBase {
|
|
17
15
|
static featureName = FEATURE_NAME;
|
|
18
|
-
constructor(
|
|
16
|
+
constructor(agentRef, {
|
|
19
17
|
domObserver
|
|
20
18
|
}) {
|
|
21
|
-
super(
|
|
22
|
-
const harvestTimeSeconds =
|
|
19
|
+
super(agentRef, FEATURE_NAME);
|
|
20
|
+
const harvestTimeSeconds = agentRef.init.soft_navigations.harvestTimeSeconds || 10;
|
|
23
21
|
this.interactionsToHarvest = new EventBuffer();
|
|
24
22
|
this.domObserver = domObserver;
|
|
25
|
-
this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentIdentifier);
|
|
23
|
+
this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentRef.agentIdentifier);
|
|
26
24
|
timeToFirstByte.subscribe(({
|
|
27
25
|
attrs
|
|
28
26
|
}) => {
|
|
@@ -45,15 +43,12 @@ export class Aggregate extends AggregateBase {
|
|
|
45
43
|
onFinished: this.onHarvestFinished.bind(this),
|
|
46
44
|
retryDelay: harvestTimeSeconds,
|
|
47
45
|
onUnload: () => this.interactionInProgress?.done() // return any held ajax or jserr events so they can be sent with EoL harvest
|
|
48
|
-
},
|
|
49
|
-
agentIdentifier,
|
|
50
|
-
ee: this.ee
|
|
51
|
-
});
|
|
46
|
+
}, this);
|
|
52
47
|
scheduler.harvest.on('events', this.onHarvestStarted.bind(this));
|
|
53
48
|
scheduler.startTimer(harvestTimeSeconds, 0);
|
|
54
49
|
} else {
|
|
55
50
|
this.blocked = true; // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
|
|
56
|
-
deregisterDrain(
|
|
51
|
+
this.deregisterDrain();
|
|
57
52
|
}
|
|
58
53
|
});
|
|
59
54
|
|
|
@@ -18,8 +18,8 @@ const UI_WAIT_INTERVAL = 1 / 10 * 1000; // assume 10 fps
|
|
|
18
18
|
|
|
19
19
|
export class Instrument extends InstrumentBase {
|
|
20
20
|
static featureName = FEATURE_NAME;
|
|
21
|
-
constructor(
|
|
22
|
-
super(
|
|
21
|
+
constructor(agentRef, auto = true) {
|
|
22
|
+
super(agentRef, FEATURE_NAME, auto);
|
|
23
23
|
if (!isBrowserScope || !gosNREUMOriginals().o.MO) return; // soft navigations is not supported outside web env or browsers without the mutation observer API
|
|
24
24
|
|
|
25
25
|
const historyEE = wrapHistory(this.ee);
|
|
@@ -61,7 +61,7 @@ export class Instrument extends InstrumentBase {
|
|
|
61
61
|
});
|
|
62
62
|
for (let eventType of INTERACTION_TRIGGERS) document.addEventListener(eventType, () => {/* no-op, this ensures the UI events are monitored by our callback above */});
|
|
63
63
|
this.abortHandler = abort;
|
|
64
|
-
this.importAggregator({
|
|
64
|
+
this.importAggregator(agentRef, {
|
|
65
65
|
domObserver
|
|
66
66
|
});
|
|
67
67
|
function abort() {
|
|
@@ -9,8 +9,6 @@ import { shouldCollectEvent } from '../../../common/deny-list/deny-list';
|
|
|
9
9
|
import { navTimingValues as navTiming } from '../../../common/timing/nav-timing';
|
|
10
10
|
import { generateUuid } from '../../../common/ids/unique-id';
|
|
11
11
|
import { Interaction } from './interaction';
|
|
12
|
-
import { getConfigurationValue } from '../../../common/config/init';
|
|
13
|
-
import { getRuntime } from '../../../common/config/runtime';
|
|
14
12
|
import { eventListenerOpts } from '../../../common/event-listener/event-listener-opts';
|
|
15
13
|
import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler';
|
|
16
14
|
import { Serializer } from './serializer';
|
|
@@ -24,7 +22,6 @@ import { bundleId } from '../../../common/ids/bundle-id';
|
|
|
24
22
|
import { loadedAsDeferredBrowserScript } from '../../../common/constants/runtime';
|
|
25
23
|
import { handle } from '../../../common/event-emitter/handle';
|
|
26
24
|
import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
|
|
27
|
-
import { deregisterDrain } from '../../../common/drain/drain';
|
|
28
25
|
import { warn } from '../../../common/util/console';
|
|
29
26
|
import { EventBuffer } from '../../utils/event-buffer';
|
|
30
27
|
const {
|
|
@@ -47,12 +44,11 @@ const {
|
|
|
47
44
|
} = CONSTANTS;
|
|
48
45
|
export class Aggregate extends AggregateBase {
|
|
49
46
|
static featureName = FEATURE_NAME;
|
|
50
|
-
constructor(
|
|
51
|
-
super(
|
|
52
|
-
const agentRuntime = getRuntime(agentIdentifier);
|
|
47
|
+
constructor(agentRef) {
|
|
48
|
+
super(agentRef, FEATURE_NAME);
|
|
53
49
|
this.state = {
|
|
54
|
-
initialPageURL:
|
|
55
|
-
lastSeenUrl:
|
|
50
|
+
initialPageURL: agentRef.runtime.origin,
|
|
51
|
+
lastSeenUrl: agentRef.runtime.origin,
|
|
56
52
|
lastSeenRouteName: null,
|
|
57
53
|
timerMap: {},
|
|
58
54
|
timerBudget: MAX_TIMER_BUDGET,
|
|
@@ -63,10 +59,10 @@ export class Aggregate extends AggregateBase {
|
|
|
63
59
|
pageLoaded: false,
|
|
64
60
|
childTime: 0,
|
|
65
61
|
depth: 0,
|
|
66
|
-
harvestTimeSeconds:
|
|
62
|
+
harvestTimeSeconds: agentRef.init.spa.harvestTimeSeconds || 10,
|
|
67
63
|
interactionsToHarvest: new EventBuffer(),
|
|
68
64
|
// The below feature flag is used to disable the SPA ajax fix for specific customers, see https://new-relic.atlassian.net/browse/NR-172169
|
|
69
|
-
disableSpaFix: (
|
|
65
|
+
disableSpaFix: (agentRef.init.feature_flags || []).indexOf('disable-spa-fix') > -1
|
|
70
66
|
};
|
|
71
67
|
let scheduler;
|
|
72
68
|
this.serializer = new Serializer(this);
|
|
@@ -74,7 +70,7 @@ export class Aggregate extends AggregateBase {
|
|
|
74
70
|
state,
|
|
75
71
|
serializer
|
|
76
72
|
} = this;
|
|
77
|
-
const baseEE = ee.get(agentIdentifier); // <-- parent baseEE
|
|
73
|
+
const baseEE = ee.get(agentRef.agentIdentifier); // <-- parent baseEE
|
|
78
74
|
const mutationEE = baseEE.get('mutation');
|
|
79
75
|
const promiseEE = baseEE.get('promise');
|
|
80
76
|
const historyEE = baseEE.get('history');
|
|
@@ -122,19 +118,16 @@ export class Aggregate extends AggregateBase {
|
|
|
122
118
|
scheduler = new HarvestScheduler('events', {
|
|
123
119
|
onFinished: onHarvestFinished,
|
|
124
120
|
retryDelay: state.harvestTimeSeconds
|
|
125
|
-
},
|
|
126
|
-
agentIdentifier,
|
|
127
|
-
ee: baseEE
|
|
128
|
-
});
|
|
121
|
+
}, this);
|
|
129
122
|
scheduler.harvest.on('events', onHarvestStarted);
|
|
130
123
|
this.drain();
|
|
131
124
|
} else {
|
|
132
125
|
this.blocked = true;
|
|
133
|
-
deregisterDrain(
|
|
126
|
+
this.deregisterDrain();
|
|
134
127
|
}
|
|
135
128
|
});
|
|
136
|
-
if (
|
|
137
|
-
state.initialPageLoad = new Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
|
|
129
|
+
if (agentRef.init.spa.enabled !== true) return;
|
|
130
|
+
state.initialPageLoad = new Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier);
|
|
138
131
|
state.initialPageLoad.save = true;
|
|
139
132
|
state.prevInteraction = state.initialPageLoad;
|
|
140
133
|
state.currentNode = state.initialPageLoad.root; // hint
|
|
@@ -215,7 +208,7 @@ export class Aggregate extends AggregateBase {
|
|
|
215
208
|
// Otherwise, if no interaction is currently active, create a new node ID,
|
|
216
209
|
// and let the aggregator know that we entered a new event handler callback
|
|
217
210
|
// so that it has a chance to possibly start an interaction.
|
|
218
|
-
var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
|
|
211
|
+
var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier);
|
|
219
212
|
|
|
220
213
|
// Store the interaction as prevInteraction in case it is prematurely discarded
|
|
221
214
|
state.prevInteraction = ixn;
|
|
@@ -306,7 +299,7 @@ export class Aggregate extends AggregateBase {
|
|
|
306
299
|
this.sent = true;
|
|
307
300
|
node.dt = this.dt;
|
|
308
301
|
if (node.dt?.timestamp) {
|
|
309
|
-
node.dt.timestamp =
|
|
302
|
+
node.dt.timestamp = agentRef.runtime.timeKeeper.correctAbsoluteTimestamp(node.dt.timestamp);
|
|
310
303
|
}
|
|
311
304
|
node.jsEnd = node.start = this.startTime;
|
|
312
305
|
node[INTERACTION][REMAINING]++;
|
|
@@ -395,7 +388,7 @@ export class Aggregate extends AggregateBase {
|
|
|
395
388
|
if (dtPayload && this[SPA_NODE]) {
|
|
396
389
|
this[SPA_NODE].dt = dtPayload;
|
|
397
390
|
if (this[SPA_NODE].dt?.timestamp) {
|
|
398
|
-
this[SPA_NODE].dt.timestamp =
|
|
391
|
+
this[SPA_NODE].dt.timestamp = agentRef.runtime.timeKeeper.correctAbsoluteTimestamp(this[SPA_NODE].dt.timestamp);
|
|
399
392
|
}
|
|
400
393
|
}
|
|
401
394
|
}
|
|
@@ -513,7 +506,7 @@ export class Aggregate extends AggregateBase {
|
|
|
513
506
|
}, this.featureName, promiseEE);
|
|
514
507
|
register(INTERACTION_API + 'get', function (t) {
|
|
515
508
|
var interaction;
|
|
516
|
-
if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION];else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION];else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
|
|
509
|
+
if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION];else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION];else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier);
|
|
517
510
|
if (!state.currentNode) {
|
|
518
511
|
interaction.checkFinish();
|
|
519
512
|
if (state.depth) setCurrentNode(interaction.root);
|
|
@@ -642,11 +635,11 @@ export class Aggregate extends AggregateBase {
|
|
|
642
635
|
register('function-err', function (args, obj, error) {
|
|
643
636
|
if (!state.currentNode) return;
|
|
644
637
|
error.__newrelic ??= {};
|
|
645
|
-
error.__newrelic[agentIdentifier] = {
|
|
638
|
+
error.__newrelic[agentRef.agentIdentifier] = {
|
|
646
639
|
interactionId: state.currentNode.interaction.id
|
|
647
640
|
};
|
|
648
641
|
if (state.currentNode.type && state.currentNode.type !== 'interaction') {
|
|
649
|
-
error.__newrelic[agentIdentifier].interactionNodeId = state.currentNode.id;
|
|
642
|
+
error.__newrelic[agentRef.agentIdentifier].interactionNodeId = state.currentNode.id;
|
|
650
643
|
}
|
|
651
644
|
}, this.featureName, baseEE);
|
|
652
645
|
baseEE.on('interaction', saveInteraction);
|
|
@@ -684,9 +677,5 @@ export class Aggregate extends AggregateBase {
|
|
|
684
677
|
scheduler?.scheduleHarvest(0);
|
|
685
678
|
if (!scheduler) warn(19);
|
|
686
679
|
}
|
|
687
|
-
function isEnabled() {
|
|
688
|
-
var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled');
|
|
689
|
-
return enabled !== false;
|
|
690
|
-
}
|
|
691
680
|
}
|
|
692
681
|
}
|
|
@@ -33,8 +33,8 @@ const {
|
|
|
33
33
|
*/
|
|
34
34
|
export class Instrument extends InstrumentBase {
|
|
35
35
|
static featureName = FEATURE_NAME;
|
|
36
|
-
constructor(
|
|
37
|
-
super(
|
|
36
|
+
constructor(agentRef, auto = true) {
|
|
37
|
+
super(agentRef, FEATURE_NAME, auto);
|
|
38
38
|
if (!isBrowserScope) return; // SPA not supported outside web env
|
|
39
39
|
|
|
40
40
|
try {
|
|
@@ -58,7 +58,7 @@ export class Instrument extends InstrumentBase {
|
|
|
58
58
|
promiseEE.on(CB_END, endTimestamp);
|
|
59
59
|
jsonpEE.on(CB_END, endTimestamp);
|
|
60
60
|
this.ee.on('fn-err', (...args) => {
|
|
61
|
-
if (!args[2]?.__newrelic?.[agentIdentifier]) handle('function-err', [...args], undefined, this.featureName, this.ee);
|
|
61
|
+
if (!args[2]?.__newrelic?.[agentRef.agentIdentifier]) handle('function-err', [...args], undefined, this.featureName, this.ee);
|
|
62
62
|
});
|
|
63
63
|
this.ee.buffer([FN_START, FN_END, 'xhr-resolved'], this.featureName);
|
|
64
64
|
eventsEE.buffer([FN_START], this.featureName);
|
|
@@ -105,7 +105,7 @@ export class Instrument extends InstrumentBase {
|
|
|
105
105
|
});
|
|
106
106
|
}
|
|
107
107
|
this.abortHandler = this.#abort;
|
|
108
|
-
this.importAggregator();
|
|
108
|
+
this.importAggregator(agentRef);
|
|
109
109
|
}
|
|
110
110
|
|
|
111
111
|
/** Restoration and resource release tasks to be done if SPA loader is being aborted. Unwind changes to globals and subscription to DOM events. */
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { FeatureBase } from './feature-base';
|
|
2
|
-
import {
|
|
3
|
-
import { getRuntime } from '../../common/config/runtime';
|
|
2
|
+
import { isValid } from '../../common/config/info';
|
|
4
3
|
import { configure } from '../../loaders/configure/configure';
|
|
5
4
|
import { gosCDN } from '../../common/window/nreum';
|
|
6
|
-
import {
|
|
5
|
+
import { drain } from '../../common/drain/drain';
|
|
7
6
|
import { activatedFeatures } from '../../common/util/feature-flags';
|
|
8
7
|
import { Obfuscator } from '../../common/util/obfuscate';
|
|
9
8
|
export class AggregateBase extends FeatureBase {
|
|
10
|
-
constructor(
|
|
11
|
-
super(
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
9
|
+
constructor(agentRef, featureName) {
|
|
10
|
+
super(agentRef.agentIdentifier, featureName);
|
|
11
|
+
this.agentRef = agentRef;
|
|
12
|
+
this.checkConfiguration(agentRef);
|
|
13
|
+
this.obfuscator = agentRef.runtime.obfuscator;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
/**
|
|
@@ -37,7 +37,7 @@ export class AggregateBase extends FeatureBase {
|
|
|
37
37
|
return flagsPromise.catch(err => {
|
|
38
38
|
this.ee.emit('internal-error', [err]);
|
|
39
39
|
this.blocked = true;
|
|
40
|
-
deregisterDrain(
|
|
40
|
+
this.deregisterDrain();
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
drain() {
|
|
@@ -49,7 +49,7 @@ export class AggregateBase extends FeatureBase {
|
|
|
49
49
|
* Checks for additional `jsAttributes` items to support backward compatibility with implementations of the agent where
|
|
50
50
|
* loader configurations may appear after the loader code is executed.
|
|
51
51
|
*/
|
|
52
|
-
checkConfiguration() {
|
|
52
|
+
checkConfiguration(existingAgent) {
|
|
53
53
|
// NOTE: This check has to happen at aggregator load time
|
|
54
54
|
if (!isValid(this.agentIdentifier)) {
|
|
55
55
|
const cdn = gosCDN();
|
|
@@ -59,7 +59,7 @@ export class AggregateBase extends FeatureBase {
|
|
|
59
59
|
try {
|
|
60
60
|
jsAttributes = {
|
|
61
61
|
...jsAttributes,
|
|
62
|
-
...
|
|
62
|
+
...existingAgent.info?.jsAttributes
|
|
63
63
|
};
|
|
64
64
|
} catch (err) {
|
|
65
65
|
// do nothing
|
|
@@ -72,12 +72,11 @@ export class AggregateBase extends FeatureBase {
|
|
|
72
72
|
...cdn.info,
|
|
73
73
|
jsAttributes
|
|
74
74
|
},
|
|
75
|
-
runtime:
|
|
75
|
+
runtime: existingAgent.runtime
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
runtime.obfuscator = new Obfuscator(this.agentIdentifier);
|
|
78
|
+
if (!existingAgent.runtime.obfuscator) {
|
|
79
|
+
existingAgent.runtime.obfuscator = new Obfuscator(this.agentIdentifier);
|
|
81
80
|
}
|
|
82
81
|
}
|
|
83
82
|
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { ee } from '../../common/event-emitter/contextual-ee';
|
|
2
|
+
import { deregisterDrain } from '../../common/drain/drain';
|
|
2
3
|
export class FeatureBase {
|
|
3
|
-
constructor(agentIdentifier,
|
|
4
|
+
constructor(agentIdentifier, featureName) {
|
|
4
5
|
/** @type {string} */
|
|
5
6
|
this.agentIdentifier = agentIdentifier;
|
|
6
|
-
/** @type {import('../../common/aggregate/aggregator').Aggregator} */
|
|
7
|
-
this.aggregator = aggregator;
|
|
8
7
|
/** @type {import('../../common/event-emitter/contextual-ee').ee} */
|
|
9
8
|
this.ee = ee.get(agentIdentifier);
|
|
10
9
|
/** @type {string} */
|
|
@@ -16,4 +15,7 @@ export class FeatureBase {
|
|
|
16
15
|
*/
|
|
17
16
|
this.blocked = false;
|
|
18
17
|
}
|
|
18
|
+
deregisterDrain() {
|
|
19
|
+
deregisterDrain(this.agentIdentifier, this.featureName);
|
|
20
|
+
}
|
|
19
21
|
}
|
|
@@ -10,7 +10,6 @@ import { onWindowLoad } from '../../common/window/load';
|
|
|
10
10
|
import { isBrowserScope } from '../../common/constants/runtime';
|
|
11
11
|
import { warn } from '../../common/util/console';
|
|
12
12
|
import { FEATURE_NAMES } from '../../loaders/features/features';
|
|
13
|
-
import { getConfigurationValue } from '../../common/config/init';
|
|
14
13
|
import { hasReplayPrerequisite } from '../session_replay/shared/utils';
|
|
15
14
|
import { canEnableSessionTracking } from './feature-gates';
|
|
16
15
|
import { single } from '../../common/util/invoke';
|
|
@@ -23,14 +22,13 @@ export class InstrumentBase extends FeatureBase {
|
|
|
23
22
|
/**
|
|
24
23
|
* Instantiate InstrumentBase.
|
|
25
24
|
* @param {string} agentIdentifier - The unique ID of the instantiated agent (relative to global scope).
|
|
26
|
-
* @param {import('../../common/aggregate/aggregator').Aggregator} aggregator - The shared Aggregator that will handle batching and reporting of data.
|
|
27
25
|
* @param {string} featureName - The name of the feature module (used to construct file path).
|
|
28
26
|
* @param {boolean} [auto=true] - Determines whether the feature should automatically register to have the draining
|
|
29
27
|
* of its pooled instrumentation data handled by the agent's centralized drain functionality, rather than draining
|
|
30
28
|
* immediately. Primarily useful for fine-grained control in tests.
|
|
31
29
|
*/
|
|
32
|
-
constructor(
|
|
33
|
-
super(agentIdentifier,
|
|
30
|
+
constructor(agentRef, featureName, auto = true) {
|
|
31
|
+
super(agentRef.agentIdentifier, featureName);
|
|
34
32
|
this.auto = auto;
|
|
35
33
|
|
|
36
34
|
/** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
|
|
@@ -50,15 +48,15 @@ export class InstrumentBase extends FeatureBase {
|
|
|
50
48
|
this.onAggregateImported = undefined;
|
|
51
49
|
|
|
52
50
|
/** used in conjunction with newrelic.start() to defer harvesting in features */
|
|
53
|
-
if (
|
|
51
|
+
if (agentRef.init[this.featureName].autoStart === false) this.auto = false;
|
|
54
52
|
/** if the feature requires opt-in (!auto-start), it will get registered once the api has been called */
|
|
55
|
-
if (this.auto) registerDrain(agentIdentifier, featureName);else {
|
|
53
|
+
if (this.auto) registerDrain(agentRef.agentIdentifier, featureName);else {
|
|
56
54
|
this.ee.on('manual-start-all', single(() => {
|
|
57
55
|
// register the feature to drain only once the API has been called, it will drain when importAggregator finishes for all the features
|
|
58
56
|
// called by the api in that cycle
|
|
59
|
-
registerDrain(
|
|
57
|
+
registerDrain(agentRef.agentIdentifier, this.featureName);
|
|
60
58
|
this.auto = true;
|
|
61
|
-
this.importAggregator();
|
|
59
|
+
this.importAggregator(agentRef);
|
|
62
60
|
}));
|
|
63
61
|
}
|
|
64
62
|
}
|
|
@@ -66,10 +64,11 @@ export class InstrumentBase extends FeatureBase {
|
|
|
66
64
|
/**
|
|
67
65
|
* Lazy-load the latter part of the feature: its aggregator. This method is called by the first part of the feature
|
|
68
66
|
* (the instrumentation) when instrumentation is complete.
|
|
67
|
+
* @param agentRef - reference to the base agent ancestor that this feature belongs to
|
|
69
68
|
* @param {Object} [argsObjFromInstrument] - any values or references to pass down to aggregate
|
|
70
69
|
* @returns void
|
|
71
70
|
*/
|
|
72
|
-
importAggregator(argsObjFromInstrument = {}) {
|
|
71
|
+
importAggregator(agentRef, argsObjFromInstrument = {}) {
|
|
73
72
|
if (this.featAggregate || !this.auto) return;
|
|
74
73
|
let loadedSuccessfully;
|
|
75
74
|
this.onAggregateImported = new Promise(resolve => {
|
|
@@ -91,6 +90,15 @@ export class InstrumentBase extends FeatureBase {
|
|
|
91
90
|
if (this.featureName === FEATURE_NAMES.sessionReplay) this.abortHandler?.(); // SR should stop recording if session DNE
|
|
92
91
|
}
|
|
93
92
|
|
|
93
|
+
// Create a single Aggregator for this agent if DNE yet; to be used by jserror endpoint features.
|
|
94
|
+
if (!agentRef.sharedAggregator) {
|
|
95
|
+
agentRef.sharedAggregator = import(/* webpackChunkName: "shared-aggregator" */'../../common/aggregate/aggregator');
|
|
96
|
+
const {
|
|
97
|
+
Aggregator
|
|
98
|
+
} = await agentRef.sharedAggregator;
|
|
99
|
+
agentRef.sharedAggregator = new Aggregator();
|
|
100
|
+
} else await agentRef.sharedAggregator; // if another feature is already importing the aggregator, wait for it to finish
|
|
101
|
+
|
|
94
102
|
/**
|
|
95
103
|
* Note this try-catch differs from the one in Agent.run() in that it's placed later in a page's lifecycle and
|
|
96
104
|
* it's only responsible for aborting its one specific feature, rather than all.
|
|
@@ -107,7 +115,7 @@ export class InstrumentBase extends FeatureBase {
|
|
|
107
115
|
const {
|
|
108
116
|
Aggregate
|
|
109
117
|
} = await lazyFeatureLoader(this.featureName, 'aggregate');
|
|
110
|
-
this.featAggregate = new Aggregate(
|
|
118
|
+
this.featAggregate = new Aggregate(agentRef, argsObjFromInstrument);
|
|
111
119
|
loadedSuccessfully(true);
|
|
112
120
|
} catch (e) {
|
|
113
121
|
warn(34, e);
|
|
@@ -10,7 +10,6 @@ import { featurePriority, FEATURE_NAMES } from './features/features';
|
|
|
10
10
|
// required features
|
|
11
11
|
import { Instrument as PageViewEvent } from '../features/page_view_event/instrument';
|
|
12
12
|
// common files
|
|
13
|
-
import { Aggregator } from '../common/aggregate/aggregator';
|
|
14
13
|
import { gosNREUM, setNREUMInitializedAgent } from '../common/window/nreum';
|
|
15
14
|
import { warn } from '../common/util/console';
|
|
16
15
|
import { globalScope } from '../common/constants/runtime';
|
|
@@ -32,9 +31,6 @@ export class Agent extends AgentBase {
|
|
|
32
31
|
warn(21);
|
|
33
32
|
return;
|
|
34
33
|
}
|
|
35
|
-
this.sharedAggregator = new Aggregator({
|
|
36
|
-
agentIdentifier: this.agentIdentifier
|
|
37
|
-
});
|
|
38
34
|
this.features = {};
|
|
39
35
|
setNREUMInitializedAgent(this.agentIdentifier, this); // append this agent onto the global NREUM.initializedAgents
|
|
40
36
|
|
|
@@ -74,7 +70,7 @@ export class Agent extends AgentBase {
|
|
|
74
70
|
missingDependencies
|
|
75
71
|
});
|
|
76
72
|
}
|
|
77
|
-
this.features[InstrumentCtor.featureName] = new InstrumentCtor(this
|
|
73
|
+
this.features[InstrumentCtor.featureName] = new InstrumentCtor(this);
|
|
78
74
|
});
|
|
79
75
|
} catch (err) {
|
|
80
76
|
warn(22, err);
|