@newrelic/browser-agent 1.246.1 → 1.248.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 +24 -0
- package/README.md +10 -2
- package/dist/cjs/common/config/state/info.js +2 -1
- package/dist/cjs/common/config/state/init.js +2 -1
- package/dist/cjs/common/config/state/loader-config.js +2 -1
- package/dist/cjs/common/config/state/runtime.js +2 -1
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/constants/runtime.js +3 -1
- package/dist/cjs/common/dispatch/global-event.js +19 -0
- package/dist/cjs/common/session/session-entity.js +14 -9
- package/dist/cjs/common/util/feature-flags.js +17 -12
- package/dist/cjs/common/window/load.js +1 -0
- package/dist/cjs/common/window/nreum.js +18 -17
- package/dist/cjs/features/metrics/aggregate/index.js +4 -2
- package/dist/cjs/features/session_replay/aggregate/index.js +70 -20
- package/dist/cjs/features/session_trace/aggregate/index.js +33 -18
- package/dist/cjs/features/spa/aggregate/index.js +7 -1
- package/dist/cjs/features/utils/aggregate-base.js +3 -1
- package/dist/cjs/loaders/agent-base.js +19 -0
- package/dist/cjs/loaders/agent.js +6 -4
- package/dist/cjs/loaders/api/api.js +10 -1
- package/dist/cjs/loaders/configure/configure.js +14 -13
- package/dist/cjs/loaders/configure/nonce.js +13 -0
- package/dist/cjs/loaders/configure/nonce.npm.js +2 -0
- package/dist/cjs/loaders/micro-agent.js +5 -4
- package/dist/esm/common/config/state/info.js +3 -2
- package/dist/esm/common/config/state/init.js +3 -2
- package/dist/esm/common/config/state/loader-config.js +3 -2
- package/dist/esm/common/config/state/runtime.js +3 -2
- 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 +1 -0
- package/dist/esm/common/dispatch/global-event.js +13 -0
- package/dist/esm/common/session/session-entity.js +14 -9
- package/dist/esm/common/util/feature-flags.js +17 -12
- package/dist/esm/common/window/load.js +1 -1
- package/dist/esm/common/window/nreum.js +16 -16
- package/dist/esm/features/metrics/aggregate/index.js +4 -2
- package/dist/esm/features/session_replay/aggregate/index.js +69 -19
- package/dist/esm/features/session_trace/aggregate/index.js +33 -18
- package/dist/esm/features/spa/aggregate/index.js +7 -1
- package/dist/esm/features/utils/aggregate-base.js +3 -1
- package/dist/esm/loaders/agent-base.js +19 -0
- package/dist/esm/loaders/agent.js +7 -5
- package/dist/esm/loaders/api/api.js +10 -1
- package/dist/esm/loaders/configure/configure.js +15 -14
- package/dist/esm/loaders/configure/nonce.js +11 -0
- package/dist/esm/loaders/configure/nonce.npm.js +1 -0
- package/dist/esm/loaders/micro-agent.js +6 -5
- package/dist/types/common/config/state/info.d.ts.map +1 -1
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/config/state/loader-config.d.ts.map +1 -1
- package/dist/types/common/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/constants/runtime.d.ts +1 -0
- package/dist/types/common/constants/runtime.d.ts.map +1 -1
- package/dist/types/common/dispatch/global-event.d.ts +2 -0
- package/dist/types/common/dispatch/global-event.d.ts.map +1 -0
- package/dist/types/common/session/session-entity.d.ts +1 -0
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/window/load.d.ts +1 -0
- package/dist/types/common/window/load.d.ts.map +1 -1
- package/dist/types/common/window/nreum.d.ts +7 -1
- package/dist/types/common/window/nreum.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +11 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/loaders/agent-base.d.ts +13 -0
- package/dist/types/loaders/agent-base.d.ts.map +1 -1
- package/dist/types/loaders/agent.d.ts.map +1 -1
- package/dist/types/loaders/api/api.d.ts +2 -0
- package/dist/types/loaders/api/api.d.ts.map +1 -1
- package/dist/types/loaders/configure/configure.d.ts +4 -11
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/configure/nonce.d.ts +1 -0
- package/dist/types/loaders/configure/nonce.d.ts.map +1 -0
- package/dist/types/loaders/configure/nonce.npm.d.ts +1 -0
- package/dist/types/loaders/configure/nonce.npm.d.ts.map +1 -0
- package/dist/types/loaders/micro-agent.d.ts +2 -2
- package/dist/types/loaders/micro-agent.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/common/config/state/info.js +3 -2
- package/src/common/config/state/init.js +3 -2
- package/src/common/config/state/loader-config.js +3 -2
- package/src/common/config/state/runtime.js +3 -2
- package/src/common/constants/runtime.js +2 -0
- package/src/common/dispatch/global-event.js +12 -0
- package/src/common/session/session-entity.js +13 -9
- package/src/common/util/feature-flags.js +15 -12
- package/src/common/window/__mocks__/nreum.js +2 -1
- package/src/common/window/load.js +1 -1
- package/src/common/window/nreum.js +15 -18
- package/src/features/metrics/aggregate/index.js +5 -1
- package/src/features/session_replay/aggregate/index.js +74 -23
- package/src/features/session_trace/aggregate/index.js +33 -14
- package/src/features/spa/aggregate/index.js +10 -1
- package/src/features/utils/aggregate-base.js +1 -1
- package/src/loaders/agent-base.js +19 -0
- package/src/loaders/agent.js +5 -5
- package/src/loaders/api/api.js +12 -1
- package/src/loaders/configure/configure.js +17 -15
- package/src/loaders/configure/nonce.js +12 -0
- package/src/loaders/configure/nonce.npm.js +1 -0
- package/src/loaders/micro-agent.js +5 -4
|
@@ -22,6 +22,9 @@ var _aggregateBase = require("../../utils/aggregate-base");
|
|
|
22
22
|
var _firstContentfulPaint = require("../../../common/vitals/first-contentful-paint");
|
|
23
23
|
var _firstPaint = require("../../../common/vitals/first-paint");
|
|
24
24
|
var _bundleId = require("../../../common/ids/bundle-id");
|
|
25
|
+
var _runtime = require("../../../common/constants/runtime");
|
|
26
|
+
var _handle = require("../../../common/event-emitter/handle");
|
|
27
|
+
var _constants2 = require("../../metrics/constants");
|
|
25
28
|
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
|
|
26
29
|
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
|
|
27
30
|
/*
|
|
@@ -186,7 +189,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
186
189
|
var ev = args[0];
|
|
187
190
|
var evName = ev.type;
|
|
188
191
|
var eventNode = ev["__nrNode:".concat(_bundleId.bundleId)];
|
|
189
|
-
if (!state.pageLoaded && evName === 'load' && eventSource === window) {
|
|
192
|
+
if (!state.pageLoaded && (evName === 'load' && eventSource === window || _runtime.loadedAsDeferredBrowserScript)) {
|
|
190
193
|
state.pageLoaded = true;
|
|
191
194
|
// set to null so prevNode is set correctly
|
|
192
195
|
this.prevNode = state.currentNode = null;
|
|
@@ -671,6 +674,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
|
|
|
671
674
|
}
|
|
672
675
|
baseEE.emit('interactionSaved', [interaction]);
|
|
673
676
|
state.interactionsToHarvest.push(interaction);
|
|
677
|
+
let smCategory = 'RouteChange';
|
|
678
|
+
if (interaction.root?.attrs?.trigger === 'initialPageLoad') smCategory = 'InitialPageLoad';else if (interaction.root?.attrs?.trigger === 'api') smCategory = 'Custom';
|
|
679
|
+
(0, _handle.handle)(_constants2.SUPPORTABILITY_METRIC_CHANNEL, ["Spa/Interaction/".concat(smCategory, "/Duration/Ms"), Math.max((interaction.root?.end || 0) - (interaction.root?.start || 0), 0)], undefined, _features.FEATURE_NAMES.metrics, baseEE);
|
|
674
680
|
scheduler.scheduleHarvest(0);
|
|
675
681
|
}
|
|
676
682
|
function isEnabled() {
|
|
@@ -49,7 +49,9 @@ class AggregateBase extends _featureBase.FeatureBase {
|
|
|
49
49
|
} catch (err) {
|
|
50
50
|
// do nothing
|
|
51
51
|
}
|
|
52
|
-
(0, _configure.configure)(
|
|
52
|
+
(0, _configure.configure)({
|
|
53
|
+
agentIdentifier: this.agentIdentifier
|
|
54
|
+
}, {
|
|
53
55
|
...(0, _nreum.gosCDN)(),
|
|
54
56
|
info: {
|
|
55
57
|
...(0, _nreum.gosCDN)().info,
|
|
@@ -106,5 +106,24 @@ class AgentBase {
|
|
|
106
106
|
start(featureNames) {
|
|
107
107
|
(0, _console.warn)('Call to agent api addRelease failed. The agent is not currently initialized.');
|
|
108
108
|
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Forces a replay to record. If a replay is already actively recording, this call will be ignored.
|
|
112
|
+
* If a recording has not been started, a new one will be created. If a recording has been started, but is currently not recording, it will resume recording.
|
|
113
|
+
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/recordReplay/}
|
|
114
|
+
*/
|
|
115
|
+
recordReplay() {
|
|
116
|
+
(0, _console.warn)('Call to agent api recordReplay failed. The agent is not currently initialized.');
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Forces an active replay to pause recording. If a replay is already actively recording, this call will cause the recording to pause.
|
|
121
|
+
* If a recording is not currently recording, this call will be ignored. This API will pause both manual and automatic replays that are in progress.
|
|
122
|
+
* The only way to resume recording after manually pausing a replay is to manually record again using the recordReplay() API.
|
|
123
|
+
* {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/recordReplay/}
|
|
124
|
+
*/
|
|
125
|
+
pauseReplay() {
|
|
126
|
+
(0, _console.warn)('Call to agent api pauseReplay failed. The agent is not currently initialized.');
|
|
127
|
+
}
|
|
109
128
|
}
|
|
110
129
|
exports.AgentBase = AgentBase;
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.Agent = void 0;
|
|
7
7
|
require("./configure/public-path.npm");
|
|
8
|
+
require("./configure/nonce.npm");
|
|
8
9
|
var _agentBase = require("./agent-base");
|
|
9
10
|
var _enabledFeatures = require("./features/enabled-features");
|
|
10
11
|
var _configure = require("./configure/configure");
|
|
@@ -49,12 +50,15 @@ class Agent extends _agentBase.AgentBase {
|
|
|
49
50
|
agentIdentifier: this.agentIdentifier
|
|
50
51
|
});
|
|
51
52
|
this.features = {};
|
|
53
|
+
(0, _nreum.setNREUMInitializedAgent)(agentIdentifier, this); // append this agent onto the global NREUM.initializedAgents
|
|
54
|
+
|
|
52
55
|
this.desiredFeatures = new Set(options.features || []); // expected to be a list of static Instrument/InstrumentBase classes, see "spa.js" for example
|
|
53
56
|
// For Now... ALL agents must make the rum call whether the page_view_event feature was enabled or not.
|
|
54
57
|
// NR1 creates an index on the rum call, and if not seen for a few days, will remove the browser app!
|
|
55
58
|
// Future work is being planned to evaluate removing this behavior from the backend, but for now we must ensure this call is made
|
|
56
59
|
this.desiredFeatures.add(_instrument.Instrument);
|
|
57
|
-
|
|
60
|
+
(0, _configure.configure)(this, options, options.loaderType || 'agent'); // add api, exposed, and other config properties
|
|
61
|
+
|
|
58
62
|
this.run();
|
|
59
63
|
}
|
|
60
64
|
get config() {
|
|
@@ -66,7 +70,6 @@ class Agent extends _agentBase.AgentBase {
|
|
|
66
70
|
};
|
|
67
71
|
}
|
|
68
72
|
run() {
|
|
69
|
-
const NR_FEATURES_REF_NAME = 'features';
|
|
70
73
|
// Attempt to initialize all the requested features (sequentially in prio order & synchronously), with any failure aborting the whole process.
|
|
71
74
|
try {
|
|
72
75
|
const enabledFeatures = (0, _enabledFeatures.getEnabledFeatures)(this.agentIdentifier);
|
|
@@ -81,7 +84,6 @@ class Agent extends _agentBase.AgentBase {
|
|
|
81
84
|
this.features[InstrumentCtor.featureName] = new InstrumentCtor(this.agentIdentifier, this.sharedAggregator);
|
|
82
85
|
}
|
|
83
86
|
});
|
|
84
|
-
(0, _nreum.gosNREUMInitializedAgents)(this.agentIdentifier, this.features, NR_FEATURES_REF_NAME);
|
|
85
87
|
} catch (err) {
|
|
86
88
|
(0, _console.warn)('Failed to initialize all enabled instrument classes (agent aborted) -', err);
|
|
87
89
|
for (const featName in this.features) {
|
|
@@ -90,7 +92,7 @@ class Agent extends _agentBase.AgentBase {
|
|
|
90
92
|
}
|
|
91
93
|
const newrelic = (0, _nreum.gosNREUM)();
|
|
92
94
|
delete newrelic.initializedAgents[this.agentIdentifier]?.api; // prevent further calls to agent-specific APIs (see "configure.js")
|
|
93
|
-
delete newrelic.initializedAgents[this.agentIdentifier]?.
|
|
95
|
+
delete newrelic.initializedAgents[this.agentIdentifier]?.features; // GC mem used internally by features
|
|
94
96
|
delete this.sharedAggregator;
|
|
95
97
|
// Keep the initialized agent object with its configs for troubleshooting purposes.
|
|
96
98
|
newrelic.ee?.abort(); // set flag and clear global backlog
|
|
@@ -26,7 +26,7 @@ const CUSTOM_ATTR_GROUP = 'CUSTOM/'; // the subgroup items should be stored unde
|
|
|
26
26
|
exports.CUSTOM_ATTR_GROUP = CUSTOM_ATTR_GROUP;
|
|
27
27
|
function setTopLevelCallers() {
|
|
28
28
|
const nr = (0, _nreum.gosCDN)();
|
|
29
|
-
const funcs = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start'];
|
|
29
|
+
const funcs = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', 'recordReplay', 'pauseReplay'];
|
|
30
30
|
funcs.forEach(f => {
|
|
31
31
|
nr[f] = function () {
|
|
32
32
|
for (var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
@@ -147,6 +147,14 @@ function setAPI(agentIdentifier, forceDrain) {
|
|
|
147
147
|
(0, _console.warn)('An unexpected issue occurred', err);
|
|
148
148
|
}
|
|
149
149
|
};
|
|
150
|
+
apiInterface.recordReplay = function () {
|
|
151
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/recordReplay/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
|
|
152
|
+
(0, _handle.handle)('recordReplay', [], undefined, _features.FEATURE_NAMES.sessionReplay, instanceEE);
|
|
153
|
+
};
|
|
154
|
+
apiInterface.pauseReplay = function () {
|
|
155
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/pauseReplay/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
|
|
156
|
+
(0, _handle.handle)('pauseReplay', [], undefined, _features.FEATURE_NAMES.sessionReplay, instanceEE);
|
|
157
|
+
};
|
|
150
158
|
apiInterface.interaction = function () {
|
|
151
159
|
return new InteractionHandle().get();
|
|
152
160
|
};
|
|
@@ -156,6 +164,7 @@ function setAPI(agentIdentifier, forceDrain) {
|
|
|
156
164
|
var contextStore = {};
|
|
157
165
|
var ixn = this;
|
|
158
166
|
var hasCb = typeof cb === 'function';
|
|
167
|
+
(0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/createTracer/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
|
|
159
168
|
(0, _handle.handle)(spaPrefix + 'tracer', [(0, _now.now)(), name, contextStore], ixn, _features.FEATURE_NAMES.spa, instanceEE);
|
|
160
169
|
return function () {
|
|
161
170
|
tracerEE.emit((hasCb ? '' : 'no-') + 'fn-start', [(0, _now.now)(), ixn, hasCb], contextStore);
|
|
@@ -12,7 +12,10 @@ var _runtime = require("../../common/constants/runtime");
|
|
|
12
12
|
var _publicPath = require("./public-path");
|
|
13
13
|
let alreadySetOnce = false; // the configure() function can run multiple times in agent lifecycle
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* Sets or re-sets the agent's configuration values from global settings. This also attach those as properties to the agent instance.
|
|
17
|
+
*/
|
|
18
|
+
function configure(agent) {
|
|
16
19
|
let opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
17
20
|
let loaderType = arguments.length > 2 ? arguments[2] : undefined;
|
|
18
21
|
let forceDrain = arguments.length > 3 ? arguments[3] : undefined;
|
|
@@ -33,31 +36,29 @@ function configure(agentIdentifier) {
|
|
|
33
36
|
// eslint-disable-next-line camelcase
|
|
34
37
|
loader_config = nr.loader_config;
|
|
35
38
|
}
|
|
36
|
-
(0, _config.setConfiguration)(agentIdentifier, init || {});
|
|
39
|
+
(0, _config.setConfiguration)(agent.agentIdentifier, init || {});
|
|
37
40
|
// eslint-disable-next-line camelcase
|
|
38
|
-
(0, _config.setLoaderConfig)(agentIdentifier, loader_config || {});
|
|
41
|
+
(0, _config.setLoaderConfig)(agent.agentIdentifier, loader_config || {});
|
|
39
42
|
info.jsAttributes ??= {};
|
|
40
43
|
if (_runtime.isWorkerScope) {
|
|
41
44
|
// add a default attr to all worker payloads
|
|
42
45
|
info.jsAttributes.isWorker = true;
|
|
43
46
|
}
|
|
44
|
-
(0, _config.setInfo)(agentIdentifier, info);
|
|
45
|
-
const updatedInit = (0, _config.getConfiguration)(agentIdentifier);
|
|
47
|
+
(0, _config.setInfo)(agent.agentIdentifier, info);
|
|
48
|
+
const updatedInit = (0, _config.getConfiguration)(agent.agentIdentifier);
|
|
46
49
|
const internalTrafficList = [info.beacon, info.errorBeacon];
|
|
47
50
|
if (!alreadySetOnce) {
|
|
48
|
-
alreadySetOnce = true;
|
|
49
51
|
if (updatedInit.proxy.assets) {
|
|
50
52
|
(0, _publicPath.redefinePublicPath)(updatedInit.proxy.assets);
|
|
51
53
|
internalTrafficList.push(updatedInit.proxy.assets);
|
|
52
54
|
}
|
|
53
55
|
if (updatedInit.proxy.beacon) internalTrafficList.push(updatedInit.proxy.beacon);
|
|
56
|
+
(0, _api.setTopLevelCallers)(); // no need to set global APIs on newrelic obj more than once
|
|
57
|
+
(0, _nreum.addToNREUM)('activatedFeatures', _featureFlags.activatedFeatures);
|
|
54
58
|
}
|
|
55
59
|
runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
|
|
56
|
-
(0, _config.setRuntime)(agentIdentifier, runtime);
|
|
57
|
-
(0, _api.
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
(0, _nreum.gosNREUMInitializedAgents)(agentIdentifier, exposed, 'exposed');
|
|
61
|
-
(0, _nreum.addToNREUM)('activatedFeatures', _featureFlags.activatedFeatures);
|
|
62
|
-
return api;
|
|
60
|
+
(0, _config.setRuntime)(agent.agentIdentifier, runtime);
|
|
61
|
+
if (agent.api === undefined) agent.api = (0, _api.setAPI)(agent.agentIdentifier, forceDrain);
|
|
62
|
+
if (agent.exposed === undefined) agent.exposed = exposed;
|
|
63
|
+
alreadySetOnce = true;
|
|
63
64
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/* global __webpack_require__ */
|
|
4
|
+
|
|
5
|
+
__webpack_require__.nc = (() => {
|
|
6
|
+
try {
|
|
7
|
+
return document?.currentScript?.nonce;
|
|
8
|
+
} catch (ex) {
|
|
9
|
+
// Swallow error and proceed like nonce is not defined
|
|
10
|
+
// This will happen when the agent is loaded in a worker scope
|
|
11
|
+
}
|
|
12
|
+
return '';
|
|
13
|
+
})();
|
|
@@ -38,12 +38,14 @@ class MicroAgent extends _agentBase.AgentBase {
|
|
|
38
38
|
agentIdentifier: this.agentIdentifier
|
|
39
39
|
});
|
|
40
40
|
this.features = {};
|
|
41
|
-
|
|
41
|
+
(0, _nreum.setNREUMInitializedAgent)(agentIdentifier, this);
|
|
42
|
+
(0, _configure.configure)(this, {
|
|
42
43
|
...options,
|
|
43
44
|
runtime: {
|
|
44
45
|
isolatedBacklog: true
|
|
45
46
|
}
|
|
46
|
-
}, options.loaderType || 'micro-agent')
|
|
47
|
+
}, options.loaderType || 'micro-agent');
|
|
48
|
+
Object.assign(this, this.api); // the APIs should be available at the class level for micro-agent
|
|
47
49
|
|
|
48
50
|
/**
|
|
49
51
|
* Starts a set of agent features if not running in "autoStart" mode
|
|
@@ -98,8 +100,7 @@ class MicroAgent extends _agentBase.AgentBase {
|
|
|
98
100
|
}
|
|
99
101
|
});
|
|
100
102
|
});
|
|
101
|
-
|
|
102
|
-
return this;
|
|
103
|
+
return true;
|
|
103
104
|
} catch (err) {
|
|
104
105
|
(0, _console.warn)('Failed to initialize instrument classes.', err);
|
|
105
106
|
return false;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defaults as nrDefaults,
|
|
1
|
+
import { defaults as nrDefaults, getNREUMInitializedAgent } from '../../window/nreum';
|
|
2
2
|
import { getModeledObject } from './configurable';
|
|
3
3
|
const model = {
|
|
4
4
|
// preset defaults
|
|
@@ -38,5 +38,6 @@ export function getInfo(id) {
|
|
|
38
38
|
export function setInfo(id, obj) {
|
|
39
39
|
if (!id) throw new Error('All info objects require an agent identifier!');
|
|
40
40
|
_cache[id] = getModeledObject(obj, model);
|
|
41
|
-
|
|
41
|
+
const agentInst = getNREUMInitializedAgent(id);
|
|
42
|
+
if (agentInst) agentInst.info = _cache[id];
|
|
42
43
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { isValidSelector } from '../../dom/query-selector';
|
|
2
2
|
import { DEFAULT_EXPIRES_MS, DEFAULT_INACTIVE_MS } from '../../session/constants';
|
|
3
3
|
import { warn } from '../../util/console';
|
|
4
|
-
import {
|
|
4
|
+
import { getNREUMInitializedAgent } from '../../window/nreum';
|
|
5
5
|
import { getModeledObject } from './configurable';
|
|
6
6
|
const model = () => {
|
|
7
7
|
const hiddenState = {
|
|
@@ -165,7 +165,8 @@ export function getConfiguration(id) {
|
|
|
165
165
|
export function setConfiguration(id, obj) {
|
|
166
166
|
if (!id) throw new Error(missingAgentIdError);
|
|
167
167
|
_cache[id] = getModeledObject(obj, model());
|
|
168
|
-
|
|
168
|
+
const agentInst = getNREUMInitializedAgent(id);
|
|
169
|
+
if (agentInst) agentInst.init = _cache[id];
|
|
169
170
|
}
|
|
170
171
|
export function getConfigurationValue(id, path) {
|
|
171
172
|
if (!id) throw new Error(missingAgentIdError);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getNREUMInitializedAgent } from '../../window/nreum';
|
|
2
2
|
import { getModeledObject } from './configurable';
|
|
3
3
|
const model = {
|
|
4
4
|
accountID: undefined,
|
|
@@ -17,5 +17,6 @@ export function getLoaderConfig(id) {
|
|
|
17
17
|
export function setLoaderConfig(id, obj) {
|
|
18
18
|
if (!id) throw new Error('All loader-config objects require an agent identifier!');
|
|
19
19
|
_cache[id] = getModeledObject(obj, model);
|
|
20
|
-
|
|
20
|
+
const agentInst = getNREUMInitializedAgent(id);
|
|
21
|
+
if (agentInst) agentInst.loader_config = _cache[id];
|
|
21
22
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getModeledObject } from './configurable';
|
|
2
|
-
import {
|
|
2
|
+
import { getNREUMInitializedAgent } from '../../window/nreum';
|
|
3
3
|
import { globalScope } from '../../constants/runtime';
|
|
4
4
|
import { BUILD_ENV, DIST_METHOD, VERSION } from "../../constants/env.npm";
|
|
5
5
|
const model = {
|
|
@@ -31,5 +31,6 @@ export function getRuntime(id) {
|
|
|
31
31
|
export function setRuntime(id, obj) {
|
|
32
32
|
if (!id) throw new Error('All runtime objects require an agent identifier!');
|
|
33
33
|
_cache[id] = getModeledObject(obj, model);
|
|
34
|
-
|
|
34
|
+
const agentInst = getNREUMInitializedAgent(id);
|
|
35
|
+
if (agentInst) agentInst.runtime = _cache[id];
|
|
35
36
|
}
|
|
@@ -15,6 +15,7 @@ export const isBrowserScope = typeof window !== 'undefined' && !!window.document
|
|
|
15
15
|
*/
|
|
16
16
|
export const isWorkerScope = typeof WorkerGlobalScope !== 'undefined' && (typeof self !== 'undefined' && self instanceof WorkerGlobalScope && self.navigator instanceof WorkerNavigator || typeof globalThis !== 'undefined' && globalThis instanceof WorkerGlobalScope && globalThis.navigator instanceof WorkerNavigator);
|
|
17
17
|
export const globalScope = isBrowserScope ? window : typeof WorkerGlobalScope !== 'undefined' && (typeof self !== 'undefined' && self instanceof WorkerGlobalScope && self || typeof globalThis !== 'undefined' && globalThis instanceof WorkerGlobalScope && globalThis);
|
|
18
|
+
export const loadedAsDeferredBrowserScript = globalScope?.document?.readyState === 'complete';
|
|
18
19
|
export const initiallyHidden = Boolean(globalScope?.document?.visibilityState === 'hidden');
|
|
19
20
|
export const initialLocation = '' + globalScope?.location;
|
|
20
21
|
export const isiOS = /iPad|iPhone|iPod/.test(globalScope.navigator?.userAgent);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { globalScope } from '../constants/runtime';
|
|
2
|
+
const GLOBAL_EVENT_NAMESPACE = 'newrelic';
|
|
3
|
+
export function dispatchGlobalEvent() {
|
|
4
|
+
let detail = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
|
|
5
|
+
try {
|
|
6
|
+
globalScope.dispatchEvent(new CustomEvent(GLOBAL_EVENT_NAMESPACE, {
|
|
7
|
+
detail
|
|
8
|
+
}));
|
|
9
|
+
} catch (err) {
|
|
10
|
+
// something happened... dispatchEvent or CustomEvent might not be supported
|
|
11
|
+
// decide what to do about it here
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -104,8 +104,8 @@ export class SessionEntity {
|
|
|
104
104
|
this.expiresTimer = new Timer({
|
|
105
105
|
// When the inactive timer ends, collect a SM and reset the session
|
|
106
106
|
onEnd: () => {
|
|
107
|
-
this.collectSM('expired'
|
|
108
|
-
this.collectSM('duration'
|
|
107
|
+
this.collectSM('expired');
|
|
108
|
+
this.collectSM('duration');
|
|
109
109
|
this.reset();
|
|
110
110
|
}
|
|
111
111
|
}, this.state.expiresAt - Date.now());
|
|
@@ -121,8 +121,8 @@ export class SessionEntity {
|
|
|
121
121
|
this.inactiveTimer = new InteractionTimer({
|
|
122
122
|
// When the inactive timer ends, collect a SM and reset the session
|
|
123
123
|
onEnd: () => {
|
|
124
|
-
this.collectSM('inactive'
|
|
125
|
-
this.collectSM('duration'
|
|
124
|
+
this.collectSM('inactive');
|
|
125
|
+
this.collectSM('duration');
|
|
126
126
|
this.reset();
|
|
127
127
|
},
|
|
128
128
|
// When the inactive timer refreshes, it will update the storage values with an update timestamp
|
|
@@ -172,14 +172,14 @@ export class SessionEntity {
|
|
|
172
172
|
if (this.isInvalid(obj)) return {};
|
|
173
173
|
// if the session expires, collect a SM count before resetting
|
|
174
174
|
if (this.isExpired(obj.expiresAt)) {
|
|
175
|
-
this.collectSM('expired'
|
|
175
|
+
this.collectSM('expired');
|
|
176
176
|
this.collectSM('duration', obj, true);
|
|
177
177
|
return this.reset();
|
|
178
178
|
}
|
|
179
179
|
// if "inactive" timer is expired at "read" time -- esp. initial read -- reset
|
|
180
180
|
// collect a SM count before resetting
|
|
181
181
|
if (this.isExpired(obj.inactiveAt)) {
|
|
182
|
-
this.collectSM('inactive'
|
|
182
|
+
this.collectSM('inactive');
|
|
183
183
|
this.collectSM('duration', obj, true);
|
|
184
184
|
return this.reset();
|
|
185
185
|
}
|
|
@@ -270,15 +270,20 @@ export class SessionEntity {
|
|
|
270
270
|
collectSM(type, data, useUpdatedAt) {
|
|
271
271
|
let value, tag;
|
|
272
272
|
if (type === 'duration') {
|
|
273
|
-
|
|
274
|
-
const endingTimestamp = useUpdatedAt ? data.updatedAt : Date.now();
|
|
275
|
-
value = endingTimestamp - startingTimestamp;
|
|
273
|
+
value = this.getDuration(data, useUpdatedAt);
|
|
276
274
|
tag = 'Session/Duration/Ms';
|
|
277
275
|
}
|
|
278
276
|
if (type === 'expired') tag = 'Session/Expired/Seen';
|
|
279
277
|
if (type === 'inactive') tag = 'Session/Inactive/Seen';
|
|
280
278
|
if (tag) handle(SUPPORTABILITY_METRIC_CHANNEL, [tag, value], undefined, FEATURE_NAMES.metrics, this.ee);
|
|
281
279
|
}
|
|
280
|
+
getDuration() {
|
|
281
|
+
let data = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.state;
|
|
282
|
+
let useUpdatedAt = arguments.length > 1 ? arguments[1] : undefined;
|
|
283
|
+
const startingTimestamp = data.expiresAt - this.expiresMs;
|
|
284
|
+
const endingTimestamp = !useUpdatedAt ? data.updatedAt : Date.now();
|
|
285
|
+
return endingTimestamp - startingTimestamp;
|
|
286
|
+
}
|
|
282
287
|
|
|
283
288
|
/**
|
|
284
289
|
* @param {number} futureMs - The number of ms to use to generate a future timestamp
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { ee } from '../event-emitter/contextual-ee';
|
|
6
6
|
import { handle } from '../event-emitter/handle';
|
|
7
7
|
import { FEATURE_NAMES } from '../../loaders/features/features';
|
|
8
|
+
import { dispatchGlobalEvent } from '../dispatch/global-event';
|
|
8
9
|
const bucketMap = {
|
|
9
10
|
stn: [FEATURE_NAMES.sessionTrace],
|
|
10
11
|
err: [FEATURE_NAMES.jserrors, FEATURE_NAMES.metrics],
|
|
@@ -18,18 +19,17 @@ const sentIds = new Set();
|
|
|
18
19
|
export function activateFeatures(flags, agentIdentifier) {
|
|
19
20
|
const sharedEE = ee.get(agentIdentifier);
|
|
20
21
|
if (!(flags && typeof flags === 'object')) return;
|
|
21
|
-
if (
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
22
|
+
if (sentIds.has(agentIdentifier)) return;
|
|
23
|
+
Object.entries(flags).forEach(_ref => {
|
|
24
|
+
let [flag, num] = _ref;
|
|
25
|
+
if (bucketMap[flag]) {
|
|
26
|
+
bucketMap[flag].forEach(feat => {
|
|
27
|
+
if (!num) handle('block-' + flag, [], undefined, feat, sharedEE);else handle('feat-' + flag, [], undefined, feat, sharedEE);
|
|
28
|
+
handle('rumresp-' + flag, [Boolean(num)], undefined, feat, sharedEE); // this is a duplicate of feat-/block- but makes awaiting for 1 event easier than 2
|
|
29
|
+
});
|
|
30
|
+
} else if (num) handle('feat-' + flag, [], undefined, undefined, sharedEE); // not sure what other flags are overlooked, but there's a test for ones not in the map --
|
|
31
|
+
activatedFeatures[flag] = Boolean(num);
|
|
32
|
+
});
|
|
33
33
|
|
|
34
34
|
// Let the features waiting on their respective flags know that RUM response was received and that any missing flags are interpreted as bad entitlement / "off".
|
|
35
35
|
// Hence, those features will not be hanging forever if their flags aren't included in the response.
|
|
@@ -40,5 +40,10 @@ export function activateFeatures(flags, agentIdentifier) {
|
|
|
40
40
|
}
|
|
41
41
|
});
|
|
42
42
|
sentIds.add(agentIdentifier);
|
|
43
|
+
|
|
44
|
+
// let any window level subscribers know that the agent is running
|
|
45
|
+
dispatchGlobalEvent({
|
|
46
|
+
loaded: true
|
|
47
|
+
});
|
|
43
48
|
}
|
|
44
49
|
export const activatedFeatures = {};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { windowAddEventListener, documentAddEventListener } from '../event-listener/event-listener-opts';
|
|
2
|
-
function checkState() {
|
|
2
|
+
export function checkState() {
|
|
3
3
|
return typeof document === 'undefined' || document.readyState === 'complete';
|
|
4
4
|
}
|
|
5
5
|
export function onWindowLoad(cb, useCapture) {
|
|
@@ -55,24 +55,24 @@ export function gosNREUMOriginals() {
|
|
|
55
55
|
}
|
|
56
56
|
return nr;
|
|
57
57
|
}
|
|
58
|
-
export function
|
|
58
|
+
export function setNREUMInitializedAgent(id, newAgentInstance) {
|
|
59
59
|
let nr = gosNREUM();
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
ms: now(),
|
|
65
|
-
date: new Date()
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
nr.initializedAgents = {
|
|
69
|
-
...externallySupplied,
|
|
70
|
-
[id]: {
|
|
71
|
-
...curr,
|
|
72
|
-
[target]: obj
|
|
73
|
-
}
|
|
60
|
+
nr.initializedAgents ??= {};
|
|
61
|
+
newAgentInstance.initializedAt = {
|
|
62
|
+
ms: now(),
|
|
63
|
+
date: new Date()
|
|
74
64
|
};
|
|
75
|
-
|
|
65
|
+
nr.initializedAgents[id] = newAgentInstance;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Get the agent instance under the associated identifier on the global newrelic object.
|
|
70
|
+
* @see setNREUMInitializedAgents
|
|
71
|
+
* @returns Existing agent instance under newrelic.initializedAgent[id], or undefined if it does not exist.
|
|
72
|
+
*/
|
|
73
|
+
export function getNREUMInitializedAgent(id) {
|
|
74
|
+
let nr = gosNREUM();
|
|
75
|
+
return nr.initializedAgents?.[id];
|
|
76
76
|
}
|
|
77
77
|
export function addToNREUM(fnName, fn) {
|
|
78
78
|
let nr = gosNREUM();
|
|
@@ -63,10 +63,12 @@ export class Aggregate extends AggregateBase {
|
|
|
63
63
|
} = getRuntime(this.agentIdentifier);
|
|
64
64
|
if (loaderType) this.storeSupportabilityMetrics("Generic/LoaderType/".concat(loaderType, "/Detected"));
|
|
65
65
|
if (distMethod) this.storeSupportabilityMetrics("Generic/DistMethod/".concat(distMethod, "/Detected"));
|
|
66
|
-
|
|
67
|
-
// frameworks on page
|
|
68
66
|
if (isBrowserScope) {
|
|
69
67
|
this.storeSupportabilityMetrics('Generic/Runtime/Browser/Detected');
|
|
68
|
+
const nonce = document?.currentScript?.nonce;
|
|
69
|
+
if (nonce && nonce !== '') {
|
|
70
|
+
this.storeSupportabilityMetrics('Generic/Runtime/Nonce/Detected');
|
|
71
|
+
}
|
|
70
72
|
|
|
71
73
|
// These SMs are used by the AppExp team
|
|
72
74
|
onDOMContentLoaded(() => {
|