@newrelic/browser-agent 1.284.1 → 1.286.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.
Files changed (83) hide show
  1. package/CHANGELOG.md +29 -0
  2. package/README.md +6 -0
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/dom/selector-path.js +1 -1
  6. package/dist/cjs/common/harvest/harvester.js +29 -2
  7. package/dist/cjs/common/util/feature-flags.js +8 -2
  8. package/dist/cjs/features/logging/aggregate/index.js +1 -1
  9. package/dist/cjs/features/session_replay/shared/recorder.js +8 -10
  10. package/dist/cjs/features/session_replay/shared/utils.js +12 -0
  11. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +3 -2
  12. package/dist/cjs/features/utils/aggregate-base.js +4 -6
  13. package/dist/cjs/features/utils/event-store-manager.js +15 -1
  14. package/dist/cjs/features/utils/nr1-debugger.js +1 -1
  15. package/dist/cjs/loaders/agent-base.js +1 -1
  16. package/dist/cjs/loaders/agent.js +3 -1
  17. package/dist/cjs/loaders/api/api.js +68 -59
  18. package/dist/cjs/loaders/api/apiAsync.js +19 -22
  19. package/dist/cjs/loaders/configure/configure.js +20 -7
  20. package/dist/cjs/loaders/features/features.js +4 -3
  21. package/dist/cjs/loaders/micro-agent-base.js +1 -1
  22. package/dist/cjs/loaders/micro-agent.js +3 -1
  23. package/dist/esm/common/constants/env.cdn.js +1 -1
  24. package/dist/esm/common/constants/env.npm.js +1 -1
  25. package/dist/esm/common/dom/selector-path.js +1 -1
  26. package/dist/esm/common/harvest/harvester.js +30 -3
  27. package/dist/esm/common/util/feature-flags.js +8 -2
  28. package/dist/esm/features/logging/aggregate/index.js +1 -1
  29. package/dist/esm/features/session_replay/shared/recorder.js +7 -9
  30. package/dist/esm/features/session_replay/shared/utils.js +11 -0
  31. package/dist/esm/features/session_trace/aggregate/trace/storage.js +3 -2
  32. package/dist/esm/features/utils/aggregate-base.js +4 -6
  33. package/dist/esm/features/utils/event-store-manager.js +15 -1
  34. package/dist/esm/features/utils/nr1-debugger.js +1 -1
  35. package/dist/esm/loaders/agent-base.js +1 -1
  36. package/dist/esm/loaders/agent.js +3 -1
  37. package/dist/esm/loaders/api/api.js +67 -58
  38. package/dist/esm/loaders/api/apiAsync.js +14 -17
  39. package/dist/esm/loaders/configure/configure.js +21 -8
  40. package/dist/esm/loaders/features/features.js +3 -2
  41. package/dist/esm/loaders/micro-agent-base.js +1 -1
  42. package/dist/esm/loaders/micro-agent.js +3 -1
  43. package/dist/types/common/dom/selector-path.d.ts.map +1 -1
  44. package/dist/types/common/harvest/harvester.d.ts.map +1 -1
  45. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  46. package/dist/types/features/logging/aggregate/index.d.ts +0 -1
  47. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  48. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  49. package/dist/types/features/session_replay/shared/utils.d.ts +1 -0
  50. package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
  51. package/dist/types/features/utils/event-store-manager.d.ts +5 -1
  52. package/dist/types/features/utils/event-store-manager.d.ts.map +1 -1
  53. package/dist/types/loaders/agent.d.ts +1 -0
  54. package/dist/types/loaders/agent.d.ts.map +1 -1
  55. package/dist/types/loaders/api/api.d.ts +1 -20
  56. package/dist/types/loaders/api/api.d.ts.map +1 -1
  57. package/dist/types/loaders/api/apiAsync.d.ts +1 -1
  58. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  59. package/dist/types/loaders/configure/configure.d.ts +1 -0
  60. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  61. package/dist/types/loaders/features/features.d.ts +2 -0
  62. package/dist/types/loaders/features/features.d.ts.map +1 -1
  63. package/dist/types/loaders/micro-agent.d.ts +1 -0
  64. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  65. package/package.json +1 -1
  66. package/src/common/dom/selector-path.js +1 -3
  67. package/src/common/harvest/harvester.js +33 -3
  68. package/src/common/util/feature-flags.js +10 -2
  69. package/src/features/logging/aggregate/index.js +2 -2
  70. package/src/features/session_replay/shared/recorder.js +7 -9
  71. package/src/features/session_replay/shared/utils.js +12 -0
  72. package/src/features/session_trace/aggregate/trace/storage.js +2 -2
  73. package/src/features/utils/aggregate-base.js +4 -4
  74. package/src/features/utils/event-store-manager.js +15 -1
  75. package/src/features/utils/nr1-debugger.js +1 -1
  76. package/src/loaders/agent-base.js +2 -2
  77. package/src/loaders/agent.js +4 -1
  78. package/src/loaders/api/api.js +64 -58
  79. package/src/loaders/api/apiAsync.js +14 -18
  80. package/src/loaders/configure/configure.js +21 -8
  81. package/src/loaders/features/features.js +3 -2
  82. package/src/loaders/micro-agent-base.js +2 -2
  83. package/src/loaders/micro-agent.js +4 -1
@@ -7,12 +7,10 @@ exports.setAPI = setAPI;
7
7
  exports.setTopLevelCallers = setTopLevelCallers;
8
8
  var _features = require("../features/features");
9
9
  var _info = require("../../common/config/info");
10
- var _runtime = require("../../common/config/runtime");
11
10
  var _handle = require("../../common/event-emitter/handle");
12
- var _contextualEe = require("../../common/event-emitter/contextual-ee");
13
11
  var _drain = require("../../common/drain/drain");
14
12
  var _load = require("../../common/window/load");
15
- var _runtime2 = require("../../common/constants/runtime");
13
+ var _runtime = require("../../common/constants/runtime");
16
14
  var _console = require("../../common/util/console");
17
15
  var _constants = require("../../features/metrics/constants");
18
16
  var _nreum = require("../../common/window/nreum");
@@ -23,6 +21,8 @@ var _constants3 = require("../../common/session/constants");
23
21
  var _constants4 = require("../../features/logging/constants");
24
22
  var _utils = require("../../features/logging/shared/utils");
25
23
  var _wrapLogger = require("../../common/wrap/wrap-logger");
24
+ var _globalEvent = require("../../common/dispatch/global-event");
25
+ var _featureFlags = require("../../common/util/feature-flags");
26
26
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
27
27
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; } /**
28
28
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
@@ -35,41 +35,39 @@ function setTopLevelCallers() {
35
35
  });
36
36
  function caller(fnName, ...args) {
37
37
  let returnVals = [];
38
- Object.values(nr.initializedAgents).forEach(val => {
39
- if (!val || !val.api) {
38
+ Object.values(nr.initializedAgents).forEach(agt => {
39
+ if (!agt || !agt.runtime) {
40
40
  (0, _console.warn)(38, fnName);
41
- } else if (val.exposed && val.api[fnName]) {
42
- returnVals.push(val.api[fnName](...args));
41
+ } else if (agt.exposed && agt[fnName] && agt.runtime.loaderType !== 'micro-agent') {
42
+ returnVals.push(agt[fnName](...args));
43
43
  }
44
44
  });
45
- return returnVals.length > 1 ? returnVals : returnVals[0];
45
+ return returnVals[0];
46
46
  }
47
47
  }
48
48
  const replayRunning = {};
49
- function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
50
- if (!forceDrain) (0, _drain.registerDrain)(agentIdentifier, 'api');
51
- const apiInterface = {};
52
- var instanceEE = _contextualEe.ee.get(agentIdentifier);
53
- var tracerEE = instanceEE.get('tracer');
54
- replayRunning[agentIdentifier] = _constants3.MODE.OFF;
55
- instanceEE.on(_constants2.SR_EVENT_EMITTER_TYPES.REPLAY_RUNNING, isRunning => {
56
- replayRunning[agentIdentifier] = isRunning;
49
+ function setAPI(agent, forceDrain) {
50
+ if (!forceDrain) (0, _drain.registerDrain)(agent.agentIdentifier, 'api');
51
+ const tracerEE = agent.ee.get('tracer');
52
+ replayRunning[agent.agentIdentifier] = _constants3.MODE.OFF;
53
+ agent.ee.on(_constants2.SR_EVENT_EMITTER_TYPES.REPLAY_RUNNING, isRunning => {
54
+ replayRunning[agent.agentIdentifier] = isRunning;
57
55
  });
58
- var prefix = 'api-';
59
- var spaPrefix = prefix + 'ixn-';
60
- apiInterface.log = function (message, {
56
+ const prefix = 'api-';
57
+ const spaPrefix = prefix + 'ixn-';
58
+ agent.log = function (message, {
61
59
  customAttributes = {},
62
60
  level = _constants4.LOG_LEVELS.INFO
63
61
  } = {}) {
64
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/log/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
65
- (0, _utils.bufferLog)(instanceEE, message, customAttributes, level);
62
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/log/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
63
+ (0, _utils.bufferLog)(agent.ee, message, customAttributes, level);
66
64
  };
67
- apiInterface.wrapLogger = (parent, functionName, {
65
+ agent.wrapLogger = (parent, functionName, {
68
66
  customAttributes = {},
69
67
  level = _constants4.LOG_LEVELS.INFO
70
68
  } = {}) => {
71
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/wrapLogger/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
72
- (0, _wrapLogger.wrapLogger)(instanceEE, parent, functionName, {
69
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/wrapLogger/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
70
+ (0, _wrapLogger.wrapLogger)(agent.ee, parent, functionName, {
73
71
  customAttributes,
74
72
  level
75
73
  });
@@ -77,14 +75,14 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
77
75
 
78
76
  // Setup stub functions that queue calls for later processing.
79
77
  _apiMethods.asyncApiMethods.forEach(fnName => {
80
- apiInterface[fnName] = apiCall(prefix, fnName, true, 'api');
78
+ agent[fnName] = apiCall(prefix, fnName, true, 'api');
81
79
  });
82
- apiInterface.addPageAction = apiCall(prefix, 'addPageAction', true, _features.FEATURE_NAMES.genericEvents);
83
- apiInterface.recordCustomEvent = apiCall(prefix, 'recordCustomEvent', true, _features.FEATURE_NAMES.genericEvents);
84
- apiInterface.setPageViewName = function (name, host) {
80
+ agent.addPageAction = apiCall(prefix, 'addPageAction', true, _features.FEATURE_NAMES.genericEvents);
81
+ agent.recordCustomEvent = apiCall(prefix, 'recordCustomEvent', true, _features.FEATURE_NAMES.genericEvents);
82
+ agent.setPageViewName = function (name, host) {
85
83
  if (typeof name !== 'string') return;
86
84
  if (name.charAt(0) !== '/') name = '/' + name;
87
- (0, _runtime.getRuntime)(agentIdentifier).customTransaction = (host || 'http://custom.transaction') + name;
85
+ agent.runtime.customTransaction = (host || 'http://custom.transaction') + name;
88
86
  return apiCall(prefix, 'setPageViewName', true)();
89
87
  };
90
88
 
@@ -97,11 +95,11 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
97
95
  * @returns @see apiCall
98
96
  */
99
97
  function appendJsAttribute(key, value, apiName, addToBrowserStorage) {
100
- const currentInfo = (0, _info.getInfo)(agentIdentifier);
98
+ const currentInfo = agent.info;
101
99
  if (value === null) {
102
100
  delete currentInfo.jsAttributes[key];
103
101
  } else {
104
- (0, _info.setInfo)(agentIdentifier, {
102
+ (0, _info.setInfo)(agent.agentIdentifier, {
105
103
  ...currentInfo,
106
104
  jsAttributes: {
107
105
  ...currentInfo.jsAttributes,
@@ -111,7 +109,7 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
111
109
  }
112
110
  return apiCall(prefix, apiName, true, !!addToBrowserStorage || value === null ? 'session' : undefined)(key, value);
113
111
  }
114
- apiInterface.setCustomAttribute = function (name, value, persistAttribute = false) {
112
+ agent.setCustomAttribute = function (name, value, persistAttribute = false) {
115
113
  if (typeof name !== 'string') {
116
114
  (0, _console.warn)(39, typeof name);
117
115
  return;
@@ -127,7 +125,7 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
127
125
  * @param {string} value - unique user identifier; a null user id suggests none should exist
128
126
  * @returns @see apiCall
129
127
  */
130
- apiInterface.setUserId = function (value) {
128
+ agent.setUserId = function (value) {
131
129
  if (!(typeof value === 'string' || value === null)) {
132
130
  (0, _console.warn)(41, typeof value);
133
131
  return;
@@ -140,30 +138,30 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
140
138
  * @param {string|null} value - Application version -- if null, will "unset" the value
141
139
  * @returns @see apiCall
142
140
  */
143
- apiInterface.setApplicationVersion = function (value) {
141
+ agent.setApplicationVersion = function (value) {
144
142
  if (!(typeof value === 'string' || value === null)) {
145
143
  (0, _console.warn)(42, typeof value);
146
144
  return;
147
145
  }
148
146
  return appendJsAttribute('application.version', value, 'setApplicationVersion', false);
149
147
  };
150
- apiInterface.start = () => {
148
+ agent.start = () => {
151
149
  try {
152
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/start/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
153
- instanceEE.emit('manual-start-all');
150
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/start/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
151
+ agent.ee.emit('manual-start-all');
154
152
  } catch (err) {
155
153
  (0, _console.warn)(23, err);
156
154
  }
157
155
  };
158
- apiInterface[_constants2.SR_EVENT_EMITTER_TYPES.RECORD] = function () {
159
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/recordReplay/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
160
- (0, _handle.handle)(_constants2.SR_EVENT_EMITTER_TYPES.RECORD, [], undefined, _features.FEATURE_NAMES.sessionReplay, instanceEE);
156
+ agent[_constants2.SR_EVENT_EMITTER_TYPES.RECORD] = function () {
157
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/recordReplay/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
158
+ (0, _handle.handle)(_constants2.SR_EVENT_EMITTER_TYPES.RECORD, [], undefined, _features.FEATURE_NAMES.sessionReplay, agent.ee);
161
159
  };
162
- apiInterface[_constants2.SR_EVENT_EMITTER_TYPES.PAUSE] = function () {
163
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/pauseReplay/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
164
- (0, _handle.handle)(_constants2.SR_EVENT_EMITTER_TYPES.PAUSE, [], undefined, _features.FEATURE_NAMES.sessionReplay, instanceEE);
160
+ agent[_constants2.SR_EVENT_EMITTER_TYPES.PAUSE] = function () {
161
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/pauseReplay/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
162
+ (0, _handle.handle)(_constants2.SR_EVENT_EMITTER_TYPES.PAUSE, [], undefined, _features.FEATURE_NAMES.sessionReplay, agent.ee);
165
163
  };
166
- apiInterface.interaction = function (options) {
164
+ agent.interaction = function (options) {
167
165
  return new InteractionHandle().get(typeof options === 'object' ? options : {});
168
166
  };
169
167
  function InteractionHandle() {}
@@ -172,9 +170,9 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
172
170
  var contextStore = {};
173
171
  var ixn = this;
174
172
  var hasCb = typeof cb === 'function';
175
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/createTracer/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
173
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/createTracer/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
176
174
  // Soft navigations won't support Tracer nodes, but this fn should still work the same otherwise (e.g., run the orig cb).
177
- if (!runSoftNavOverSpa) (0, _handle.handle)(spaPrefix + 'tracer', [(0, _now.now)(), name, contextStore], ixn, _features.FEATURE_NAMES.spa, instanceEE);
175
+ if (!agent.runSoftNavOverSpa) (0, _handle.handle)(spaPrefix + 'tracer', [(0, _now.now)(), name, contextStore], ixn, _features.FEATURE_NAMES.spa, agent.ee);
178
176
  return function () {
179
177
  tracerEE.emit((hasCb ? '' : 'no-') + 'fn-start', [(0, _now.now)(), ixn, hasCb], contextStore);
180
178
  if (hasCb) {
@@ -193,36 +191,47 @@ function setAPI(agentIdentifier, forceDrain, runSoftNavOverSpa = false) {
193
191
  }
194
192
  };
195
193
  ['actionText', 'setName', 'setAttribute', 'save', 'ignore', 'onEnd', 'getContext', 'end', 'get'].forEach(name => {
196
- InteractionApiProto[name] = apiCall(spaPrefix, name, undefined, runSoftNavOverSpa ? _features.FEATURE_NAMES.softNav : _features.FEATURE_NAMES.spa);
194
+ InteractionApiProto[name] = apiCall(spaPrefix, name, undefined, agent.runSoftNavOverSpa ? _features.FEATURE_NAMES.softNav : _features.FEATURE_NAMES.spa);
197
195
  });
198
- apiInterface.setCurrentRouteName = runSoftNavOverSpa ? apiCall(spaPrefix, 'routeName', undefined, _features.FEATURE_NAMES.softNav) : apiCall(prefix, 'routeName', true, _features.FEATURE_NAMES.spa);
196
+ agent.setCurrentRouteName = agent.runSoftNavOverSpa ? apiCall(spaPrefix, 'routeName', undefined, _features.FEATURE_NAMES.softNav) : apiCall(prefix, 'routeName', true, _features.FEATURE_NAMES.spa);
199
197
  function apiCall(prefix, name, notSpa, bufferGroup) {
200
198
  return function () {
201
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/' + name + '/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
202
- if (bufferGroup) (0, _handle.handle)(prefix + name, [notSpa ? (0, _now.now)() : performance.now(), ...arguments], notSpa ? null : this, bufferGroup, instanceEE); // no bufferGroup means only the SM is emitted
199
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/' + name + '/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
200
+ (0, _globalEvent.dispatchGlobalEvent)({
201
+ agentIdentifier: agent.agentIdentifier,
202
+ drained: !!_featureFlags.activatedFeatures?.[agent.agentIdentifier],
203
+ type: 'data',
204
+ name: 'api',
205
+ feature: prefix + name,
206
+ data: {
207
+ notSpa,
208
+ bufferGroup
209
+ }
210
+ });
211
+ if (bufferGroup) (0, _handle.handle)(prefix + name, [notSpa ? (0, _now.now)() : performance.now(), ...arguments], notSpa ? null : this, bufferGroup, agent.ee); // no bufferGroup means only the SM is emitted
203
212
  return notSpa ? undefined : this; // returns the InteractionHandle which allows these methods to be chained
204
213
  };
205
214
  }
206
- apiInterface.noticeError = function (err, customAttributes) {
215
+ agent.noticeError = function (err, customAttributes) {
207
216
  if (typeof err === 'string') err = new Error(err);
208
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/noticeError/called'], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
209
- (0, _handle.handle)('err', [err, (0, _now.now)(), false, customAttributes, !!replayRunning[agentIdentifier]], undefined, _features.FEATURE_NAMES.jserrors, instanceEE);
217
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/noticeError/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
218
+ (0, _handle.handle)('err', [err, (0, _now.now)(), false, customAttributes, !!replayRunning[agent.agentIdentifier]], undefined, _features.FEATURE_NAMES.jserrors, agent.ee);
210
219
  };
211
220
 
212
221
  // theres no window.load event on non-browser scopes, lazy load immediately
213
- if (!_runtime2.isBrowserScope) lazyLoad();
222
+ if (!_runtime.isBrowserScope) lazyLoad();
214
223
  // try to stay out of the way of the window.load event, lazy load once that has finished.
215
224
  else (0, _load.onWindowLoad)(() => lazyLoad(), true);
216
225
  function lazyLoad() {
217
226
  Promise.resolve().then(() => _interopRequireWildcard(require(/* webpackChunkName: "async-api" */'./apiAsync'))).then(({
218
- setAPI
227
+ setAsyncAPI
219
228
  }) => {
220
- setAPI(agentIdentifier);
221
- (0, _drain.drain)(agentIdentifier, 'api');
229
+ setAsyncAPI(agent);
230
+ (0, _drain.drain)(agent.agentIdentifier, 'api');
222
231
  }).catch(err => {
223
232
  (0, _console.warn)(27, err);
224
- instanceEE.abort();
233
+ agent.ee.abort();
225
234
  });
226
235
  }
227
- return apiInterface;
236
+ return true;
228
237
  }
@@ -3,23 +3,20 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.setAPI = setAPI;
6
+ exports.setAsyncAPI = setAsyncAPI;
7
7
  var _features = require("../features/features");
8
- var _runtime = require("../../common/config/runtime");
9
- var _contextualEe = require("../../common/event-emitter/contextual-ee");
10
8
  var _handle = require("../../common/event-emitter/handle");
11
9
  var _registerHandler = require("../../common/event-emitter/register-handler");
12
10
  var _invoke = require("../../common/util/invoke");
13
11
  var _constants = require("../../features/metrics/constants");
14
- var _runtime2 = require("../../common/constants/runtime");
12
+ var _runtime = require("../../common/constants/runtime");
15
13
  /**
16
14
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
17
15
  * SPDX-License-Identifier: Apache-2.0
18
16
  */
19
17
 
20
- function setAPI(agentIdentifier) {
21
- var instanceEE = _contextualEe.ee.get(agentIdentifier);
22
- var api = {
18
+ function setAsyncAPI(agent) {
19
+ const api = {
23
20
  finished: (0, _invoke.single)(finished),
24
21
  setErrorHandler,
25
22
  addToTrace,
@@ -27,40 +24,40 @@ function setAPI(agentIdentifier) {
27
24
  };
28
25
 
29
26
  // Hook all of the api functions up to the queues/stubs created in loader/api.js
30
- Object.entries(api).forEach(([fnName, fnCall]) => (0, _registerHandler.registerHandler)('api-' + fnName, fnCall, 'api', instanceEE));
27
+ Object.entries(api).forEach(([fnName, fnCall]) => (0, _registerHandler.registerHandler)('api-' + fnName, fnCall, 'api', agent.ee));
31
28
 
32
29
  // All API functions get passed the time they were called as their
33
30
  // first parameter. These functions can be called asynchronously.
34
31
 
35
32
  function finished(t, providedTime) {
36
- var time = providedTime ? providedTime - _runtime2.originTime : t;
33
+ const time = providedTime ? providedTime - _runtime.originTime : t;
37
34
  (0, _handle.handle)(_constants.CUSTOM_METRIC_CHANNEL, ['finished', {
38
35
  time
39
- }], undefined, _features.FEATURE_NAMES.metrics, instanceEE);
36
+ }], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
40
37
  addToTrace(t, {
41
38
  name: 'finished',
42
- start: time + _runtime2.originTime,
39
+ start: time + _runtime.originTime,
43
40
  origin: 'nr'
44
41
  });
45
- (0, _handle.handle)('api-addPageAction', [time, 'finished'], undefined, _features.FEATURE_NAMES.genericEvents, instanceEE);
42
+ (0, _handle.handle)('api-addPageAction', [time, 'finished'], undefined, _features.FEATURE_NAMES.genericEvents, agent.ee);
46
43
  }
47
- function addToTrace(t, evt) {
44
+ function addToTrace(_, evt) {
48
45
  if (!(evt && typeof evt === 'object' && evt.name && evt.start)) return;
49
- var report = {
46
+ const report = {
50
47
  n: evt.name,
51
- s: evt.start - _runtime2.originTime,
52
- e: (evt.end || evt.start) - _runtime2.originTime,
48
+ s: evt.start - _runtime.originTime,
49
+ e: (evt.end || evt.start) - _runtime.originTime,
53
50
  o: evt.origin || '',
54
51
  t: 'api'
55
52
  };
56
- (0, _handle.handle)('bstApi', [report], undefined, _features.FEATURE_NAMES.sessionTrace, instanceEE);
53
+ (0, _handle.handle)('bstApi', [report], undefined, _features.FEATURE_NAMES.sessionTrace, agent.ee);
57
54
  }
58
- function setErrorHandler(t, handler) {
59
- (0, _runtime.getRuntime)(agentIdentifier).onerror = handler;
55
+ function setErrorHandler(_, handler) {
56
+ agent.runtime.onerror = handler;
60
57
  }
61
- var releaseCount = 0;
62
- function addRelease(t, name, id) {
58
+ let releaseCount = 0;
59
+ function addRelease(_, name, id) {
63
60
  if (++releaseCount > 10) return;
64
- (0, _runtime.getRuntime)(agentIdentifier).releaseIds[name.slice(-200)] = ('' + id).slice(-200);
61
+ agent.runtime.releaseIds[name.slice(-200)] = ('' + id).slice(-200);
65
62
  }
66
63
  }
@@ -14,15 +14,17 @@ var _featureFlags = require("../../common/util/feature-flags");
14
14
  var _runtime2 = require("../../common/constants/runtime");
15
15
  var _publicPath = require("./public-path");
16
16
  var _contextualEe = require("../../common/event-emitter/contextual-ee");
17
+ var _globalEvent = require("../../common/dispatch/global-event");
17
18
  /**
18
19
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
19
20
  * SPDX-License-Identifier: Apache-2.0
20
21
  */
21
22
 
22
- let alreadySetOnce = false; // the configure() function can run multiple times in agent lifecycle
23
+ const alreadySetOnce = new Set(); // the configure() function can run multiple times in agent lifecycle for different agents
23
24
 
24
25
  /**
25
26
  * Sets or re-sets the agent's configuration values from global settings. This also attach those as properties to the agent instance.
27
+ * IMPORTANT: setNREUMInitializedAgent must be called on the agent prior to calling this function.
26
28
  */
27
29
  function configure(agent, opts = {}, loaderType, forceDrain) {
28
30
  // eslint-disable-next-line camelcase
@@ -50,9 +52,9 @@ function configure(agent, opts = {}, loaderType, forceDrain) {
50
52
  info.jsAttributes.isWorker = true;
51
53
  }
52
54
  (0, _info.setInfo)(agent.agentIdentifier, info);
53
- const updatedInit = (0, _init.getConfiguration)(agent.agentIdentifier);
55
+ const updatedInit = agent.init;
54
56
  const internalTrafficList = [info.beacon, info.errorBeacon];
55
- if (!alreadySetOnce) {
57
+ if (!alreadySetOnce.has(agent.agentIdentifier)) {
56
58
  if (updatedInit.proxy.assets) {
57
59
  (0, _publicPath.redefinePublicPath)(updatedInit.proxy.assets);
58
60
  internalTrafficList.push(updatedInit.proxy.assets);
@@ -67,8 +69,19 @@ function configure(agent, opts = {}, loaderType, forceDrain) {
67
69
  runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
68
70
  runtime.ptid = agent.agentIdentifier;
69
71
  (0, _runtime.setRuntime)(agent.agentIdentifier, runtime);
70
- agent.ee = _contextualEe.ee.get(agent.agentIdentifier);
71
- if (agent.api === undefined) agent.api = (0, _api.setAPI)(agent.agentIdentifier, forceDrain, agent.runSoftNavOverSpa);
72
- if (agent.exposed === undefined) agent.exposed = exposed;
73
- alreadySetOnce = true;
72
+ if (!alreadySetOnce.has(agent.agentIdentifier)) {
73
+ agent.ee = _contextualEe.ee.get(agent.agentIdentifier);
74
+ agent.exposed = exposed;
75
+ (0, _api.setAPI)(agent, forceDrain); // assign our API functions to the agent instance
76
+
77
+ (0, _globalEvent.dispatchGlobalEvent)({
78
+ agentIdentifier: agent.agentIdentifier,
79
+ drained: !!_featureFlags.activatedFeatures?.[agent.agentIdentifier],
80
+ type: 'lifecycle',
81
+ name: 'initialize',
82
+ feature: undefined,
83
+ data: agent.config
84
+ });
85
+ }
86
+ alreadySetOnce.add(agent.agentIdentifier);
74
87
  }
@@ -3,7 +3,7 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.featurePriority = exports.RUM = exports.JSERRORS = exports.FEATURE_TO_ENDPOINT = exports.FEATURE_NAMES = exports.EVENTS = void 0;
6
+ exports.featurePriority = exports.RUM = exports.LOGS = exports.JSERRORS = exports.FEATURE_TO_ENDPOINT = exports.FEATURE_NAMES = exports.EVENTS = exports.BLOBS = void 0;
7
7
  /**
8
8
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
9
9
  * SPDX-License-Identifier: Apache-2.0
@@ -12,8 +12,9 @@ exports.featurePriority = exports.RUM = exports.JSERRORS = exports.FEATURE_TO_EN
12
12
  // To reduce build size a bit:
13
13
  const EVENTS = exports.EVENTS = 'events';
14
14
  const JSERRORS = exports.JSERRORS = 'jserrors';
15
- const BLOBS = 'browser/blobs';
15
+ const BLOBS = exports.BLOBS = 'browser/blobs';
16
16
  const RUM = exports.RUM = 'rum';
17
+ const LOGS = exports.LOGS = 'browser/logs';
17
18
  const FEATURE_NAMES = exports.FEATURE_NAMES = {
18
19
  ajax: 'ajax',
19
20
  genericEvents: 'generic_events',
@@ -59,6 +60,6 @@ const FEATURE_TO_ENDPOINT = exports.FEATURE_TO_ENDPOINT = {
59
60
  [FEATURE_NAMES.jserrors]: JSERRORS,
60
61
  [FEATURE_NAMES.sessionTrace]: BLOBS,
61
62
  [FEATURE_NAMES.sessionReplay]: BLOBS,
62
- [FEATURE_NAMES.logging]: 'browser/logs',
63
+ [FEATURE_NAMES.logging]: LOGS,
63
64
  [FEATURE_NAMES.genericEvents]: 'ins'
64
65
  };
@@ -23,7 +23,7 @@ class MicroAgentBase {
23
23
  * @param {...any} args
24
24
  */
25
25
  #callMethod(methodName, ...args) {
26
- if (typeof this.api?.[methodName] !== 'function') (0, _console.warn)(35, methodName);else return this.api[methodName](...args);
26
+ if (this[methodName] === MicroAgentBase.prototype[methodName]) (0, _console.warn)(35, methodName);else return this[methodName](...args);
27
27
  }
28
28
 
29
29
  // MicroAgent class custom defines its own start
@@ -38,7 +38,6 @@ class MicroAgent extends _microAgentBase.MicroAgentBase {
38
38
  isolatedBacklog: true
39
39
  }
40
40
  }, options.loaderType || 'micro-agent');
41
- Object.assign(this, this.api); // the APIs should be available at the class level for micro-agent
42
41
 
43
42
  /**
44
43
  * Starts a set of agent features if not running in "autoStart" mode
@@ -91,5 +90,8 @@ class MicroAgent extends _microAgentBase.MicroAgentBase {
91
90
  runtime: this.runtime
92
91
  };
93
92
  }
93
+ get api() {
94
+ return this;
95
+ }
94
96
  }
95
97
  exports.MicroAgent = MicroAgent;
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.284.1";
14
+ export const VERSION = "1.286.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.284.1";
14
+ export const VERSION = "1.286.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -40,7 +40,7 @@ export const generateSelectorPath = (elem, targetFields = []) => {
40
40
  localName
41
41
  } = elem;
42
42
  targetFields.forEach(field => {
43
- nearestFields[nearestAttrName(field)] ||= elem[field];
43
+ nearestFields[nearestAttrName(field)] ||= elem[field]?.baseVal || elem[field];
44
44
  });
45
45
  const selector = [localName, id ? "#".concat(id) : '', pathSelector ? ">".concat(pathSelector) : ''].join('');
46
46
  pathSelector = selector;
@@ -3,7 +3,7 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants';
6
- import { FEATURE_TO_ENDPOINT, JSERRORS, RUM, EVENTS, FEATURE_NAMES } from '../../loaders/features/features';
6
+ import { FEATURE_TO_ENDPOINT, JSERRORS, RUM, EVENTS, FEATURE_NAMES, BLOBS, LOGS } from '../../loaders/features/features';
7
7
  import { VERSION } from "../constants/env.npm";
8
8
  import { globalScope, isWorkerScope } from '../constants/runtime';
9
9
  import { handle } from '../event-emitter/handle';
@@ -16,6 +16,8 @@ import { obj, param } from '../url/encode';
16
16
  import { warn } from '../util/console';
17
17
  import { stringify } from '../util/stringify';
18
18
  import { getSubmitMethod, xhr as xhrMethod, xhrFetch as fetchMethod } from '../util/submit-data';
19
+ import { activatedFeatures } from '../util/feature-flags';
20
+ import { dispatchGlobalEvent } from '../dispatch/global-event';
19
21
  const RETRY_FAILED = 'Harvester/Retry/Failed/';
20
22
  const RETRY_SUCCEEDED = 'Harvester/Retry/Succeeded/';
21
23
  export class Harvester {
@@ -81,7 +83,8 @@ export class Harvester {
81
83
  localOpts,
82
84
  submitMethod,
83
85
  cbFinished,
84
- raw: aggregateInst.harvestOpts.raw
86
+ raw: aggregateInst.harvestOpts.raw,
87
+ featureName: aggregateInst.featureName
85
88
  });
86
89
  ranSend = true;
87
90
  });
@@ -123,7 +126,8 @@ function send(agentRef, {
123
126
  localOpts = {},
124
127
  submitMethod,
125
128
  cbFinished,
126
- raw
129
+ raw,
130
+ featureName
127
131
  }) {
128
132
  if (!agentRef.info.errorBeacon) return false;
129
133
  let {
@@ -204,6 +208,22 @@ function send(agentRef, {
204
208
  });
205
209
  }
206
210
  }
211
+ dispatchGlobalEvent({
212
+ agentIdentifier: agentRef.agentIdentifier,
213
+ drained: !!activatedFeatures?.[agentRef.agentIdentifier],
214
+ type: 'data',
215
+ name: 'harvest',
216
+ feature: featureName,
217
+ data: {
218
+ endpoint,
219
+ headers,
220
+ targetApp,
221
+ payload,
222
+ submitMethod: getSubmitMethodName(),
223
+ raw,
224
+ synchronousXhr: !!(localOpts.isFinalHarvest && isWorkerScope)
225
+ }
226
+ });
207
227
  return true;
208
228
  function shouldRetry(status) {
209
229
  switch (status) {
@@ -214,6 +234,11 @@ function send(agentRef, {
214
234
  }
215
235
  return status >= 502 && status <= 504 || status >= 512 && status <= 530;
216
236
  }
237
+ function getSubmitMethodName() {
238
+ if (submitMethod === xhrMethod) return 'xhr';
239
+ if (submitMethod === fetchMethod) return 'fetch';
240
+ return 'beacon';
241
+ }
217
242
  }
218
243
 
219
244
  /**
@@ -245,12 +270,14 @@ function cleanPayload(payload = {}) {
245
270
  function baseQueryString(agentRef, qs, endpoint, applicationID) {
246
271
  const ref = agentRef.runtime.obfuscator.obfuscateString(cleanURL('' + globalScope.location));
247
272
  const hr = agentRef.runtime.session?.state.sessionReplayMode === 1 && endpoint !== JSERRORS;
273
+ const ht = agentRef.runtime.session?.state.sessionTraceMode === 1 && ![LOGS, BLOBS].includes(endpoint);
248
274
  const qps = ['a=' + applicationID, param('sa', agentRef.info.sa ? '' + agentRef.info.sa : ''), param('v', VERSION), transactionNameParam(), param('ct', agentRef.runtime.customTransaction), '&rst=' + now(), '&ck=0',
249
275
  // ck param DEPRECATED - still expected by backend
250
276
  '&s=' + (agentRef.runtime.session?.state.value || '0'),
251
277
  // the 0 id encaps all untrackable and default traffic
252
278
  param('ref', ref), param('ptid', agentRef.runtime.ptid ? '' + agentRef.runtime.ptid : '')];
253
279
  if (hr) qps.push(param('hr', '1', qs));
280
+ if (ht) qps.push(param('ht', '1', qs));
254
281
  return qps.join('');
255
282
 
256
283
  // Constructs the transaction name param for the beacon URL.
@@ -25,8 +25,14 @@ export function activateFeatures(flags, agentIdentifier) {
25
25
  activatedFeatures[agentIdentifier] = flags;
26
26
  sentIds.add(agentIdentifier);
27
27
 
28
- // let any window level subscribers know that the agent is running
28
+ // let any window level subscribers know that the agent is running, per install docs
29
29
  dispatchGlobalEvent({
30
- loaded: true
30
+ agentIdentifier,
31
+ loaded: true,
32
+ drained: true,
33
+ type: 'lifecycle',
34
+ name: 'load',
35
+ feature: undefined,
36
+ data: flags
31
37
  });
32
38
  }
@@ -26,7 +26,7 @@ export class Aggregate extends AggregateBase {
26
26
  });
27
27
  this.ee.on(SESSION_EVENTS.UPDATE, (type, data) => {
28
28
  if (this.blocked || type !== SESSION_EVENT_TYPES.CROSS_TAB) return;
29
- if (this.mode !== LOGGING_MODE.OFF && data.loggingMode === LOGGING_MODE.OFF) this.abort(ABORT_REASONS.CROSS_TAB);else this.mode = data.loggingMode;
29
+ if (this.loggingMode !== LOGGING_MODE.OFF && data.loggingMode === LOGGING_MODE.OFF) this.abort(ABORT_REASONS.CROSS_TAB);else this.loggingMode = data.loggingMode;
30
30
  });
31
31
  this.harvestOpts.raw = true;
32
32
  this.waitForFlags(['log']).then(([loggingMode]) => {
@@ -11,9 +11,11 @@ import { stylesheetEvaluator } from './stylesheet-evaluator';
11
11
  import { handle } from '../../../common/event-emitter/handle';
12
12
  import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants';
13
13
  import { FEATURE_NAMES } from '../../../loaders/features/features';
14
- import { buildNRMetaNode } from './utils';
14
+ import { buildNRMetaNode, customMasker } from './utils';
15
15
  import { IDEAL_PAYLOAD_SIZE } from '../../../common/constants/agent-constants';
16
16
  import { AggregateBase } from '../../utils/aggregate-base';
17
+ import { warn } from '../../../common/util/console';
18
+ import { single } from '../../../common/util/invoke';
17
19
  export class Recorder {
18
20
  /** Each page mutation or event will be stored (raw) in this array. This array will be cleared on each harvest */
19
21
  #events;
@@ -23,6 +25,8 @@ export class Recorder {
23
25
  #preloaded;
24
26
  /** flag that if true, blocks events from being "stored". Only set to true when a full snapshot has incomplete nodes (only stylesheets ATM) */
25
27
  #fixing = false;
28
+ #warnCSSOnce = single(() => warn(47)); // notifies user of potential replayer issue if fix_stylesheets is off
29
+
26
30
  constructor(parent) {
27
31
  this.#events = new RecorderEvents();
28
32
  this.#backloggedEvents = new RecorderEvents();
@@ -83,14 +87,7 @@ export class Recorder {
83
87
  inline_images,
84
88
  collect_fonts
85
89
  } = this.parent.agentRef.init.session_replay;
86
- const customMasker = (text, element) => {
87
- try {
88
- if (typeof element?.type === 'string' && element.type.toLowerCase() !== 'password' && (element?.dataset?.nrUnmask !== undefined || element?.classList?.contains('nr-unmask'))) return text;
89
- } catch (err) {
90
- // likely an element was passed to this handler that was invalid and was missing attributes or methods
91
- }
92
- return '*'.repeat(text?.length || 0);
93
- };
90
+
94
91
  // set up rrweb configurations for maximum privacy --
95
92
  // https://newrelic.atlassian.net/wiki/spaces/O11Y/pages/2792293280/2023+02+28+Browser+-+Session+Replay#Configuration-options
96
93
  const stop = recorder({
@@ -131,6 +128,7 @@ export class Recorder {
131
128
  if (!this.shouldFix) {
132
129
  if (incompletes > 0) {
133
130
  this.currentBufferTarget.inlinedAllStylesheets = false;
131
+ this.#warnCSSOnce();
134
132
  handle(SUPPORTABILITY_METRIC_CHANNEL, [missingInlineSMTag + 'Skipped', incompletes], undefined, FEATURE_NAMES.metrics, this.parent.ee);
135
133
  }
136
134
  return this.store(event, isCheckout);