@newrelic/browser-agent 1.310.1 → 1.311.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 (131) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/common/config/configurable.js +2 -2
  3. package/dist/cjs/common/config/runtime.js +8 -2
  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/constants/runtime.js +17 -4
  7. package/dist/cjs/common/deny-list/deny-list.js +2 -2
  8. package/dist/cjs/common/drain/drain.js +27 -37
  9. package/dist/cjs/common/harvest/harvester.js +1 -3
  10. package/dist/cjs/common/session/session-entity.js +7 -8
  11. package/dist/cjs/common/util/console.js +1 -2
  12. package/dist/cjs/common/util/feature-flags.js +5 -16
  13. package/dist/cjs/common/util/script-tracker.js +22 -4
  14. package/dist/cjs/common/util/stringify.js +22 -7
  15. package/dist/cjs/common/vitals/largest-contentful-paint.js +0 -1
  16. package/dist/cjs/common/vitals/load-time.js +3 -2
  17. package/dist/cjs/common/vitals/time-to-first-byte.js +2 -2
  18. package/dist/cjs/features/jserrors/aggregate/index.js +0 -4
  19. package/dist/cjs/features/page_view_event/aggregate/index.js +3 -3
  20. package/dist/cjs/features/page_view_event/aggregate/initialized-features.js +3 -5
  21. package/dist/cjs/features/page_view_event/instrument/index.js +3 -5
  22. package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -0
  23. package/dist/cjs/features/session_trace/aggregate/index.js +4 -3
  24. package/dist/cjs/features/utils/agent-session.js +3 -4
  25. package/dist/cjs/features/utils/aggregate-base.js +4 -6
  26. package/dist/cjs/features/utils/feature-base.js +6 -7
  27. package/dist/cjs/features/utils/instrument-base.js +7 -8
  28. package/dist/cjs/loaders/api/register-api-types.js +1 -1
  29. package/dist/cjs/loaders/api/register.js +1 -1
  30. package/dist/cjs/loaders/api/sharedHandlers.js +2 -4
  31. package/dist/cjs/loaders/configure/configure.js +23 -21
  32. package/dist/esm/common/config/configurable.js +2 -2
  33. package/dist/esm/common/config/runtime.js +8 -2
  34. package/dist/esm/common/constants/env.cdn.js +1 -1
  35. package/dist/esm/common/constants/env.npm.js +1 -1
  36. package/dist/esm/common/constants/runtime.js +15 -2
  37. package/dist/esm/common/deny-list/deny-list.js +2 -2
  38. package/dist/esm/common/drain/drain.js +27 -36
  39. package/dist/esm/common/harvest/harvester.js +1 -3
  40. package/dist/esm/common/session/session-entity.js +7 -8
  41. package/dist/esm/common/util/console.js +1 -2
  42. package/dist/esm/common/util/feature-flags.js +5 -14
  43. package/dist/esm/common/util/script-tracker.js +22 -5
  44. package/dist/esm/common/util/stringify.js +22 -7
  45. package/dist/esm/common/vitals/largest-contentful-paint.js +0 -1
  46. package/dist/esm/common/vitals/load-time.js +4 -3
  47. package/dist/esm/common/vitals/time-to-first-byte.js +3 -3
  48. package/dist/esm/features/jserrors/aggregate/index.js +0 -4
  49. package/dist/esm/features/page_view_event/aggregate/index.js +4 -4
  50. package/dist/esm/features/page_view_event/aggregate/initialized-features.js +3 -5
  51. package/dist/esm/features/page_view_event/instrument/index.js +3 -5
  52. package/dist/esm/features/page_view_timing/aggregate/index.js +3 -1
  53. package/dist/esm/features/session_trace/aggregate/index.js +5 -4
  54. package/dist/esm/features/utils/agent-session.js +3 -4
  55. package/dist/esm/features/utils/aggregate-base.js +4 -6
  56. package/dist/esm/features/utils/feature-base.js +6 -7
  57. package/dist/esm/features/utils/instrument-base.js +7 -8
  58. package/dist/esm/loaders/api/register-api-types.js +1 -1
  59. package/dist/esm/loaders/api/register.js +1 -1
  60. package/dist/esm/loaders/api/sharedHandlers.js +2 -4
  61. package/dist/esm/loaders/configure/configure.js +24 -21
  62. package/dist/tsconfig.tsbuildinfo +1 -1
  63. package/dist/types/common/config/configurable.d.ts.map +1 -1
  64. package/dist/types/common/config/runtime.d.ts.map +1 -1
  65. package/dist/types/common/constants/runtime.d.ts +1 -1
  66. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  67. package/dist/types/common/drain/drain.d.ts +6 -6
  68. package/dist/types/common/drain/drain.d.ts.map +1 -1
  69. package/dist/types/common/harvest/harvester.d.ts.map +1 -1
  70. package/dist/types/common/session/session-entity.d.ts +2 -2
  71. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  72. package/dist/types/common/util/console.d.ts.map +1 -1
  73. package/dist/types/common/util/feature-flags.d.ts +3 -5
  74. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  75. package/dist/types/common/util/script-tracker.d.ts +5 -0
  76. package/dist/types/common/util/script-tracker.d.ts.map +1 -1
  77. package/dist/types/common/util/stringify.d.ts.map +1 -1
  78. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  79. package/dist/types/features/page_view_event/aggregate/initialized-features.d.ts +2 -2
  80. package/dist/types/features/page_view_event/aggregate/initialized-features.d.ts.map +1 -1
  81. package/dist/types/features/page_view_event/instrument/index.d.ts +1 -1
  82. package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
  83. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  84. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  85. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  86. package/dist/types/features/utils/aggregate-base.d.ts +0 -1
  87. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  88. package/dist/types/features/utils/feature-base.d.ts +3 -3
  89. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  90. package/dist/types/features/utils/instrument-base.d.ts +2 -3
  91. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  92. package/dist/types/loaders/api/register-api-types.d.ts +1 -1
  93. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
  94. package/dist/types/loaders/api/sharedHandlers.d.ts.map +1 -1
  95. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  96. package/package.json +1 -1
  97. package/src/common/config/configurable.js +2 -1
  98. package/src/common/config/runtime.js +8 -2
  99. package/src/common/constants/runtime.js +16 -2
  100. package/src/common/deny-list/deny-list.js +2 -2
  101. package/src/common/drain/__mocks__/drain.js +2 -1
  102. package/src/common/drain/drain.js +27 -37
  103. package/src/common/harvest/harvester.js +1 -3
  104. package/src/common/session/session-entity.js +7 -8
  105. package/src/common/util/console.js +1 -2
  106. package/src/common/util/feature-flags.js +5 -17
  107. package/src/common/util/script-tracker.js +23 -5
  108. package/src/common/util/stringify.js +24 -7
  109. package/src/common/vitals/largest-contentful-paint.js +0 -1
  110. package/src/common/vitals/load-time.js +4 -3
  111. package/src/common/vitals/time-to-first-byte.js +3 -3
  112. package/src/features/jserrors/aggregate/index.js +0 -4
  113. package/src/features/page_view_event/aggregate/index.js +4 -4
  114. package/src/features/page_view_event/aggregate/initialized-features.js +3 -5
  115. package/src/features/page_view_event/instrument/index.js +3 -5
  116. package/src/features/page_view_timing/aggregate/index.js +4 -1
  117. package/src/features/session_trace/aggregate/index.js +5 -4
  118. package/src/features/utils/__mocks__/feature-base.js +3 -3
  119. package/src/features/utils/agent-session.js +3 -4
  120. package/src/features/utils/aggregate-base.js +4 -6
  121. package/src/features/utils/feature-base.js +6 -7
  122. package/src/features/utils/instrument-base.js +7 -9
  123. package/src/loaders/api/register-api-types.js +1 -1
  124. package/src/loaders/api/register.js +1 -1
  125. package/src/loaders/api/sharedHandlers.js +2 -4
  126. package/src/loaders/configure/configure.js +30 -26
  127. package/dist/cjs/features/utils/nr1-debugger.js +0 -30
  128. package/dist/esm/features/utils/nr1-debugger.js +0 -23
  129. package/dist/types/features/utils/nr1-debugger.d.ts +0 -2
  130. package/dist/types/features/utils/nr1-debugger.d.ts.map +0 -1
  131. package/src/features/utils/nr1-debugger.js +0 -26
@@ -11,7 +11,7 @@ var _constants2 = require("../../../common/session/constants");
11
11
  var _globalEvent = require("../../../common/dispatch/global-event");
12
12
  var _load = require("../../../common/window/load");
13
13
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /**
14
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
14
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
15
15
  * SPDX-License-Identifier: Apache-2.0
16
16
  */
17
17
  class Instrument extends _instrumentBase.InstrumentBase {
@@ -20,17 +20,16 @@ class Instrument extends _instrumentBase.InstrumentBase {
20
20
  super(agentRef, CONSTANTS.FEATURE_NAME);
21
21
 
22
22
  /** setup inspection events for window lifecycle */
23
- this.setupInspectionEvents(agentRef.agentIdentifier);
23
+ this.setupInspectionEvents();
24
24
 
25
25
  /** feature specific APIs */
26
26
  (0, _setPageViewName.setupSetPageViewNameAPI)(agentRef);
27
27
  this.importAggregator(agentRef, () => Promise.resolve().then(() => _interopRequireWildcard(require(/* webpackChunkName: "page_view_event-aggregate" */'../aggregate'))));
28
28
  }
29
- setupInspectionEvents(agentIdentifier) {
29
+ setupInspectionEvents() {
30
30
  const dispatch = (evt, name) => {
31
31
  if (!evt) return;
32
32
  (0, _globalEvent.dispatchGlobalEvent)({
33
- agentIdentifier,
34
33
  timeStamp: evt.timeStamp,
35
34
  loaded: evt.target.readyState === 'complete',
36
35
  type: 'window',
@@ -49,7 +48,6 @@ class Instrument extends _instrumentBase.InstrumentBase {
49
48
  });
50
49
  this.ee.on(_constants2.SESSION_EVENTS.UPDATE, (_, data) => {
51
50
  (0, _globalEvent.dispatchGlobalEvent)({
52
- agentIdentifier,
53
51
  type: 'lifecycle',
54
52
  name: 'session',
55
53
  data
@@ -21,6 +21,7 @@ var _runtime = require("../../../common/constants/runtime");
21
21
  var _eventOrigin = require("../../../common/util/event-origin");
22
22
  var _loadTime = require("../../../common/vitals/load-time");
23
23
  var _webdriverDetection = require("../../../common/util/webdriver-detection");
24
+ var _cleanUrl = require("../../../common/url/clean-url");
24
25
  /**
25
26
  * Copyright 2020-2026 New Relic, Inc. All rights reserved.
26
27
  * SPDX-License-Identifier: Apache-2.0
@@ -84,6 +85,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
84
85
  }
85
86
  addTiming(name, value, attrs) {
86
87
  attrs = attrs || {};
88
+ attrs.pageUrl = (0, _cleanUrl.cleanURL)((0, _runtime.getNavigationEntry)()?.name || _runtime.initialLocation);
87
89
  addConnectionAttributes(attrs); // network conditions may differ from the actual for VitalMetrics when they were captured
88
90
 
89
91
  // If cls was set to another value by `onCLS`, then it's supported and is attached onto any timing but is omitted until such time.
@@ -15,7 +15,7 @@ var _traverse = require("../../../common/util/traverse");
15
15
  var _cleanUrl = require("../../../common/url/clean-url");
16
16
  var _console = require("../../../common/util/console");
17
17
  /**
18
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
18
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
19
19
  * SPDX-License-Identifier: Apache-2.0
20
20
  */
21
21
 
@@ -64,8 +64,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
64
64
  // if another page's session entity has expired, or another page has transitioned to off and this one hasn't... we can just abort straight away here
65
65
  if (this.sessionId !== sessionState.value || eventType === 'cross-tab' && sessionState.sessionTraceMode === _constants2.MODE.OFF) this.abort(2);
66
66
  });
67
- if ((0, _runtime.supportsNavTimingL2)()) {
68
- this.traceStorage.storeTiming(_runtime.globalScope.performance?.getEntriesByType?.('navigation')[0]);
67
+ const navEntry = (0, _runtime.getNavigationEntry)();
68
+ if (navEntry) {
69
+ this.traceStorage.storeTiming(navEntry);
69
70
  } else {
70
71
  this.traceStorage.storeTiming(_runtime.globalScope.performance?.timing, true);
71
72
  }
@@ -5,7 +5,6 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.setupAgentSession = setupAgentSession;
7
7
  var _drain = require("../../common/drain/drain");
8
- var _contextualEe = require("../../common/event-emitter/contextual-ee");
9
8
  var _registerHandler = require("../../common/event-emitter/register-handler");
10
9
  var _sessionEntity = require("../../common/session/session-entity");
11
10
  var _localStorage = require("../../common/storage/local-storage.js");
@@ -27,7 +26,7 @@ function setupAgentSession(agentRef) {
27
26
 
28
27
  const sessionInit = agentRef.init.session;
29
28
  agentRef.runtime.session = new _sessionEntity.SessionEntity({
30
- agentIdentifier: agentRef.agentIdentifier,
29
+ agentRef,
31
30
  key: _constants.DEFAULT_KEY,
32
31
  storage: new _localStorage.LocalStorage(),
33
32
  expiresMs: sessionInit?.expiresMs,
@@ -49,7 +48,7 @@ function setupAgentSession(agentRef) {
49
48
 
50
49
  /** track changes to the jsAttributes field over time for aiding with harvest mechanics */
51
50
  agentRef.runtime.jsAttributesMetadata = (0, _attributeSize.trackObjectAttributeSize)(agentRef.info, 'jsAttributes');
52
- const sharedEE = _contextualEe.ee.get(agentRef.agentIdentifier);
51
+ const sharedEE = agentRef.ee;
53
52
 
54
53
  // any calls to newrelic.setCustomAttribute(<persisted>) will need to be added to:
55
54
  // local info.jsAttributes {}
@@ -74,6 +73,6 @@ function setupAgentSession(agentRef) {
74
73
  consent: accept === undefined ? true : accept
75
74
  });
76
75
  }, 'session', sharedEE);
77
- (0, _drain.drain)(agentRef.agentIdentifier, 'session');
76
+ (0, _drain.drain)(agentRef, 'session');
78
77
  return agentRef.runtime.session;
79
78
  }
@@ -9,7 +9,6 @@ var _info = require("../../common/config/info");
9
9
  var _configure = require("../../loaders/configure/configure");
10
10
  var _nreum = require("../../common/window/nreum");
11
11
  var _drain = require("../../common/drain/drain");
12
- var _featureFlags = require("../../common/util/feature-flags");
13
12
  var _obfuscate = require("../../common/util/obfuscate");
14
13
  var _features = require("../../loaders/features/features");
15
14
  var _harvester = require("../../common/harvest/harvester");
@@ -30,8 +29,7 @@ class AggregateBase extends _featureBase.FeatureBase {
30
29
  * @param {string} featureName The name of the feature creating the instance.
31
30
  */
32
31
  constructor(agentRef, featureName) {
33
- super(agentRef.agentIdentifier, featureName);
34
- this.agentRef = agentRef;
32
+ super(agentRef, featureName);
35
33
  this.checkConfiguration(agentRef);
36
34
  this.doOnceForAllAggregate(agentRef);
37
35
 
@@ -115,8 +113,8 @@ class AggregateBase extends _featureBase.FeatureBase {
115
113
  */
116
114
  waitForFlags(flagNames = []) {
117
115
  const flagsPromise = new Promise((resolve, reject) => {
118
- if (_featureFlags.activatedFeatures[this.agentIdentifier]) {
119
- resolve(buildOutput(_featureFlags.activatedFeatures[this.agentIdentifier]));
116
+ if (this.agentRef.runtime?.activatedFeatures) {
117
+ resolve(buildOutput(this.agentRef.runtime.activatedFeatures));
120
118
  } else {
121
119
  this.ee.on('rumresp', (resp = {}) => {
122
120
  resolve(buildOutput(resp));
@@ -140,7 +138,7 @@ class AggregateBase extends _featureBase.FeatureBase {
140
138
  * Stages the feature to be drained
141
139
  */
142
140
  drain() {
143
- (0, _drain.drain)(this.agentIdentifier, this.featureName);
141
+ (0, _drain.drain)(this.agentRef, this.featureName);
144
142
  }
145
143
  preHarvestChecks(opts) {
146
144
  return !this.blocked && !this.ee.aborted;
@@ -4,19 +4,18 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.FeatureBase = void 0;
7
- var _contextualEe = require("../../common/event-emitter/contextual-ee");
8
7
  var _drain = require("../../common/drain/drain");
9
8
  /**
10
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
9
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
11
10
  * SPDX-License-Identifier: Apache-2.0
12
11
  */
13
12
 
14
13
  class FeatureBase {
15
- constructor(agentIdentifier, featureName) {
16
- /** @type {string} */
17
- this.agentIdentifier = agentIdentifier;
14
+ constructor(agentRef, featureName) {
15
+ /** @type {Object} */
16
+ this.agentRef = agentRef;
18
17
  /** @type {import('../../common/event-emitter/contextual-ee').ee} */
19
- this.ee = _contextualEe.ee.get(agentIdentifier);
18
+ this.ee = agentRef?.ee;
20
19
  /** @type {string} */
21
20
  this.featureName = featureName;
22
21
  /**
@@ -27,7 +26,7 @@ class FeatureBase {
27
26
  this.blocked = false;
28
27
  }
29
28
  deregisterDrain() {
30
- (0, _drain.deregisterDrain)(this.agentIdentifier, this.featureName);
29
+ (0, _drain.deregisterDrain)(this.agentRef, this.featureName);
31
30
  }
32
31
  }
33
32
  exports.FeatureBase = FeatureBase;
@@ -16,7 +16,7 @@ var _invoke = require("../../common/util/invoke");
16
16
  var _agentConstants = require("../../common/constants/agent-constants");
17
17
  var _handle = require("../../common/event-emitter/handle");
18
18
  function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r = new WeakMap(), n = new WeakMap(); return (_interopRequireWildcard = function (e, t) { if (!t && e && e.__esModule) return e; var o, i, f = { __proto__: null, default: e }; if (null === e || "object" != typeof e && "function" != typeof e) return f; if (o = t ? n : r) { if (o.has(e)) return o.get(e); o.set(e, f); } for (const t in e) "default" !== t && {}.hasOwnProperty.call(e, t) && ((i = (o = Object.defineProperty) && Object.getOwnPropertyDescriptor(e, t)) && (i.get || i.set) ? o(f, t, i) : f[t] = e[t]); return f; })(e, t); } /**
19
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
19
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
20
20
  * SPDX-License-Identifier: Apache-2.0
21
21
  */ /**
22
22
  * @file Defines `InstrumentBase` to be used as the super of the Instrument classes implemented by each feature.
@@ -30,12 +30,11 @@ function _interopRequireWildcard(e, t) { if ("function" == typeof WeakMap) var r
30
30
  class InstrumentBase extends _featureBase.FeatureBase {
31
31
  /**
32
32
  * Instantiate InstrumentBase.
33
- * @param {string} agentIdentifier - The unique ID of the instantiated agent (relative to global scope).
33
+ * @param {Object} agentRef - The agent reference object.
34
34
  * @param {string} featureName - The name of the feature module (used to construct file path).
35
35
  */
36
36
  constructor(agentRef, featureName) {
37
- super(agentRef.agentIdentifier, featureName);
38
- this.agentRef = agentRef;
37
+ super(agentRef, featureName);
39
38
 
40
39
  /** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
41
40
  this.abortHandler = undefined;
@@ -65,13 +64,13 @@ class InstrumentBase extends _featureBase.FeatureBase {
65
64
  this.ee.on('manual-start-all', (0, _invoke.single)(() => {
66
65
  // register the feature to drain only once the API has been called, it will drain when importAggregator finishes for all the features
67
66
  // called by the api in that cycle
68
- (0, _drain.registerDrain)(agentRef.agentIdentifier, this.featureName);
67
+ (0, _drain.registerDrain)(agentRef, this.featureName);
69
68
  resolve();
70
69
  }));
71
70
  });
72
71
  } else {
73
72
  /** if the feature requires opt-in (!auto-start), it will get registered once the api has been called */
74
- (0, _drain.registerDrain)(agentRef.agentIdentifier, featureName);
73
+ (0, _drain.registerDrain)(agentRef, featureName);
75
74
  }
76
75
  }
77
76
 
@@ -111,7 +110,7 @@ class InstrumentBase extends _featureBase.FeatureBase {
111
110
  */
112
111
  try {
113
112
  if (!this.#shouldImportAgg(this.featureName, session, agentRef.init)) {
114
- (0, _drain.drain)(this.agentIdentifier, this.featureName);
113
+ (0, _drain.drain)(this.agentRef, this.featureName);
115
114
  this.loadedSuccessfully(false); // aggregate module isn't loaded at all
116
115
  return;
117
116
  }
@@ -125,7 +124,7 @@ class InstrumentBase extends _featureBase.FeatureBase {
125
124
  (0, _console.warn)(34, e);
126
125
  this.abortHandler?.(); // undo any important alterations made to the page
127
126
  // not supported yet but nice to do: "abort" this agent's EE for this feature specifically
128
- (0, _drain.drain)(this.agentIdentifier, this.featureName, true);
127
+ (0, _drain.drain)(this.agentRef, this.featureName, true);
129
128
  this.loadedSuccessfully(false);
130
129
  if (this.ee) this.ee.abort();
131
130
  }
@@ -24,7 +24,7 @@ exports.default = void 0;
24
24
  */
25
25
  /**
26
26
  * @typedef {Object} RegisterAPIConstructor
27
- * @property {string|number} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
27
+ * @property {string} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
28
28
  * @property {string} name - The readable name for the registered entity. This will be assigned to any synthesized entities.
29
29
  * @property {{[key: string]: any}} [tags] - The tags for the registered entity as key-value pairs. This will be assigned to any synthesized entities. Tags are converted to source.* attributes (e.g., {environment: 'production'} becomes source.environment: 'production').
30
30
  * @property {boolean} [isolated] - When true, each registration creates an isolated instance. When false, multiple registrations with the same id and isolated: false will share a single instance, including all custom attributes, ids, names, and metadata. Calling deregister on a shared instance will deregister it for all entities using the instance. Defaults to true.
@@ -94,7 +94,7 @@ function register(agentRef, target, parent) {
94
94
  invalidApiResponse = warning;
95
95
  };
96
96
  function hasValidValue(val) {
97
- return typeof val === 'string' && !!val.trim() && val.trim().length < 501 || typeof val === 'number';
97
+ return typeof val === 'string' && !!val.trim() && val.trim().length < 501;
98
98
  }
99
99
 
100
100
  /** primary cases that can block the register API from working at init time */
@@ -9,13 +9,12 @@ var _globalEvent = require("../../common/dispatch/global-event");
9
9
  var _handle = require("../../common/event-emitter/handle");
10
10
  var _now = require("../../common/timing/now");
11
11
  var _console = require("../../common/util/console");
12
- var _featureFlags = require("../../common/util/feature-flags");
13
12
  var _constants = require("../../features/metrics/constants");
14
13
  var _agentBase = require("../agent-base");
15
14
  var _features = require("../features/features");
16
15
  var _constants2 = require("./constants");
17
16
  /**
18
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
17
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
19
18
  * SPDX-License-Identifier: Apache-2.0
20
19
  */
21
20
 
@@ -35,8 +34,7 @@ function setupAPI(name, fn, agent, obj) {
35
34
  api[name] = function () {
36
35
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ['API/' + name + '/called'], undefined, _features.FEATURE_NAMES.metrics, agent.ee);
37
36
  (0, _globalEvent.dispatchGlobalEvent)({
38
- agentIdentifier: agent.agentIdentifier,
39
- drained: !!_featureFlags.activatedFeatures?.[agent.agentIdentifier],
37
+ drained: !!agent.runtime?.activatedFeatures,
40
38
  type: 'data',
41
39
  name: 'api',
42
40
  feature: _constants2.prefix + name,
@@ -9,7 +9,6 @@ var _nreum = require("../../common/window/nreum");
9
9
  var _info = require("../../common/config/info");
10
10
  var _init = require("../../common/config/init");
11
11
  var _runtime = require("../../common/config/runtime");
12
- var _featureFlags = require("../../common/util/feature-flags");
13
12
  var _runtime2 = require("../../common/constants/runtime");
14
13
  var _publicPath = require("./public-path");
15
14
  var _contextualEe = require("../../common/event-emitter/contextual-ee");
@@ -20,8 +19,6 @@ var _loaderConfig = require("../../common/config/loader-config");
20
19
  * SPDX-License-Identifier: Apache-2.0
21
20
  */
22
21
 
23
- const alreadySetOnce = new Set(); // the configure() function can run multiple times in agent lifecycle for different agents
24
-
25
22
  /**
26
23
  * Sets or re-sets the agent's configuration values from global settings. This also attach those as properties to the agent instance.
27
24
  * IMPORTANT: setNREUMInitializedAgent must be called on the agent prior to calling this function.
@@ -52,32 +49,37 @@ function configure(agent, opts = {}, loaderType, forceDrain) {
52
49
  }
53
50
  agent.info = (0, _info.mergeInfo)(info);
54
51
  const updatedInit = agent.init;
55
- const internalTrafficList = [info.beacon, info.errorBeacon];
56
- if (!alreadySetOnce.has(agent.agentIdentifier)) {
57
- if (updatedInit.proxy.assets) {
58
- (0, _publicPath.redefinePublicPath)(updatedInit.proxy.assets);
59
- internalTrafficList.push(updatedInit.proxy.assets);
60
- }
61
- if (updatedInit.proxy.beacon) internalTrafficList.push(updatedInit.proxy.beacon);
62
- agent.beacons = [...internalTrafficList];
63
- (0, _topLevelCallers.setTopLevelCallers)(agent); // no need to set global APIs on newrelic obj more than once
64
- (0, _nreum.addToNREUM)('activatedFeatures', _featureFlags.activatedFeatures);
52
+ agent.runtime ??= (0, _runtime.mergeRuntime)(runtime);
53
+
54
+ // Apply proxy settings whenever configure is called (supports late {init} setting)
55
+ if (updatedInit.proxy.assets) {
56
+ (0, _publicPath.redefinePublicPath)(updatedInit.proxy.assets);
65
57
  }
66
- runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
67
- runtime.ptid = agent.agentIdentifier;
68
- runtime.loaderType = loaderType;
69
- agent.runtime = (0, _runtime.mergeRuntime)(runtime);
70
- if (!alreadySetOnce.has(agent.agentIdentifier)) {
58
+ if (!agent.runtime.configured) {
59
+ Object.defineProperty(agent, 'beacons', {
60
+ get() {
61
+ return [agent.info.beacon, agent.info.errorBeacon, agent.init.proxy.assets, agent.init.proxy.beacon].filter(Boolean);
62
+ }
63
+ });
64
+ Object.defineProperty(agent.runtime, 'denyList', {
65
+ get() {
66
+ // Compute the internal traffic list fresh each time to ensure beacons array is current
67
+ return [...(agent.init.ajax.deny_list || []), ...(agent.init.ajax.block_internal ? agent.beacons : [])];
68
+ }
69
+ });
70
+ agent.runtime.ptid = agent.agentIdentifier;
71
+ (0, _topLevelCallers.setTopLevelCallers)(agent); // no need to set global APIs on newrelic obj more than once
72
+
73
+ agent.runtime.loaderType = loaderType;
71
74
  agent.ee = _contextualEe.ee.get(agent.agentIdentifier);
72
75
  agent.exposed = exposed;
73
76
  (0, _globalEvent.dispatchGlobalEvent)({
74
- agentIdentifier: agent.agentIdentifier,
75
- drained: !!_featureFlags.activatedFeatures?.[agent.agentIdentifier],
77
+ drained: !!agent.runtime.activatedFeatures,
76
78
  type: 'lifecycle',
77
79
  name: 'initialize',
78
80
  feature: undefined,
79
81
  data: agent.config
80
82
  });
83
+ agent.runtime.configured = true;
81
84
  }
82
- alreadySetOnce.add(agent.agentIdentifier);
83
85
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
2
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { warn } from '../util/console';
@@ -17,7 +17,7 @@ export function getModeledObject(obj, model) {
17
17
  output[key] = null;
18
18
  continue;
19
19
  }
20
- if (Array.isArray(obj[key]) && Array.isArray(model[key])) output[key] = Array.from(new Set([...obj[key], ...model[key]]));else if (typeof obj[key] === 'object' && typeof model[key] === 'object') output[key] = getModeledObject(obj[key], model[key]);else output[key] = obj[key];
20
+ if (Array.isArray(obj[key]) && Array.isArray(model[key])) output[key] = Array.from(new Set([...obj[key], ...model[key]]));else if (obj[key] instanceof Map || obj[key] instanceof Set || obj[key] instanceof Date || obj[key] instanceof RegExp) output[key] = obj[key];else if (typeof obj[key] === 'object' && typeof model[key] === 'object') output[key] = getModeledObject(obj[key], model[key]);else output[key] = obj[key];
21
21
  } catch (e) {
22
22
  if (!output[key]) warn(1, e);
23
23
  }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
2
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { getModeledObject } from './configurable';
@@ -21,8 +21,12 @@ const hiddenState = {
21
21
  consented: false
22
22
  };
23
23
  const RuntimeModel = {
24
+ /** @type {{[key: string]: number} | undefined} */
25
+ activatedFeatures: undefined,
24
26
  /** Agent-specific metadata found in the RUM call response. ex. entityGuid */
25
27
  appMetadata: {},
28
+ /** @type {boolean} */
29
+ configured: false,
26
30
  get consented() {
27
31
  return this.session?.state?.consent || hiddenState.consented;
28
32
  },
@@ -30,8 +34,10 @@ const RuntimeModel = {
30
34
  hiddenState.consented = value;
31
35
  },
32
36
  customTransaction: undefined,
33
- denyList: undefined,
37
+ denyList: [],
34
38
  disabled: false,
39
+ /** @type {Map<string, {staged: boolean, priority: number}>} */
40
+ drainRegistry: new Map(),
35
41
  harvester: undefined,
36
42
  isolatedBacklog: false,
37
43
  isRecording: false,
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.310.1";
14
+ export const VERSION = "1.311.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.310.1";
14
+ export const VERSION = "1.311.0";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
2
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
@@ -49,4 +49,17 @@ export const ffVersion = (() => {
49
49
  * @type {number}
50
50
  */
51
51
  export const originTime = Date.now() - now();
52
- export const supportsNavTimingL2 = () => typeof PerformanceNavigationTiming !== 'undefined' && globalScope?.performance?.getEntriesByType('navigation')?.[0]?.responseStart;
52
+
53
+ /**
54
+ * Gets the first navigation entry from the Performance Timeline API.
55
+ * Returns undefined if the entry is not available or invalid.
56
+ * Matches web-vitals validation: checks that responseStart exists, is positive, and is not larger than current time.
57
+ * See: https://github.com/GoogleChrome/web-vitals/issues/137
58
+ * @returns {PerformanceNavigationTiming | undefined}
59
+ */
60
+ export const getNavigationEntry = () => {
61
+ const navigationEntry = globalScope?.performance?.getEntriesByType?.('navigation')?.[0];
62
+ if (navigationEntry && navigationEntry.responseStart > 0 && navigationEntry.responseStart < globalScope.performance.now()) {
63
+ return navigationEntry;
64
+ }
65
+ };
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Copyright 2020-2025 New Relic, Inc. All rights reserved.
2
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
 
@@ -84,5 +84,5 @@ export function setDenyList(denyListConfig) {
84
84
  function convertToRegularExpression(filter, isPathname = false) {
85
85
  const newFilter = filter.replace(/[.+?^${}()|[\]\\]/g, m => '\\' + m) // use a replacer function to not break apm injection
86
86
  .replace(/\*/g, '.*?'); // use lazy matching instead of greedy
87
- return new RegExp((isPathname ? '^' : '') + newFilter + '$');
87
+ return new RegExp((isPathname ? '^' : '') + newFilter + '\x24'); // x24 == $, but using a literal $ causes webpack to to break when building unminified
88
88
  }
@@ -4,82 +4,73 @@
4
4
  */
5
5
 
6
6
  import { dispatchGlobalEvent } from '../../common/dispatch/global-event';
7
- import { ee } from '../event-emitter/contextual-ee';
8
7
  import { registerHandler as defaultRegister } from '../event-emitter/register-handler';
9
8
  import { featurePriority } from '../../loaders/features/features';
10
9
  import { EventContext } from '../event-emitter/event-context';
11
- const registry = {};
12
10
 
13
11
  /**
14
12
  * Adds an entry to the centralized drain registry specifying that a particular agent has events of a particular named
15
13
  * event-group "bucket" that should be drained at the time the agent drains all its buffered events. Buffered events
16
14
  * accumulate because instrumentation begins as soon as possible, before the agent has finished lazy-loading the code
17
15
  * responsible for aggregating and reporting captured data.
18
- * @param {string} agentIdentifier - A 16 character string uniquely identifying the agent.
16
+ * @param {Object} agentRef - The agent reference object.
19
17
  * @param {string} group - The named "bucket" for the events this feature will be bucketing for later collection.
20
18
  */
21
- export function registerDrain(agentIdentifier, group) {
19
+ export function registerDrain(agentRef, group) {
20
+ if (!agentRef) return;
22
21
  // Here `item` captures the registered properties of a feature-group: whether it is ready for its buffered events
23
22
  // to be drained (`staged`) and the `priority` order in which it should be drained relative to other feature groups.
24
23
  const item = {
25
24
  staged: false,
26
25
  priority: featurePriority[group] || 0
27
26
  };
28
- curateRegistry(agentIdentifier);
29
- if (!registry[agentIdentifier].get(group)) registry[agentIdentifier].set(group, item);
27
+ if (!agentRef.runtime.drainRegistry.get(group)) agentRef.runtime.drainRegistry.set(group, item);
30
28
  }
31
29
 
32
30
  /**
33
31
  * Removes an item from the registry and immediately re-checks if the registry is ready to "drain all"
34
- * @param {*} agentIdentifier - A 16 character string uniquely identifying the agent.
32
+ * @param {Object} agentRef - The agent reference object.
35
33
  * @param {*} group - The named "bucket" to be removed from the registry
36
34
  */
37
- export function deregisterDrain(agentIdentifier, group) {
38
- if (!agentIdentifier || !registry[agentIdentifier]) return;
39
- if (registry[agentIdentifier].get(group)) registry[agentIdentifier].delete(group);
40
- drainGroup(agentIdentifier, group, false);
41
- if (registry[agentIdentifier].size) checkCanDrainAll(agentIdentifier);
42
- }
43
-
44
- /**
45
- * Registers the specified agent with the centralized event buffer registry if it is not already registered.
46
- * Agents without an identifier (as in the case of some tests) will be excluded from the registry.
47
- * @param {string} agentIdentifier - A 16 character string uniquely identifying an agent.
48
- */
49
- function curateRegistry(agentIdentifier) {
50
- if (!agentIdentifier) throw new Error('agentIdentifier required');
51
- if (!registry[agentIdentifier]) registry[agentIdentifier] = new Map();
35
+ export function deregisterDrain(agentRef, group) {
36
+ if (!agentRef) return;
37
+ const drainRegistry = agentRef.runtime.drainRegistry;
38
+ if (!drainRegistry) return;
39
+ if (drainRegistry.get(group)) drainRegistry.delete(group);
40
+ drainGroup(agentRef, group, false);
41
+ if (drainRegistry.size) checkCanDrainAll(agentRef);
52
42
  }
53
43
 
54
44
  /**
55
45
  * Drain buffered events out of the event emitter. Each feature should have its events bucketed by "group" and drain
56
46
  * its own named group explicitly, when ready.
57
- * @param {string} agentIdentifier - A unique 16 character ID corresponding to an instantiated agent.
47
+ * @param {Object} agentRef - The agent reference object.
58
48
  * @param {string} featureName - A named group into which the feature's buffered events are bucketed.
59
49
  * @param {boolean} force - Whether to force the drain to occur immediately, bypassing the registry and staging logic.
60
50
  */
61
- export function drain(agentIdentifier = '', featureName = 'feature', force = false) {
62
- curateRegistry(agentIdentifier);
51
+ export function drain(agentRef, featureName = 'feature', force = false) {
52
+ if (!agentRef) return;
63
53
  // If the feature for the specified agent is not in the registry, that means the instrument file was bypassed.
64
54
  // This could happen in tests, or loaders that directly import the aggregator. In these cases it is safe to
65
55
  // drain the feature group immediately rather than waiting to drain all at once.
66
- if (!agentIdentifier || !registry[agentIdentifier].get(featureName) || force) return drainGroup(agentIdentifier, featureName);
56
+ if (!agentRef.runtime.drainRegistry.get(featureName) || force) return drainGroup(agentRef, featureName);
67
57
 
68
58
  // When `drain` is called, this feature is ready to drain (staged).
69
- registry[agentIdentifier].get(featureName).staged = true;
70
- checkCanDrainAll(agentIdentifier);
59
+ agentRef.runtime.drainRegistry.get(featureName).staged = true;
60
+ checkCanDrainAll(agentRef);
71
61
  }
72
62
 
73
63
  /** Checks all items in the registry to see if they have been "staged". If ALL items are staged, it will drain all registry items (drainGroup). It not, nothing will happen */
74
- function checkCanDrainAll(agentIdentifier) {
64
+ function checkCanDrainAll(agentRef) {
65
+ if (!agentRef) return;
75
66
  // Only when the event-groups for all features are ready to drain (staged) do we execute the drain. This has the effect
76
67
  // that the last feature to call drain triggers drain for all features.
77
- const items = Array.from(registry[agentIdentifier]);
68
+ const items = Array.from(agentRef.runtime.drainRegistry);
78
69
  if (items.every(([key, values]) => values.staged)) {
79
70
  items.sort((a, b) => a[1].priority - b[1].priority);
80
71
  items.forEach(([group]) => {
81
- registry[agentIdentifier].delete(group);
82
- drainGroup(agentIdentifier, group);
72
+ agentRef.runtime.drainRegistry.delete(group);
73
+ drainGroup(agentRef, group);
83
74
  });
84
75
  }
85
76
  }
@@ -89,12 +80,12 @@ function checkCanDrainAll(agentIdentifier) {
89
80
  * the subscribed handlers for the group.
90
81
  * @param {*} group - The name of a particular feature's event "bucket".
91
82
  */
92
- function drainGroup(agentIdentifier, group, activateGroup = true) {
93
- const baseEE = agentIdentifier ? ee.get(agentIdentifier) : ee;
83
+ function drainGroup(agentRef, group, activateGroup = true) {
84
+ if (!agentRef) return;
85
+ const baseEE = agentRef.ee;
94
86
  const handlers = defaultRegister.handlers; // other storage in registerHandler
95
- if (baseEE.aborted || !baseEE.backlog || !handlers) return;
87
+ if (!baseEE || baseEE.aborted || !baseEE.backlog || !handlers) return;
96
88
  dispatchGlobalEvent({
97
- agentIdentifier,
98
89
  type: 'lifecycle',
99
90
  name: 'drain',
100
91
  feature: group
@@ -15,7 +15,6 @@ import { obj, param } from '../url/encode';
15
15
  import { warn } from '../util/console';
16
16
  import { stringify } from '../util/stringify';
17
17
  import { getSubmitMethod, xhr as xhrMethod, xhrFetch as fetchMethod } from '../util/submit-data';
18
- import { activatedFeatures } from '../util/feature-flags';
19
18
  import { dispatchGlobalEvent } from '../dispatch/global-event';
20
19
  const RETRY = 'Harvester/Retry/';
21
20
  const RETRY_ATTEMPTED = RETRY + 'Attempted/';
@@ -229,8 +228,7 @@ export function send(agentRef, {
229
228
  }
230
229
  }
231
230
  dispatchGlobalEvent({
232
- agentIdentifier: agentRef.agentIdentifier,
233
- drained: !!activatedFeatures?.[agentRef.agentIdentifier],
231
+ drained: !!agentRef.runtime?.activatedFeatures,
234
232
  type: 'data',
235
233
  name: 'harvest',
236
234
  feature: featureName,