@newrelic/browser-agent 1.261.2 → 1.263.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 (103) hide show
  1. package/CHANGELOG.md +27 -0
  2. package/dist/cjs/common/config/state/configurable.js +4 -4
  3. package/dist/cjs/common/config/state/init.js +5 -3
  4. package/dist/cjs/common/constants/env.cdn.js +1 -1
  5. package/dist/cjs/common/constants/env.npm.js +1 -1
  6. package/dist/cjs/common/context/shared-context.js +2 -2
  7. package/dist/cjs/common/drain/drain.js +22 -16
  8. package/dist/cjs/common/harvest/harvest.js +1 -1
  9. package/dist/cjs/common/session/session-entity.js +2 -2
  10. package/dist/cjs/common/timing/time-keeper.js +13 -2
  11. package/dist/cjs/common/util/console.js +3 -4
  12. package/dist/cjs/common/util/obfuscate.js +3 -3
  13. package/dist/cjs/common/wrap/wrap-logger.js +2 -0
  14. package/dist/cjs/common/wrap/wrap-xhr.js +1 -1
  15. package/dist/cjs/features/logging/aggregate/index.js +27 -2
  16. package/dist/cjs/features/logging/constants.js +2 -5
  17. package/dist/cjs/features/logging/shared/utils.js +2 -18
  18. package/dist/cjs/features/metrics/aggregate/index.js +16 -0
  19. package/dist/cjs/features/page_view_event/aggregate/index.js +20 -4
  20. package/dist/cjs/features/session_replay/aggregate/index.js +1 -1
  21. package/dist/cjs/features/session_replay/shared/recorder.js +1 -1
  22. package/dist/cjs/features/session_trace/aggregate/index.js +1 -1
  23. package/dist/cjs/features/spa/aggregate/index.js +1 -1
  24. package/dist/cjs/features/utils/aggregate-base.js +4 -3
  25. package/dist/cjs/features/utils/instrument-base.js +2 -2
  26. package/dist/cjs/loaders/agent-base.js +1 -1
  27. package/dist/cjs/loaders/agent.js +3 -4
  28. package/dist/cjs/loaders/api/api.js +13 -16
  29. package/dist/cjs/loaders/micro-agent.js +5 -5
  30. package/dist/esm/common/config/state/configurable.js +4 -4
  31. package/dist/esm/common/config/state/init.js +5 -3
  32. package/dist/esm/common/constants/env.cdn.js +1 -1
  33. package/dist/esm/common/constants/env.npm.js +1 -1
  34. package/dist/esm/common/context/shared-context.js +2 -2
  35. package/dist/esm/common/drain/drain.js +22 -16
  36. package/dist/esm/common/harvest/harvest.js +1 -1
  37. package/dist/esm/common/session/session-entity.js +2 -2
  38. package/dist/esm/common/timing/time-keeper.js +12 -2
  39. package/dist/esm/common/util/console.js +3 -4
  40. package/dist/esm/common/util/obfuscate.js +3 -3
  41. package/dist/esm/common/wrap/wrap-logger.js +2 -0
  42. package/dist/esm/common/wrap/wrap-xhr.js +1 -1
  43. package/dist/esm/features/logging/aggregate/index.js +28 -3
  44. package/dist/esm/features/logging/constants.js +1 -4
  45. package/dist/esm/features/logging/shared/utils.js +2 -18
  46. package/dist/esm/features/metrics/aggregate/index.js +16 -0
  47. package/dist/esm/features/page_view_event/aggregate/index.js +21 -5
  48. package/dist/esm/features/session_replay/aggregate/index.js +1 -1
  49. package/dist/esm/features/session_replay/shared/recorder.js +1 -1
  50. package/dist/esm/features/session_trace/aggregate/index.js +1 -1
  51. package/dist/esm/features/spa/aggregate/index.js +1 -1
  52. package/dist/esm/features/utils/aggregate-base.js +4 -3
  53. package/dist/esm/features/utils/instrument-base.js +2 -2
  54. package/dist/esm/loaders/agent-base.js +1 -1
  55. package/dist/esm/loaders/agent.js +3 -4
  56. package/dist/esm/loaders/api/api.js +15 -18
  57. package/dist/esm/loaders/micro-agent.js +5 -5
  58. package/dist/types/common/config/state/init.d.ts.map +1 -1
  59. package/dist/types/common/drain/drain.d.ts.map +1 -1
  60. package/dist/types/common/timing/time-keeper.d.ts +2 -1
  61. package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
  62. package/dist/types/common/util/console.d.ts +1 -1
  63. package/dist/types/common/util/console.d.ts.map +1 -1
  64. package/dist/types/common/wrap/wrap-logger.d.ts.map +1 -1
  65. package/dist/types/features/logging/aggregate/index.d.ts +1 -1
  66. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  67. package/dist/types/features/logging/constants.d.ts +0 -3
  68. package/dist/types/features/logging/constants.d.ts.map +1 -1
  69. package/dist/types/features/logging/shared/utils.d.ts +1 -1
  70. package/dist/types/features/logging/shared/utils.d.ts.map +1 -1
  71. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  72. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  73. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  74. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  75. package/dist/types/loaders/agent.d.ts.map +1 -1
  76. package/dist/types/loaders/api/api.d.ts.map +1 -1
  77. package/package.json +1 -1
  78. package/src/common/config/state/configurable.js +4 -4
  79. package/src/common/config/state/init.js +4 -3
  80. package/src/common/context/shared-context.js +2 -2
  81. package/src/common/drain/drain.js +21 -16
  82. package/src/common/harvest/harvest.js +1 -1
  83. package/src/common/session/session-entity.js +2 -2
  84. package/src/common/timing/time-keeper.js +14 -2
  85. package/src/common/util/console.js +3 -4
  86. package/src/common/util/obfuscate.js +3 -3
  87. package/src/common/wrap/wrap-logger.js +2 -0
  88. package/src/common/wrap/wrap-xhr.js +1 -1
  89. package/src/features/logging/aggregate/index.js +30 -3
  90. package/src/features/logging/constants.js +0 -4
  91. package/src/features/logging/shared/utils.js +2 -19
  92. package/src/features/metrics/aggregate/index.js +12 -0
  93. package/src/features/page_view_event/aggregate/index.js +22 -5
  94. package/src/features/session_replay/aggregate/index.js +1 -1
  95. package/src/features/session_replay/shared/recorder.js +1 -1
  96. package/src/features/session_trace/aggregate/index.js +1 -1
  97. package/src/features/spa/aggregate/index.js +1 -1
  98. package/src/features/utils/aggregate-base.js +4 -3
  99. package/src/features/utils/instrument-base.js +2 -2
  100. package/src/loaders/agent-base.js +1 -1
  101. package/src/loaders/agent.js +3 -4
  102. package/src/loaders/api/api.js +15 -18
  103. package/src/loaders/micro-agent.js +5 -5
@@ -1,7 +1,7 @@
1
1
  import { globalScope, isBrowserScope, originTime } from '../../../common/constants/runtime';
2
2
  import { addPT, addPN } from '../../../common/timing/nav-timing';
3
3
  import { stringify } from '../../../common/util/stringify';
4
- import { getInfo, getRuntime } from '../../../common/config/config';
4
+ import { getInfo, getRuntime, isConfigured } from '../../../common/config/config';
5
5
  import { Harvest } from '../../../common/harvest/harvest';
6
6
  import * as CONSTANTS from '../constants';
7
7
  import { getActivatedFeaturesFlags } from './initialized-features';
@@ -25,6 +25,10 @@ export class Aggregate extends AggregateBase {
25
25
  this.firstByteToWindowLoad = 0; // our "frontend" duration
26
26
  this.firstByteToDomContent = 0; // our "dom processing" duration
27
27
  this.timeKeeper = new TimeKeeper(this.agentIdentifier);
28
+ if (!isConfigured(agentIdentifier)) {
29
+ this.ee.abort();
30
+ return warn(43);
31
+ }
28
32
  if (isBrowserScope) {
29
33
  timeToFirstByte.subscribe(_ref => {
30
34
  let {
@@ -47,7 +51,6 @@ export class Aggregate extends AggregateBase {
47
51
  const info = getInfo(this.agentIdentifier);
48
52
  const agentRuntime = getRuntime(this.agentIdentifier);
49
53
  const harvester = new Harvest(this);
50
- if (!info.beacon) return;
51
54
  if (info.queueTime) this.aggregator.store('measures', 'qt', {
52
55
  value: info.queueTime
53
56
  });
@@ -140,11 +143,24 @@ export class Aggregate extends AggregateBase {
140
143
  this.timeKeeper.processRumRequest(xhr, rumStartTime, rumEndTime);
141
144
  if (!this.timeKeeper.ready) throw new Error('TimeKeeper not ready');
142
145
  agentRuntime.timeKeeper = this.timeKeeper;
146
+
147
+ // Check if the time diff is such that we need to capture a supportability metric
148
+ if (this.timeKeeper.localTimeDiff >= 12 * 60 * 60 * 1000) {
149
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed12Hrs'], undefined, FEATURE_NAMES.metrics, this.ee);
150
+ } else if (this.timeKeeper.localTimeDiff >= 6 * 60 * 60 * 1000) {
151
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed6Hrs'], undefined, FEATURE_NAMES.metrics, this.ee);
152
+ } else if (this.timeKeeper.localTimeDiff >= 60 * 60 * 1000) {
153
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/DiffExceed1Hrs'], undefined, FEATURE_NAMES.metrics, this.ee);
154
+ }
143
155
  } catch (error) {
144
- handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, FEATURE_NAMES.metrics, this.ee);
156
+ if (error?.message?.indexOf('invalid format') > 0) {
157
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/InvalidFormat'], undefined, FEATURE_NAMES.metrics, this.ee);
158
+ } else {
159
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['PVE/NRTime/Calculation/Failed'], undefined, FEATURE_NAMES.metrics, this.ee);
160
+ }
145
161
  drain(this.agentIdentifier, FEATURE_NAMES.metrics, true);
146
162
  this.ee.abort();
147
- warn('Could not calculate New Relic server time. Agent shutting down.', error);
163
+ warn(17, error);
148
164
  return;
149
165
  }
150
166
  try {
@@ -157,7 +173,7 @@ export class Aggregate extends AggregateBase {
157
173
  this.drain();
158
174
  } catch (err) {
159
175
  this.ee.abort();
160
- warn('RUM call failed. Agent shutting down.', err);
176
+ warn(18, err);
161
177
  }
162
178
  }
163
179
  });
@@ -416,7 +416,7 @@ export class Aggregate extends AggregateBase {
416
416
  abort() {
417
417
  let reason = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {};
418
418
  let data = arguments.length > 1 ? arguments[1] : undefined;
419
- warn("SR aborted -- ".concat(reason.message));
419
+ warn(33, reason.message);
420
420
  handle(SUPPORTABILITY_METRIC_CHANNEL, ["SessionReplay/Abort/".concat(reason.sm), data], undefined, FEATURE_NAMES.metrics, this.ee);
421
421
  this.blocked = true;
422
422
  this.mode = MODE.OFF;
@@ -33,7 +33,7 @@ export class Recorder {
33
33
  /** Config to inform to inline stylesheet contents (true default) */
34
34
  this.shouldInlineStylesheets = getConfigurationValue(this.parent.agentIdentifier, 'session_replay.inline_stylesheet');
35
35
  /** A flag that can be set to false by failing conversions to stop the fetching process */
36
- this.shouldFix = this.shouldInlineStylesheets;
36
+ this.shouldFix = this.shouldInlineStylesheets && getConfigurationValue(this.parent.agentIdentifier, 'session_replay.fix_stylesheets');
37
37
  /** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
38
38
  this.stopRecording = () => {/* no-op until set by rrweb initializer */};
39
39
  }
@@ -236,6 +236,6 @@ export class Aggregate extends AggregateBase {
236
236
  this.agentRuntime.session.write({
237
237
  sessionTraceMode: this.mode
238
238
  });
239
- this.scheduler.stopTimer();
239
+ this.scheduler?.stopTimer();
240
240
  }
241
241
  }
@@ -693,7 +693,7 @@ export class Aggregate extends AggregateBase {
693
693
  if (interaction.root?.attrs?.trigger === 'initialPageLoad') smCategory = 'InitialPageLoad';else if (interaction.routeChange) smCategory = 'RouteChange';else smCategory = 'Custom';
694
694
  handle(SUPPORTABILITY_METRIC_CHANNEL, ["Spa/Interaction/".concat(smCategory, "/Duration/Ms"), Math.max((interaction.root?.end || 0) - (interaction.root?.start || 0), 0)], undefined, FEATURE_NAMES.metrics, baseEE);
695
695
  scheduler?.scheduleHarvest(0);
696
- if (!scheduler) warn('SPA scheduler is not initialized. Saved interaction is not sent!');
696
+ if (!scheduler) warn(19);
697
697
  }
698
698
  function isEnabled() {
699
699
  var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled');
@@ -49,8 +49,9 @@ export class AggregateBase extends FeatureBase {
49
49
  checkConfiguration() {
50
50
  // NOTE: This check has to happen at aggregator load time
51
51
  if (!isConfigured(this.agentIdentifier)) {
52
+ const cdn = gosCDN();
52
53
  let jsAttributes = {
53
- ...gosCDN().info?.jsAttributes
54
+ ...cdn.info?.jsAttributes
54
55
  };
55
56
  try {
56
57
  jsAttributes = {
@@ -63,9 +64,9 @@ export class AggregateBase extends FeatureBase {
63
64
  configure({
64
65
  agentIdentifier: this.agentIdentifier
65
66
  }, {
66
- ...gosCDN(),
67
+ ...cdn,
67
68
  info: {
68
- ...gosCDN().info,
69
+ ...cdn.info,
69
70
  jsAttributes
70
71
  },
71
72
  runtime: getRuntime(this.agentIdentifier)
@@ -87,7 +87,7 @@ export class InstrumentBase extends FeatureBase {
87
87
  session = setupAgentSession(this.agentIdentifier);
88
88
  }
89
89
  } catch (e) {
90
- warn('A problem occurred when starting up session manager. This page will not start or extend any session.', e);
90
+ warn(20, e);
91
91
  this.ee.emit('internal-error', [e]);
92
92
  if (this.featureName === FEATURE_NAMES.sessionReplay) this.abortHandler?.(); // SR should stop recording if session DNE
93
93
  }
@@ -111,7 +111,7 @@ export class InstrumentBase extends FeatureBase {
111
111
  this.featAggregate = new Aggregate(this.agentIdentifier, this.aggregator, argsObjFromInstrument);
112
112
  loadedSuccessfully(true);
113
113
  } catch (e) {
114
- warn("Downloading and initializing ".concat(this.featureName, " failed..."), e);
114
+ warn(34, e);
115
115
  this.abortHandler?.(); // undo any important alterations made to the page
116
116
  // not supported yet but nice to do: "abort" this agent's EE for this feature specifically
117
117
  drain(this.agentIdentifier, this.featureName, true);
@@ -28,7 +28,7 @@ export class AgentBase {
28
28
  for (var _len = arguments.length, args = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
29
29
  args[_key - 1] = arguments[_key];
30
30
  }
31
- if (typeof this.api?.[methodName] !== 'function') warn("Call to agent api ".concat(methodName, " failed. The API is not currently initialized."));else return this.api[methodName](...args);
31
+ if (typeof this.api?.[methodName] !== 'function') warn(35, methodName);else return this.api[methodName](...args);
32
32
  }
33
33
 
34
34
  /**
@@ -13,7 +13,6 @@ import { Instrument as PageViewEvent } from '../features/page_view_event/instrum
13
13
  import { Aggregator } from '../common/aggregate/aggregator';
14
14
  import { gosNREUM, setNREUMInitializedAgent } from '../common/window/nreum';
15
15
  import { warn } from '../common/util/console';
16
- import { stringify } from '../common/util/stringify';
17
16
  import { globalScope } from '../common/constants/runtime';
18
17
 
19
18
  /**
@@ -30,7 +29,7 @@ export class Agent extends AgentBase {
30
29
  if (!globalScope) {
31
30
  // We could not determine the runtime environment. Short-circuite the agent here
32
31
  // to avoid possible exceptions later that may cause issues with customer's application.
33
- warn('Failed to initialize the agent. Could not determine the runtime environment.');
32
+ warn(21);
34
33
  return;
35
34
  }
36
35
  this.sharedAggregator = new Aggregator({
@@ -69,11 +68,11 @@ export class Agent extends AgentBase {
69
68
  if (!this.runSoftNavOverSpa && InstrumentCtor.featureName === FEATURE_NAMES.softNav) return;
70
69
  const dependencies = getFeatureDependencyNames(InstrumentCtor.featureName);
71
70
  const hasAllDeps = dependencies.every(featName => featName in this.features); // any other feature(s) this depends on should've been initialized on prior iterations by priority order
72
- if (!hasAllDeps) warn("".concat(InstrumentCtor.featureName, " is enabled but one or more dependent features has not been initialized (").concat(stringify(dependencies), "). This may cause unintended consequences or missing data..."));
71
+ if (!hasAllDeps) warn(36, InstrumentCtor.featureName);
73
72
  this.features[InstrumentCtor.featureName] = new InstrumentCtor(this.agentIdentifier, this.sharedAggregator);
74
73
  });
75
74
  } catch (err) {
76
- warn('Failed to initialize all enabled instrument classes (agent aborted) -', err);
75
+ warn(22, err);
77
76
  for (const featName in this.features) {
78
77
  // this.features hold only features that have been instantiated
79
78
  this.features[featName].abortHandler?.();
@@ -16,8 +16,8 @@ import { apiMethods, asyncApiMethods } from './api-methods';
16
16
  import { SR_EVENT_EMITTER_TYPES } from '../../features/session_replay/constants';
17
17
  import { now } from '../../common/timing/now';
18
18
  import { MODE } from '../../common/session/constants';
19
- import { LOGGING_FAILURE_MESSAGE, LOGGING_IGNORED, LOGGING_LEVEL_FAILURE_MESSAGE, LOG_LEVELS, MAX_PAYLOAD_SIZE } from '../../features/logging/constants';
20
- import { bufferLog, isValidLogLevel } from '../../features/logging/shared/utils';
19
+ import { LOG_LEVELS } from '../../features/logging/constants';
20
+ import { bufferLog } from '../../features/logging/shared/utils';
21
21
  import { wrapLogger } from '../../common/wrap/wrap-logger';
22
22
  export function setTopLevelCallers() {
23
23
  const nr = gosCDN();
@@ -35,7 +35,9 @@ export function setTopLevelCallers() {
35
35
  }
36
36
  let returnVals = [];
37
37
  Object.values(nr.initializedAgents).forEach(val => {
38
- if (val.exposed && val.api[fnName]) {
38
+ if (!val || !val.api) {
39
+ warn(38, fnName);
40
+ } else if (val.exposed && val.api[fnName]) {
39
41
  returnVals.push(val.api[fnName](...args));
40
42
  }
41
43
  });
@@ -60,23 +62,18 @@ export function setAPI(agentIdentifier, forceDrain) {
60
62
  customAttributes = {},
61
63
  level = LOG_LEVELS.INFO
62
64
  } = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
63
- if (!customAttributes || typeof customAttributes !== 'object') customAttributes = {};
64
- if (typeof message !== 'string' || !message) return warn(LOGGING_IGNORED + 'invalid message');
65
- if (!isValidLogLevel(level)) return warn(LOGGING_LEVEL_FAILURE_MESSAGE + level, LOG_LEVELS);
66
- if (message.length > MAX_PAYLOAD_SIZE) return warn(LOGGING_IGNORED + '> ' + MAX_PAYLOAD_SIZE + ' bytes: ', message.slice(0, 25) + '...');
67
- bufferLog(instanceEE, message, customAttributes, level.toUpperCase());
65
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['API/log/called'], undefined, FEATURE_NAMES.metrics, instanceEE);
66
+ bufferLog(instanceEE, message, customAttributes, level);
68
67
  };
69
68
  apiInterface.wrapLogger = function (parent, functionName) {
70
69
  let {
71
70
  customAttributes = {},
72
71
  level = LOG_LEVELS.INFO
73
72
  } = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {};
74
- if (!customAttributes || typeof customAttributes !== 'object') customAttributes = {};
75
- if (!(typeof parent === 'object' && !!parent && typeof functionName === 'string' && !!functionName && typeof parent[functionName] === 'function' && typeof customAttributes === 'object')) return warn(LOGGING_FAILURE_MESSAGE + 'invalid argument(s)');
76
- if (!isValidLogLevel(level)) return warn(LOGGING_FAILURE_MESSAGE + LOGGING_LEVEL_FAILURE_MESSAGE + level, LOG_LEVELS);
73
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['API/wrapLogger/called'], undefined, FEATURE_NAMES.metrics, instanceEE);
77
74
  wrapLogger(instanceEE, parent, functionName, {
78
75
  customAttributes,
79
- level: level.toUpperCase()
76
+ level
80
77
  });
81
78
  };
82
79
 
@@ -118,11 +115,11 @@ export function setAPI(agentIdentifier, forceDrain) {
118
115
  apiInterface.setCustomAttribute = function (name, value) {
119
116
  let persistAttribute = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false;
120
117
  if (typeof name !== 'string') {
121
- warn("Failed to execute setCustomAttribute.\nName must be a string type, but a type of <".concat(typeof name, "> was provided."));
118
+ warn(39, typeof name);
122
119
  return;
123
120
  }
124
121
  if (!(['string', 'number', 'boolean'].includes(typeof value) || value === null)) {
125
- warn("Failed to execute setCustomAttribute.\nNon-null value must be a string, number or boolean type, but a type of <".concat(typeof value, "> was provided."));
122
+ warn(40, typeof value);
126
123
  return;
127
124
  }
128
125
  return appendJsAttribute(name, value, 'setCustomAttribute', persistAttribute);
@@ -134,7 +131,7 @@ export function setAPI(agentIdentifier, forceDrain) {
134
131
  */
135
132
  apiInterface.setUserId = function (value) {
136
133
  if (!(typeof value === 'string' || value === null)) {
137
- warn("Failed to execute setUserId.\nNon-null value must be a string type, but a type of <".concat(typeof value, "> was provided."));
134
+ warn(41, typeof value);
138
135
  return;
139
136
  }
140
137
  return appendJsAttribute('enduser.id', value, 'setUserId', true);
@@ -147,7 +144,7 @@ export function setAPI(agentIdentifier, forceDrain) {
147
144
  */
148
145
  apiInterface.setApplicationVersion = function (value) {
149
146
  if (!(typeof value === 'string' || value === null)) {
150
- warn("Failed to execute setApplicationVersion. Expected <String | null>, but got <".concat(typeof value, ">."));
147
+ warn(42, typeof value);
151
148
  return;
152
149
  }
153
150
  return appendJsAttribute('application.version', value, 'setApplicationVersion', false);
@@ -157,7 +154,7 @@ export function setAPI(agentIdentifier, forceDrain) {
157
154
  handle(SUPPORTABILITY_METRIC_CHANNEL, ['API/start/called'], undefined, FEATURE_NAMES.metrics, instanceEE);
158
155
  instanceEE.emit('manual-start-all');
159
156
  } catch (err) {
160
- warn('An unexpected issue occurred', err);
157
+ warn(23, err);
161
158
  }
162
159
  };
163
160
  apiInterface[SR_EVENT_EMITTER_TYPES.RECORD] = function () {
@@ -226,7 +223,7 @@ export function setAPI(agentIdentifier, forceDrain) {
226
223
  setAPI(agentIdentifier);
227
224
  drain(agentIdentifier, 'api');
228
225
  }).catch(err => {
229
- warn('Downloading runtime APIs failed...', err);
226
+ warn(27, err);
230
227
  instanceEE.abort();
231
228
  });
232
229
  }
@@ -58,11 +58,11 @@ export class MicroAgent extends AgentBase {
58
58
  const featNames = nonAutoFeatures;
59
59
  if (features === undefined) features = featNames;else {
60
60
  features = Array.isArray(features) && features.length ? features : [features];
61
- if (features.some(f => !featNames.includes(f))) return warn("Invalid feature name supplied. Acceptable feature names are: ".concat(featNames));
61
+ if (features.some(f => !featNames.includes(f))) return warn(37, featNames);
62
62
  if (!features.includes(FEATURE_NAMES.pageViewEvent)) features.push(FEATURE_NAMES.pageViewEvent);
63
63
  }
64
64
  } catch (err) {
65
- warn('An unexpected issue occurred', err);
65
+ warn(23, err);
66
66
  }
67
67
  try {
68
68
  const enabledFeatures = getEnabledFeatures(this.agentIdentifier);
@@ -70,7 +70,7 @@ export class MicroAgent extends AgentBase {
70
70
  // a biproduct of doing this is that the "session manager" is automatically handled through importing this feature
71
71
  this.features.page_view_event = new PVE(this.agentIdentifier, this.sharedAggregator);
72
72
  } catch (err) {
73
- warn('Something prevented the agent from instrumenting.', err);
73
+ warn(24, err);
74
74
  }
75
75
  onWindowLoad(() => {
76
76
  // these features do not import an "instrument" file, meaning they are only hooked up to the API.
@@ -86,13 +86,13 @@ export class MicroAgent extends AgentBase {
86
86
  Aggregate
87
87
  } = _ref2;
88
88
  this.features[f] = new Aggregate(this.agentIdentifier, this.sharedAggregator);
89
- }).catch(err => warn('Something prevented the agent from being downloaded.', err));
89
+ }).catch(err => warn(25, err));
90
90
  }
91
91
  });
92
92
  });
93
93
  return true;
94
94
  } catch (err) {
95
- warn('Failed to initialize instrument classes.', err);
95
+ warn(26, err);
96
96
  return false;
97
97
  }
98
98
  }
@@ -1 +1 @@
1
- {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../src/common/config/state/init.js"],"names":[],"mappings":"AAgHA,+CAIC;AAED,0DAKC;AAED,+DAYC"}
1
+ {"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../../../src/common/config/state/init.js"],"names":[],"mappings":"AAiHA,+CAIC;AAED,0DAKC;AAED,+DAYC"}
@@ -1 +1 @@
1
- {"version":3,"file":"drain.d.ts","sourceRoot":"","sources":["../../../../src/common/drain/drain.js"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,+CAHW,MAAM,SACN,MAAM,QAQhB;AAED;;;;GAIG;AACH,iDAHW,GAAC,SACD,GAAC,QAMX;AAYD;;;;;;GAMG;AACH,wCAJW,MAAM,gBACN,MAAM,UACN,OAAO,QAajB"}
1
+ {"version":3,"file":"drain.d.ts","sourceRoot":"","sources":["../../../../src/common/drain/drain.js"],"names":[],"mappings":"AAYA;;;;;;;GAOG;AACH,+CAHW,MAAM,SACN,MAAM,QAQhB;AAED;;;;GAIG;AACH,iDAHW,GAAC,SACD,GAAC,QAOX;AAYD;;;;;;GAMG;AACH,wCAJW,MAAM,gBACN,MAAM,UACN,OAAO,QAajB"}
@@ -5,8 +5,9 @@
5
5
  */
6
6
  export class TimeKeeper {
7
7
  constructor(agentIdentifier: any);
8
- get ready(): number;
8
+ get ready(): boolean;
9
9
  get correctedOriginTime(): number;
10
+ get localTimeDiff(): number;
10
11
  /**
11
12
  * Process a rum request to calculate NR server time.
12
13
  * @param rumRequest {XMLHttpRequest} The xhr for the rum request
@@ -1 +1 @@
1
- {"version":3,"file":"time-keeper.d.ts","sourceRoot":"","sources":["../../../../src/common/timing/time-keeper.js"],"names":[],"mappings":"AAGA;;;;GAIG;AACH;IA2BE,kCAGC;IAED,oBAEC;IAED,kCAEC;IAED;;;;;OAKG;IACH,8BAJsB,cAAc,aACf,MAAM,WACR,MAAM,QAuBxB;IAED;;;;;OAKG;IACH,uCAHwB,MAAM,GACjB,MAAM,CAIlB;IAED;;;;OAIG;IACH,oCAHqB,MAAM,GACf,MAAM,CAIjB;IAED,+FAA+F;IAC/F,0BAOC;;CACF"}
1
+ {"version":3,"file":"time-keeper.d.ts","sourceRoot":"","sources":["../../../../src/common/timing/time-keeper.js"],"names":[],"mappings":"AAKA;;;;GAIG;AACH;IA2BE,kCAGC;IAED,qBAEC;IAED,kCAEC;IAED,4BAEC;IAED;;;;;OAKG;IACH,8BAJsB,cAAc,aACf,MAAM,WACR,MAAM,QA2BxB;IAED;;;;;OAKG;IACH,uCAHwB,MAAM,GACjB,MAAM,CAIlB;IAED;;;;OAIG;IACH,oCAHqB,MAAM,GACf,MAAM,CAIjB;IAED,+FAA+F;IAC/F,0BASC;;CACF"}
@@ -4,5 +4,5 @@
4
4
  * @param {*} [secondary] Secondary data to include, usually an error or object
5
5
  * @returns
6
6
  */
7
- export function warn(message: string, secondary?: any): void;
7
+ export function warn(code: any, secondary?: any): void;
8
8
  //# sourceMappingURL=console.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../../../src/common/util/console.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,8BAJW,MAAM,cACN,GAAC,QAOX"}
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../../../src/common/util/console.js"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,4CAHW,GAAC,QAMX"}
@@ -1 +1 @@
1
- {"version":3,"file":"wrap-logger.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-logger.js"],"names":[],"mappings":"AAaA;;;;;;GAMG;AAEH,qCANW,MAAM,UACN,MAAM,YACN,MAAM,iBACJ,MAAM,CAmBlB;AAED;;;;;;GAMG;AACH,mCAJW,MAAM,GAEJ,MAAM,CAIlB"}
1
+ {"version":3,"file":"wrap-logger.d.ts","sourceRoot":"","sources":["../../../../src/common/wrap/wrap-logger.js"],"names":[],"mappings":"AAcA;;;;;;GAMG;AAEH,qCANW,MAAM,UACN,MAAM,YACN,MAAM,iBACJ,MAAM,CAoBlB;AAED;;;;;;GAMG;AACH,mCAJW,MAAM,GAEJ,MAAM,CAIlB"}
@@ -9,7 +9,7 @@ export class Aggregate extends AggregateBase {
9
9
  estimatedBytes: number;
10
10
  harvestTimeSeconds: any;
11
11
  scheduler: HarvestScheduler;
12
- handleLog(timestamp: any, message: any, attributes: any, level: any): void;
12
+ handleLog(timestamp: any, message: any, attributes?: {}, level?: string): void;
13
13
  prepareHarvest(): {
14
14
  qs: {
15
15
  browser_monitoring_key: any;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/aggregate/index.js"],"names":[],"mappings":"AAWA;IACE,2BAAiC;IAGjC,mDA4BC;IAzBC,+BAA+B;IAC/B,oBAAsB;IACtB,4CAA4C;IAC5C,oBAAsB;IACtB,sHAAsH;IACtH,uBAAuB;IAKvB,wBAAmG;IAGjG,4BAKQ;IASZ,2EAoBC;IAED;;;;;;gBAYQ,0FAA0F;;;;;;;;;;;;YAY5F,0DAA0D;;;kBAI/D;IAED,qCAEC;;CACF;8BA7F6B,4BAA4B;iCAJzB,2CAA2C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/aggregate/index.js"],"names":[],"mappings":"AAYA;IACE,2BAAiC;IAGjC,mDA4BC;IAzBC,+BAA+B;IAC/B,oBAAsB;IACtB,4CAA4C;IAC5C,oBAAsB;IACtB,sHAAsH;IACtH,uBAAuB;IAKvB,wBAAmG;IAGjG,4BAKQ;IASZ,+EA8CC;IAED;;;;;;gBAYQ,0FAA0F;;;;;;;;;;;;YAY5F,0DAA0D;;;kBAI/D;IAED,qCAEC;;CACF;8BAxH6B,4BAA4B;iCAJzB,2CAA2C"}
@@ -8,7 +8,4 @@ export namespace LOG_LEVELS {
8
8
  export const LOGGING_EVENT_EMITTER_CHANNEL: "log";
9
9
  export const FEATURE_NAME: string;
10
10
  export const MAX_PAYLOAD_SIZE: 1000000;
11
- export const LOGGING_FAILURE_MESSAGE: "failed to wrap logger: ";
12
- export const LOGGING_LEVEL_FAILURE_MESSAGE: "invalid log level: ";
13
- export const LOGGING_IGNORED: "ignored log: ";
14
11
  //# sourceMappingURL=constants.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/logging/constants.js"],"names":[],"mappings":";;;;;;;AAUA,kDAAkD;AAElD,kCAAiD;AAEjD,uCAAuC;AAEvC,gEAAgE;AAChE,kEAAkE;AAClE,8CAA8C"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../src/features/logging/constants.js"],"names":[],"mappings":";;;;;;;AAUA,kDAAkD;AAElD,kCAAiD;AAEjD,uCAAuC"}
@@ -9,7 +9,7 @@ export function bufferLog(ee: ContextualEE, message: string, customAttributes?:
9
9
  }, level?: enum): void;
10
10
  /**
11
11
  * Checks if a supplied log level is acceptable for use in generating a log event
12
- * @param {string} level
12
+ * @param {string} level -- must be cast to uppercase before running this test
13
13
  * @returns {boolean}
14
14
  */
15
15
  export function isValidLogLevel(level: string): boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/shared/utils.js"],"names":[],"mappings":"AAQA;;;;;KAKK;AACL,8BALa,YAAY,WACZ,MAAM,qBACN;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAC,CAAA;CAAC,UAClB,IAAI,QAoBhB;AAED;;;;GAIG;AACH,uCAHW,MAAM,GACJ,OAAO,CAKnB"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../../../src/features/logging/shared/utils.js"],"names":[],"mappings":"AAMA;;;;;KAKK;AACL,8BALa,YAAY,WACZ,MAAM,qBACN;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAC,CAAA;CAAC,UAClB,IAAI,QAKhB;AAED;;;;GAIG;AACH,uCAHW,MAAM,GACJ,OAAO,CAKnB"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAaA;IACE,2BAAiC;IACjC,mDAsBC;IAED,wDAKC;IAED,iDAKC;IAED,qBA6CC;IAED,0BAOC;IAED,eAkCC;IA/BG,mCAAyB;CAgC9B;8BAtI6B,4BAA4B"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/metrics/aggregate/index.js"],"names":[],"mappings":"AAaA;IACE,2BAAiC;IACjC,mDAsBC;IAED,wDAKC;IAED,iDAKC;IAED,qBAyDC;IAED,0BAOC;IAED,eAkCC;IA/BG,mCAAyB;CAgC9B;8BAlJ6B,4BAA4B"}
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_event/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAA2C;IAC3C,mDAqBC;IAlBC,wBAAwB;IACxB,8BAA8B;IAC9B,8BAA8B;IAC9B,uBAAsD;IAiBxD,gBAsGC;CACF;8BA3I6B,4BAA4B;2BAS/B,oCAAoC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/features/page_view_event/aggregate/index.js"],"names":[],"mappings":"AAoBA;IACE,2BAA2C;IAC3C,mDA0BC;IAvBC,wBAAwB;IACxB,8BAA8B;IAC9B,8BAA8B;IAC9B,uBAAsD;IAsBxD,gBAkHC;CACF;8BA5J6B,4BAA4B;2BAS/B,oCAAoC"}
@@ -1 +1 @@
1
- {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAYA;IAUE,yBAkBC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAA6C;IAC7C,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;MAYC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAsCC;IAED;;;;;OAKG;IACH,aAHW,GAAC,cACD,GAAC,QA4BX;IAED,0HAA0H;IAC1H,yCAqDC;IA3CG,8BAAoB;IA6CxB,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BA3N8B,mBAAmB"}
1
+ {"version":3,"file":"recorder.d.ts","sourceRoot":"","sources":["../../../../../src/features/session_replay/shared/recorder.js"],"names":[],"mappings":"AAYA;IAUE,yBAkBC;IAdC,iEAAiE;IACjE,mBAAsB;IACtB,6DAA6D;IAC7D,oCAAuC;IACvC,kIAAkI;IAClI,kBAAqB;IACrB,sDAAsD;IACtD,YAAoB;IACpB,oEAAoE;IACpE,6BAAqH;IACrH,0FAA0F;IAC1F,eAAqI;IACrI,uIAAuI;IACvI,0BAAyE;IAG3E;;;;;;;;;MAYC;IAED,mFAAmF;IACnF,oBAKC;IAED,qDAAqD;IACrD,uBAsCC;IAED;;;;;OAKG;IACH,aAHW,GAAC,cACD,GAAC,QA4BX;IAED,0HAA0H;IAC1H,yCAqDC;IA3CG,8BAAoB;IA6CxB,0HAA0H;IAC1H,yBAOC;IAED,wBAEC;IAED,gCAAgC;IAChC,uCAGC;IAED;;;SAGK;IACL,oCAGC;;CACF;+BA3N8B,mBAAmB"}
@@ -1 +1 @@
1
- {"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAOA;IACE,4BAGC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAsBlB;IAED,cAGC;IADC,6BAAmB;IAGrB;;;OAGG;IACH,2BAqBC;CACF;4BAtE2B,gBAAgB"}
1
+ {"version":3,"file":"aggregate-base.d.ts","sourceRoot":"","sources":["../../../../src/features/utils/aggregate-base.js"],"names":[],"mappings":"AAOA;IACE,4BAGC;IAED;;;;OAIG;IACH,yBAHW,MAAM,EAAE,gBAsBlB;IAED,cAGC;IADC,6BAAmB;IAGrB;;;OAGG;IACH,2BAsBC;CACF;4BAvE2B,gBAAgB"}
@@ -1 +1 @@
1
- {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAkBA;;;GAGG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,wCA2BhB;IAdC,yCAAiF;IACjF,yBAAkB;IAGlB,sCAAsD;IAMtD,uCAA6G;IAM/G;;;;;MAOC;IAED,yBAiCC;CACF;0BA5FyB,cAAc;2BAQb,gCAAgC"}
1
+ {"version":3,"file":"agent.d.ts","sourceRoot":"","sources":["../../../src/loaders/agent.js"],"names":[],"mappings":"AAiBA;;;GAGG;AACH;IACE;;;OAGG;IACH,qBAHW,MAAM,wCA2BhB;IAdC,yCAAiF;IACjF,yBAAkB;IAGlB,sCAAsD;IAMtD,uCAA6G;IAM/G;;;;;MAOC;IAED,yBAiCC;CACF;0BA3FyB,cAAc;2BAQb,gCAAgC"}
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAsBA,2CAeC;AAID;;;;;;;;;;;;IAsEE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EAiGvB"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../../src/loaders/api/api.js"],"names":[],"mappings":"AAsBA,2CAiBC;AAID;;;;;;;;;;;;IAiEE;;;;OAIG;qBAFQ,MAAM;IAWjB;;;;OAIG;iCAFQ,MAAM,GAAC,IAAI;;;;;EAiGvB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@newrelic/browser-agent",
3
- "version": "1.261.2",
3
+ "version": "1.263.0",
4
4
  "private": false,
5
5
  "author": "New Relic Browser Agent Team <browser-agent@newrelic.com>",
6
6
  "description": "New Relic Browser Agent",
@@ -2,8 +2,8 @@ import { warn } from '../../util/console'
2
2
 
3
3
  export function getModeledObject (obj, model) {
4
4
  try {
5
- if (!obj || typeof obj !== 'object') return warn('Setting a Configurable requires an object as input')
6
- if (!model || typeof model !== 'object') return warn('Setting a Configurable requires a model to set its initial properties')
5
+ if (!obj || typeof obj !== 'object') return warn(3)
6
+ if (!model || typeof model !== 'object') return warn(4)
7
7
  // allow getters and setters to pass from model to target
8
8
  const output = Object.create(
9
9
  Object.getPrototypeOf(model),
@@ -19,11 +19,11 @@ export function getModeledObject (obj, model) {
19
19
  else if (typeof obj[key] === 'object' && typeof model[key] === 'object') output[key] = getModeledObject(obj[key], model[key])
20
20
  else output[key] = obj[key]
21
21
  } catch (e) {
22
- warn('An error occurred while setting a property of a Configurable', e)
22
+ warn(1, e)
23
23
  }
24
24
  }
25
25
  return output
26
26
  } catch (err) {
27
- warn('An error occured while setting a Configurable', err)
27
+ warn(2, err)
28
28
  }
29
29
  }
@@ -69,6 +69,7 @@ const model = () => {
69
69
  collect_fonts: false, // serialize fonts for collection without public asset url, this is currently broken in RRWeb -- https://github.com/rrweb-io/rrweb/issues/1304. When fixed, revisit with test cases
70
70
  inline_images: false, // serialize images for collection without public asset url -- right now this is only useful for testing as it easily generates payloads too large to be harvested
71
71
  inline_stylesheet: true, // serialize css for collection without public asset url
72
+ fix_stylesheets: true, // fetch missing stylesheet resources for inlining, only works if 'inline_stylesheet' is also true
72
73
  // recording config settings
73
74
  mask_all_inputs: true,
74
75
  // this has a getter/setter to facilitate validation of the selectors
@@ -76,7 +77,7 @@ const model = () => {
76
77
  set mask_text_selector (val) {
77
78
  if (isValidSelector(val)) hiddenState.mask_selector = `${val},${nrMask}`
78
79
  else if (val === '' || val === null) hiddenState.mask_selector = nrMask
79
- else warn('An invalid session_replay.mask_selector was provided. \'*\' will be used.', val)
80
+ else warn(5, val)
80
81
  },
81
82
  // these properties only have getters because they are enforcable constants and should error if someone tries to override them
82
83
  get block_class () { return 'nr-block' },
@@ -89,7 +90,7 @@ const model = () => {
89
90
  },
90
91
  set block_selector (val) {
91
92
  if (isValidSelector(val)) hiddenState.block_selector += `,${val}`
92
- else if (val !== '') warn('An invalid session_replay.block_selector was provided and will not be used', val)
93
+ else if (val !== '') warn(6, val)
93
94
  },
94
95
  // password: must always be present and true no matter what customer sets
95
96
  get mask_input_options () {
@@ -97,7 +98,7 @@ const model = () => {
97
98
  },
98
99
  set mask_input_options (val) {
99
100
  if (val && typeof val === 'object') hiddenState.mask_input_options = { ...val, password: true }
100
- else warn('An invalid session_replay.mask_input_option was provided and will not be used', val)
101
+ else warn(7, val)
101
102
  }
102
103
  },
103
104
  session_trace: { enabled: true, harvestTimeSeconds: 10, autoStart: true },
@@ -8,14 +8,14 @@ const model = {
8
8
  export class SharedContext {
9
9
  constructor (context) {
10
10
  try {
11
- if (typeof context !== 'object') return warn('shared context requires an object as input')
11
+ if (typeof context !== 'object') return warn(8)
12
12
  this.sharedContext = {}
13
13
  Object.assign(this.sharedContext, model)
14
14
  Object.entries(context).forEach(([key, value]) => {
15
15
  if (Object.keys(model).includes(key)) this.sharedContext[key] = value
16
16
  })
17
17
  } catch (err) {
18
- warn('An error occurred while setting SharedContext', err)
18
+ warn(9, err)
19
19
  }
20
20
  }
21
21
  }
@@ -32,8 +32,9 @@ export function registerDrain (agentIdentifier, group) {
32
32
  * @param {*} group - The named "bucket" to be removed from the registry
33
33
  */
34
34
  export function deregisterDrain (agentIdentifier, group) {
35
- curateRegistry(agentIdentifier)
35
+ if (!agentIdentifier || !registry[agentIdentifier]) return
36
36
  if (registry[agentIdentifier].get(group)) registry[agentIdentifier].delete(group)
37
+ drainGroup(agentIdentifier, group, false)
37
38
  if (registry[agentIdentifier].size) checkCanDrainAll(agentIdentifier)
38
39
  }
39
40
 
@@ -86,29 +87,33 @@ function checkCanDrainAll (agentIdentifier) {
86
87
  * the subscribed handlers for the group.
87
88
  * @param {*} group - The name of a particular feature's event "bucket".
88
89
  */
89
- function drainGroup (agentIdentifier, group) {
90
+ function drainGroup (agentIdentifier, group, activateGroup = true) {
90
91
  const baseEE = agentIdentifier ? ee.get(agentIdentifier) : ee
91
92
  const handlers = defaultRegister.handlers // other storage in registerHandler
92
- if (!baseEE.backlog || !handlers) return
93
+ if (baseEE.aborted || !baseEE.backlog || !handlers) return
93
94
 
94
- var bufferedEventsInGroup = baseEE.backlog[group]
95
- var groupHandlers = handlers[group] // each group in the registerHandler storage
96
- if (groupHandlers) {
97
- // We don't cache the length of the buffer while looping because events might still be added while processing.
98
- for (var i = 0; bufferedEventsInGroup && i < bufferedEventsInGroup.length; ++i) { // eslint-disable-line no-unmodified-loop-condition
99
- emitEvent(bufferedEventsInGroup[i], groupHandlers)
100
- }
95
+ // Only activated features being drained should run queued listeners on buffered events. Deactivated features only need to release memory.
96
+ if (activateGroup) {
97
+ const bufferedEventsInGroup = baseEE.backlog[group]
98
+ const groupHandlers = handlers[group] // each group in the registerHandler storage
99
+ if (groupHandlers) {
100
+ // We don't cache the length of the buffer while looping because events might still be added while processing.
101
+ for (let i = 0; bufferedEventsInGroup && i < bufferedEventsInGroup.length; ++i) { // eslint-disable-line no-unmodified-loop-condition
102
+ emitEvent(bufferedEventsInGroup[i], groupHandlers)
103
+ }
101
104
 
102
- mapOwn(groupHandlers, function (eventType, handlerRegistrationList) {
103
- mapOwn(handlerRegistrationList, function (i, registration) {
104
- // registration is an array of: [targetEE, eventHandler]
105
- registration[0].on(eventType, registration[1])
105
+ mapOwn(groupHandlers, function (eventType, handlerRegistrationList) {
106
+ mapOwn(handlerRegistrationList, function (i, registration) {
107
+ // registration is an array of: [targetEE, eventHandler]
108
+ registration[0].on(eventType, registration[1])
109
+ })
106
110
  })
107
- })
111
+ }
108
112
  }
113
+
109
114
  if (!baseEE.isolatedBacklog) delete handlers[group]
110
115
  baseEE.backlog[group] = null
111
- baseEE.emit('drain-' + group, [])
116
+ baseEE.emit('drain-' + group, []) // TODO: Code exists purely for a unit test and needs to be refined
112
117
  }
113
118
 
114
119
  /**
@@ -122,7 +122,7 @@ export class Harvest extends SharedContext {
122
122
  body = stringify(body)
123
123
  }
124
124
  /** Warn --once per endpoint-- if the agent tries to send large payloads */
125
- if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(`The Browser Agent is attempting to send a very large payload to /${endpoint}. This is usually tied to large amounts of custom attributes. Please check your configurations.`)
125
+ if (body.length > 750000 && (warnings[endpoint] = (warnings?.[endpoint] || 0) + 1) === 1) warn(28, endpoint)
126
126
  }
127
127
 
128
128
  if (!body || body.length === 0 || body === '{}' || body === '[]') {