@newrelic/browser-agent 1.312.1 → 1.313.0-rc.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/dist/cjs/common/config/init-types.js +3 -2
  3. package/dist/cjs/common/config/init.js +10 -8
  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/timing/time-keeper.js +28 -1
  7. package/dist/cjs/common/util/short-circuit.js +13 -0
  8. package/dist/cjs/common/util/submit-data.js +2 -9
  9. package/dist/cjs/common/v2/script-correlation.js +50 -0
  10. package/dist/cjs/common/v2/script-tracker.js +278 -0
  11. package/dist/cjs/common/{util/v2.js → v2/utils.js} +4 -4
  12. package/dist/cjs/common/wrap/wrap-fetch.js +2 -2
  13. package/dist/cjs/common/wrap/wrap-function.js +2 -2
  14. package/dist/cjs/common/wrap/wrap-xhr.js +2 -2
  15. package/dist/cjs/features/ajax/aggregate/index.js +4 -4
  16. package/dist/cjs/features/generic_events/aggregate/index.js +21 -2
  17. package/dist/cjs/features/generic_events/instrument/index.js +24 -21
  18. package/dist/cjs/features/jserrors/aggregate/index.js +206 -40
  19. package/dist/cjs/features/logging/aggregate/index.js +4 -4
  20. package/dist/cjs/features/metrics/instrument/index.js +1 -8
  21. package/dist/cjs/features/session_trace/aggregate/index.js +3 -4
  22. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +2 -2
  23. package/dist/cjs/interfaces/registered-entity.js +7 -20
  24. package/dist/cjs/loaders/api/register-api-types.js +8 -8
  25. package/dist/cjs/loaders/api/register.js +57 -44
  26. package/dist/esm/common/config/init-types.js +3 -2
  27. package/dist/esm/common/config/init.js +10 -8
  28. package/dist/esm/common/constants/env.cdn.js +1 -1
  29. package/dist/esm/common/constants/env.npm.js +1 -1
  30. package/dist/esm/common/timing/time-keeper.js +28 -1
  31. package/dist/esm/common/util/short-circuit.js +6 -0
  32. package/dist/esm/common/util/submit-data.js +2 -9
  33. package/dist/esm/common/v2/script-correlation.js +43 -0
  34. package/dist/esm/common/v2/script-tracker.js +270 -0
  35. package/dist/esm/common/{util/v2.js → v2/utils.js} +4 -4
  36. package/dist/esm/common/wrap/wrap-fetch.js +1 -1
  37. package/dist/esm/common/wrap/wrap-function.js +1 -1
  38. package/dist/esm/common/wrap/wrap-xhr.js +1 -1
  39. package/dist/esm/features/ajax/aggregate/index.js +1 -1
  40. package/dist/esm/features/generic_events/aggregate/index.js +20 -1
  41. package/dist/esm/features/generic_events/instrument/index.js +24 -21
  42. package/dist/esm/features/jserrors/aggregate/index.js +205 -39
  43. package/dist/esm/features/logging/aggregate/index.js +1 -1
  44. package/dist/esm/features/metrics/instrument/index.js +2 -9
  45. package/dist/esm/features/session_trace/aggregate/index.js +4 -5
  46. package/dist/esm/features/session_trace/aggregate/trace/storage.js +2 -2
  47. package/dist/esm/interfaces/registered-entity.js +7 -20
  48. package/dist/esm/loaders/api/register-api-types.js +8 -8
  49. package/dist/esm/loaders/api/register.js +54 -42
  50. package/dist/tsconfig.tsbuildinfo +1 -1
  51. package/dist/types/common/config/init-types.d.ts +10 -8
  52. package/dist/types/common/config/init-types.d.ts.map +1 -1
  53. package/dist/types/common/config/init.d.ts.map +1 -1
  54. package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
  55. package/dist/types/common/util/short-circuit.d.ts +8 -0
  56. package/dist/types/common/util/short-circuit.d.ts.map +1 -0
  57. package/dist/types/common/util/submit-data.d.ts.map +1 -1
  58. package/dist/types/common/v2/script-correlation.d.ts +38 -0
  59. package/dist/types/common/v2/script-correlation.d.ts.map +1 -0
  60. package/dist/types/common/{util → v2}/script-tracker.d.ts +3 -0
  61. package/dist/types/common/v2/script-tracker.d.ts.map +1 -0
  62. package/dist/types/common/{util/v2.d.ts → v2/utils.d.ts} +1 -1
  63. package/dist/types/common/v2/utils.d.ts.map +1 -0
  64. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  65. package/dist/types/features/generic_events/instrument/index.d.ts +1 -1
  66. package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
  67. package/dist/types/features/jserrors/aggregate/index.d.ts +25 -16
  68. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  69. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  70. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  71. package/dist/types/interfaces/registered-entity.d.ts +0 -10
  72. package/dist/types/interfaces/registered-entity.d.ts.map +1 -1
  73. package/dist/types/loaders/api/register-api-types.d.ts +15 -15
  74. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -1
  75. package/dist/types/loaders/api/register.d.ts +6 -0
  76. package/dist/types/loaders/api/register.d.ts.map +1 -1
  77. package/package.json +2 -2
  78. package/src/common/config/init-types.js +3 -2
  79. package/src/common/config/init.js +6 -4
  80. package/src/common/timing/time-keeper.js +30 -1
  81. package/src/common/util/short-circuit.js +6 -0
  82. package/src/common/util/submit-data.js +2 -8
  83. package/src/common/v2/script-correlation.js +44 -0
  84. package/src/common/v2/script-tracker.js +260 -0
  85. package/src/common/{util/v2.js → v2/utils.js} +4 -4
  86. package/src/common/wrap/wrap-fetch.js +1 -1
  87. package/src/common/wrap/wrap-function.js +1 -1
  88. package/src/common/wrap/wrap-xhr.js +1 -1
  89. package/src/features/ajax/aggregate/index.js +1 -1
  90. package/src/features/generic_events/aggregate/index.js +20 -1
  91. package/src/features/generic_events/instrument/index.js +25 -22
  92. package/src/features/jserrors/aggregate/index.js +200 -43
  93. package/src/features/logging/aggregate/index.js +1 -1
  94. package/src/features/metrics/instrument/index.js +2 -13
  95. package/src/features/session_trace/aggregate/index.js +4 -6
  96. package/src/features/session_trace/aggregate/trace/storage.js +2 -2
  97. package/src/interfaces/registered-entity.js +8 -20
  98. package/src/loaders/api/register-api-types.js +8 -8
  99. package/src/loaders/api/register.js +56 -35
  100. package/dist/cjs/common/util/script-tracker.js +0 -204
  101. package/dist/esm/common/util/script-tracker.js +0 -196
  102. package/dist/types/common/util/script-tracker.d.ts.map +0 -1
  103. package/dist/types/common/util/v2.d.ts.map +0 -1
  104. package/src/common/util/script-tracker.js +0 -189
@@ -13,7 +13,6 @@ exports.default = void 0;
13
13
  * @property {(name: string, attributes?: object) => void} addPageAction - Add a page action for the registered entity.
14
14
  * @property {(message: string, options?: { customAttributes?: object, level?: 'ERROR' | 'TRACE' | 'DEBUG' | 'INFO' | 'WARN'}) => void} log - Capture a log for the registered entity.
15
15
  * @property {(error: Error | string, customAttributes?: object) => void} noticeError - Notice an error for the registered entity.
16
- * @property {(target: RegisterAPIConstructor) => RegisterAPI} register - Record a custom event for the registered entity.
17
16
  * @property {() => void} deregister - Deregister the registered entity, which blocks its use and captures end of life timings.
18
17
  * @property {(eventType: string, attributes?: Object) => void} recordCustomEvent - Record a custom event for the registered entity.
19
18
  * @property {(eventType: string, options?: {start?: number|PerformanceMark, end?: number|PerformanceMark, customAttributes?: object}) => ({start: number, end: number, duration: number, customAttributes: object})} measure - Measures a task that is recorded as a BrowserPerformance event.
@@ -27,14 +26,14 @@ exports.default = void 0;
27
26
  * @property {string} id - The unique id for the registered entity. This will be assigned to any synthesized entities.
28
27
  * @property {string} name - The readable name for the registered entity. This will be assigned to any synthesized entities.
29
28
  * @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
- * @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.
29
+ * @property {RegisterAPITarget} [parent] - The parent target for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
31
30
  * @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
32
31
  */
33
32
  /**
34
33
  * @typedef {Object} RegisterAPIMetadata
35
34
  * @property {Object} customAttributes - The custom attributes for the registered entity.
36
- * @property {RegisterAPITimings} timings - The timing metrics for the registered entity.
37
- * @property {RegisterAPITarget} target - The options for the registered entity.
35
+ * @property {Partial<RegisterAPITimings>} timings - The timing metrics for the registered entity.
36
+ * @property {Partial<RegisterAPITarget>} target - The options for the registered entity.
38
37
  */
39
38
  /**
40
39
  * @typedef {Object} RegisterAPITarget
@@ -42,15 +41,16 @@ exports.default = void 0;
42
41
  * @property {string} name - The name returned for the registered entity.
43
42
  * @property {{[key: string]: any}} [tags] - The tags for the registered entity as key-value pairs.
44
43
  * @property {string} [parentId] - The parentId for the registered entity. If none was supplied, it will assume the entity guid from the main agent.
45
- * @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.
46
44
  */
47
45
  /**
48
46
  * @typedef {Object} RegisterAPITimings
49
47
  * @property {number} registeredAt - The timestamp when the registered entity was created.
50
48
  * @property {number} [reportedAt] - The timestamp when the registered entity was deregistered.
51
- * @property {number} fetchStart - The timestamp when the registered entity began fetching.
52
- * @property {number} fetchEnd - The timestamp when the registered entity finished fetching.
49
+ * @property {number} fetchStart - The timestamp when the registered entity began fetching (performance.start).
50
+ * @property {number} fetchEnd - The timestamp when the registered entity finished fetching (performance.end).
51
+ * @property {number} scriptStart - The timestamp when script initialization began (max of dom.start or performance.end, or performance.end if no dom.start).
52
+ * @property {number} scriptEnd - The timestamp when script loading completed (dom.end or registeredAt if no dom.end).
53
53
  * @property {Object} [asset] - The asset path (if found) for the registered entity.
54
- * @property {string} type - The type of timing associated with the registered entity, 'script' or 'link' if found with the performance resource API, 'inline' if found to be associated with the root document URL, or 'unknown' if no associated resource could be found.
54
+ * @property {string} type - The type of timing associated with the registered entity, 'script' or 'link' if found with the performance resource API, 'fetch' for dynamic imports, 'inline' if found to be associated with the root document URL, or 'unknown' if no associated resource could be found.
55
55
  */
56
56
  var _default = exports.default = {};
@@ -4,9 +4,10 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.setupRegisterAPI = setupRegisterAPI;
7
+ exports.warnings = void 0;
7
8
  var _handle = require("../../common/event-emitter/handle");
8
9
  var _console = require("../../common/util/console");
9
- var _v = require("../../common/util/v2");
10
+ var _utils = require("../../common/v2/utils");
10
11
  var _features = require("../features/features");
11
12
  var _now = require("../../common/timing/now");
12
13
  var _constants = require("../../features/metrics/constants");
@@ -19,7 +20,7 @@ var _invoke = require("../../common/util/invoke");
19
20
  var _measure = require("./measure");
20
21
  var _recordCustomEvent = require("./recordCustomEvent");
21
22
  var _pageVisibility = require("../../common/window/page-visibility");
22
- var _scriptTracker = require("../../common/util/script-tracker");
23
+ var _scriptTracker = require("../../common/v2/script-tracker");
23
24
  var _uniqueId = require("../../common/ids/unique-id");
24
25
  /**
25
26
  * Copyright 2020-2026 New Relic, Inc. All rights reserved.
@@ -32,6 +33,23 @@ var _uniqueId = require("../../common/ids/unique-id");
32
33
 
33
34
  const PROTECTED_KEYS = ['name', 'id', 'type'];
34
35
 
36
+ /**
37
+ * Map of API methods to their names (prevents minification from breaking method name references)
38
+ * @private
39
+ */
40
+ const METHOD_NAMES = new Map([[_addPageAction.addPageAction, 'addPageAction'], [_log.log, 'log'], [_measure.measure, 'measure'], [_noticeError.noticeError, 'noticeError'], [_recordCustomEvent.recordCustomEvent, 'recordCustomEvent']]);
41
+
42
+ /**
43
+ * Warning functions that only fire once - can be reset in tests
44
+ * @private
45
+ */
46
+ const warnings = exports.warnings = {
47
+ experimental: (0, _invoke.single)(() => (0, _console.warn)(54, 'newrelic.register')),
48
+ disabled: (0, _invoke.single)(() => (0, _console.warn)(55)),
49
+ invalidTarget: (0, _invoke.single)(target => (0, _console.warn)(48, target)),
50
+ deregistered: (0, _invoke.single)(() => (0, _console.warn)(68))
51
+ };
52
+
35
53
  /**
36
54
  * @experimental
37
55
  * IMPORTANT: This feature is being developed for use internally and is not in a public-facing production-ready state.
@@ -48,38 +66,41 @@ function setupRegisterAPI(agent) {
48
66
  * Also conducts certain side-effects, such as harvesting a PageView event when triggered and gathering metadata for the registered entity.
49
67
  * @param {Object} agentRef the reference to the base agent instance
50
68
  * @param {import('./register-api-types').RegisterAPIConstructor} target
51
- * @param {import('./register-api-types').RegisterAPIConstructor} [parent]
52
69
  * @returns {RegisterAPI} the api object to be returned from the register api method
53
70
  */
54
- function register(agentRef, target, parent) {
55
- (0, _console.warn)(54, 'newrelic.register');
71
+ function register(agentRef, target) {
72
+ warnings.experimental();
56
73
  target ||= {};
57
74
  target.instance = (0, _uniqueId.generateRandomHexString)(8);
58
- target.type = _v.V2_TYPES.MFE;
75
+ target.type = _utils.V2_TYPES.MFE;
59
76
  target.licenseKey ||= agentRef.info.licenseKey; // will inherit the license key from the container agent if not provided for brevity. A future state may dictate that we need different license keys to do different things.
60
77
  target.blocked = false;
61
78
  if (typeof target.tags !== 'object' || target.tags === null || Array.isArray(target.tags)) target.tags = {};
62
- target.parent = parent || {
79
+ target.parent ??= {
63
80
  get id() {
64
81
  return agentRef.runtime.appMetadata.agents[0].entityGuid;
65
82
  },
66
83
  // getter because this is asyncronously set
67
- type: _v.V2_TYPES.BA
84
+ type: _utils.V2_TYPES.BA
68
85
  };
69
86
  const timings = (0, _scriptTracker.findScriptTimings)();
70
87
  const attrs = {};
71
- Object.defineProperty(target, 'attributes', {
72
- get() {
73
- return {
74
- ...attrs,
75
- 'source.id': target.id,
76
- 'source.name': target.name,
77
- 'source.type': target.type,
78
- 'parent.type': target.parent?.type || _v.V2_TYPES.BA,
79
- 'parent.id': target.parent?.id
80
- };
81
- }
82
- });
88
+
89
+ // Only define attributes getter if it doesn't already exist
90
+ if (!Object.prototype.hasOwnProperty.call(target, 'attributes')) {
91
+ Object.defineProperty(target, 'attributes', {
92
+ get() {
93
+ return {
94
+ ...attrs,
95
+ 'source.id': target.id,
96
+ 'source.name': target.name,
97
+ 'source.type': target.type,
98
+ 'parent.type': target.parent?.type || _utils.V2_TYPES.BA,
99
+ 'parent.id': target.parent?.id
100
+ };
101
+ }
102
+ });
103
+ }
83
104
 
84
105
  // Process tags object and add to attrs, excluding protected keys
85
106
  Object.entries(target.tags).forEach(([key, value]) => {
@@ -87,23 +108,11 @@ function register(agentRef, target, parent) {
87
108
  attrs["source.".concat(key)] = value;
88
109
  }
89
110
  });
90
- target.isolated ??= true;
91
111
 
92
112
  /** @type {Function} a function that is set and reports when APIs are triggered -- warns the customer of the invalid state */
93
113
  let invalidApiResponse = () => {};
94
114
  /** @type {Array} the array of registered target APIs */
95
115
  const registeredEntities = agentRef.runtime.registeredEntities;
96
- if (!target.isolated) {
97
- /** if we have already registered this non-isolated target, go ahead and re-use it */
98
- const sharedEntity = registeredEntities.find(({
99
- metadata: {
100
- target: {
101
- id
102
- }
103
- }
104
- }) => id === target.id && !target.isolated);
105
- if (sharedEntity) return sharedEntity;
106
- }
107
116
 
108
117
  /**
109
118
  * Block the API, and supply a warning function to display a message to end users
@@ -118,8 +127,8 @@ function register(agentRef, target, parent) {
118
127
  }
119
128
 
120
129
  /** primary cases that can block the register API from working at init time */
121
- if (!agentRef.init.api.allow_registered_children) block((0, _invoke.single)(() => (0, _console.warn)(55)));
122
- if (!hasValidValue(target.id) || !hasValidValue(target.name)) block((0, _invoke.single)(() => (0, _console.warn)(48, target)));
130
+ if (!agentRef.init.api.register.enabled) block(warnings.disabled);
131
+ if (!hasValidValue(target.id) || !hasValidValue(target.name)) block(() => warnings.invalidTarget(target));
123
132
 
124
133
  /** @type {RegisterAPI} */
125
134
  const api = {
@@ -130,7 +139,7 @@ function register(agentRef, target, parent) {
130
139
  deregister: () => {
131
140
  /** note: blocking this instance will disable access for all entities sharing the instance, and will invalidate it from the v2 checks */
132
141
  reportTimings();
133
- block((0, _invoke.single)(() => (0, _console.warn)(68)));
142
+ block(warnings.deregistered);
134
143
  },
135
144
  log: (message, options = {}) => report(_log.log, [message, {
136
145
  ...options,
@@ -150,7 +159,6 @@ function register(agentRef, target, parent) {
150
159
  ...attrs,
151
160
  ...attributes
152
161
  }, agentRef], target),
153
- register: (target = {}) => report(register, [agentRef, target], api.metadata.target),
154
162
  recordCustomEvent: (eventType, attributes = {}) => report(_recordCustomEvent.recordCustomEvent, [eventType, {
155
163
  ...attrs,
156
164
  ...attributes
@@ -192,20 +200,24 @@ function register(agentRef, target, parent) {
192
200
  // only ever report the timings the first time this is called
193
201
  if (timings.reportedAt) return;
194
202
  timings.reportedAt = (0, _now.now)();
203
+ const timeToFetch = timings.fetchEnd - timings.fetchStart; // fetchStart to fetchEnd
204
+ const timeToExecute = timings.scriptEnd - timings.scriptStart; // scriptStart to scriptEnd
195
205
  api.recordCustomEvent('MicroFrontEndTiming', {
196
206
  assetUrl: timings.asset,
197
207
  // the url of the script that was registered, or undefined if it could not be determined (inline or no match)
198
208
  assetType: timings.type,
199
209
  // the type of asset that was associated with the timings, one of 'script', 'link' (if preloaded and found in the resource timing buffer), 'preload' (if preloaded but not found in the resource timing buffer), or "unknown" if it could not be determined
200
- timeToLoad: timings.registeredAt - timings.fetchStart,
201
- // fetchStart to registeredAt
210
+ timeAlive: timings.reportedAt - timings.registeredAt,
211
+ // registeredAt to reportedAt
202
212
  timeToBeRequested: timings.fetchStart,
203
213
  // origin to fetchStart
204
- timeToFetch: timings.fetchEnd - timings.fetchStart,
214
+ timeToExecute,
215
+ // scriptStart to scriptEnd
216
+ timeToFetch,
205
217
  // fetchStart to fetchEnd
206
- timeToRegister: timings.registeredAt - timings.fetchEnd,
207
- // fetchEnd to registeredAt
208
- timeAlive: timings.reportedAt - timings.registeredAt // registeredAt to reportedAt
218
+ timeToLoad: timeToFetch + timeToExecute,
219
+ // fetch time and script time together
220
+ timeToRegister: timings.registeredAt // timestamp when register() was called
209
221
  });
210
222
  }
211
223
 
@@ -222,7 +234,7 @@ function register(agentRef, target, parent) {
222
234
 
223
235
  /**
224
236
  * The reporter method that will be used to report the data to the container agent's API method. If invalid, will log a warning and not execute.
225
- * If the api.duplicate_registered_data configuration value is set to true, the data will be reported to BOTH the container and the external target
237
+ * If the api.register.duplicate_data_to_container configuration value is set to true, the data will be reported to BOTH the container and the external target
226
238
  * @param {*} methodToCall the container agent's API method to call
227
239
  * @param {*} args the arguments to supply to the container agent's API method
228
240
  * @param {string} target the target to report the data to. If undefined, will report to the container agent's target.
@@ -233,7 +245,8 @@ function register(agentRef, target, parent) {
233
245
  if (isBlocked() && methodToCall !== register) return;
234
246
  /** set the timestamp before the async part of waiting for the rum response for better accuracy */
235
247
  const timestamp = (0, _now.now)();
236
- (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ["API/register/".concat(methodToCall.name, "/called")], undefined, _features.FEATURE_NAMES.metrics, agentRef.ee);
248
+ const methodName = METHOD_NAMES.get(methodToCall) || 'unknown';
249
+ (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ["API/register/".concat(methodName, "/called")], undefined, _features.FEATURE_NAMES.metrics, agentRef.ee);
237
250
  try {
238
251
  return methodToCall(...args, target, timestamp); // always report to target
239
252
  } catch (err) {
@@ -12,8 +12,9 @@
12
12
  * @property {boolean} [ajax.enabled] - Turn on/off the ajax feature (on by default).
13
13
  * @property {boolean} [ajax.autoStart] - If true, the agent will automatically start the ajax feature. Otherwise, it will be in a deferred state until the `start` API method is called.
14
14
  * @property {Object} [api]
15
- * @property {boolean} [api.allow_registered_children] - If true, the agent will allow registered children to be sent to the server.
16
- * @property {boolean} [api.duplicate_registered_data] - If true, the agent will capture registered child data to the main agent as well as the registered child.
15
+ * @property {Object} [api.register]
16
+ * @property {boolean} [api.register.enabled] - If true, the agent will allow registered children to be sent to the server.
17
+ * @property {boolean} [api.register.duplicate_data_to_container] - If true, the agent will capture registered child data to the main agent as well as the registered child.
17
18
  * @property {Object} [distributed_tracing]
18
19
  * @property {boolean} [distributed_tracing.enabled] - If true, distributed tracing headers will be added to outgoing requests. Requires ajax feature to be running.
19
20
  * @property {boolean} [distributed_tracing.exclude_newrelic_header]
@@ -21,7 +21,7 @@ const InitModelFn = () => {
21
21
  const hiddenState = {
22
22
  feature_flags: [],
23
23
  experimental: {
24
- allow_registered_children: false,
24
+ register: false,
25
25
  resources: false
26
26
  },
27
27
  mask_selector: '*',
@@ -54,13 +54,15 @@ const InitModelFn = () => {
54
54
  autoStart: true
55
55
  },
56
56
  api: {
57
- get allow_registered_children() {
58
- return hiddenState.feature_flags.includes(FEATURE_FLAGS.REGISTER) || hiddenState.experimental.allow_registered_children;
59
- },
60
- set allow_registered_children(val) {
61
- hiddenState.experimental.allow_registered_children = val;
62
- },
63
- duplicate_registered_data: false
57
+ register: {
58
+ get enabled() {
59
+ return hiddenState.feature_flags.includes(FEATURE_FLAGS.REGISTER) || hiddenState.experimental.register;
60
+ },
61
+ set enabled(val) {
62
+ hiddenState.experimental.register = val;
63
+ },
64
+ duplicate_data_to_container: false
65
+ }
64
66
  },
65
67
  browser_consent_mode: {
66
68
  enabled: false
@@ -11,7 +11,7 @@
11
11
  /**
12
12
  * Exposes the version of the agent
13
13
  */
14
- export const VERSION = "1.312.1";
14
+ export const VERSION = "1.313.0-rc.1";
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.312.1";
14
+ export const VERSION = "1.313.0-rc.1";
15
15
 
16
16
  /**
17
17
  * Exposes the build type of the agent
@@ -1,9 +1,12 @@
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
+ import { SUPPORTABILITY_METRIC_CHANNEL } from '../../features/metrics/constants';
5
6
  import { originTime } from '../constants/runtime';
6
7
  import { isNative } from '../util/monkey-patched';
8
+ import { handle } from '../event-emitter/handle';
9
+ import { FEATURE_NAMES } from '../../loaders/features/features';
7
10
 
8
11
  /**
9
12
  * Class used to adjust the timestamp of harvested data to New Relic server time. This
@@ -36,11 +39,31 @@ export class TimeKeeper {
36
39
  * @type {boolean}
37
40
  */
38
41
  #ready = false;
42
+ #reportedDrift = false;
39
43
  constructor(sessionObj) {
40
44
  this.#session = sessionObj;
41
45
  this.processStoredDiff();
42
46
  isNative(performance.now, Date.now); // will warn the user if these are not native functions. We need these to be native for time in the agent to be accurate in general.
43
47
  }
48
+ #detectDrift() {
49
+ if (this.#reportedDrift) return;
50
+ try {
51
+ // Drift detection: measures if performance.now() and Date.now() have become desynchronized
52
+ // This can happen when a machine sleeps and the performance timer freezes while Date continues
53
+ // this can also happen when a user sets their clock forward during the page lifecycle,
54
+ // but we have no way of distinguishing that from actual clock drift so we will just treat it as drift.
55
+ // In either case, the performance timestamps would be inaccurate at that point so we want to detect and report a count of it.
56
+ // We only detect positive drift (performance clock falling behind Date clock)
57
+ // Note: localTimeDiff (server time offset) is NOT part of drift - that's a legitimate offset
58
+ const drift = Date.now() - originTime - performance.now();
59
+ if (drift > 1000) {
60
+ this.#reportedDrift = true;
61
+ handle(SUPPORTABILITY_METRIC_CHANNEL, ['Generic/TimeKeeper/ClockDrift/Detected', drift], undefined, FEATURE_NAMES.metrics, this.#session.agentRef.ee);
62
+ }
63
+ } catch (err) {
64
+ // Silently ignore drift detection errors to avoid breaking normal operation
65
+ }
66
+ }
44
67
  get ready() {
45
68
  return this.#ready;
46
69
  }
@@ -85,6 +108,7 @@ export class TimeKeeper {
85
108
  * @returns {number} Corrected unix/epoch timestamp
86
109
  */
87
110
  convertRelativeTimestamp(relativeTime) {
111
+ this.#detectDrift();
88
112
  return originTime + relativeTime;
89
113
  }
90
114
 
@@ -95,6 +119,7 @@ export class TimeKeeper {
95
119
  * @returns {number}
96
120
  */
97
121
  convertAbsoluteTimestamp(timestamp) {
122
+ this.#detectDrift();
98
123
  return timestamp - originTime;
99
124
  }
100
125
 
@@ -104,6 +129,7 @@ export class TimeKeeper {
104
129
  * @return {number} Corrected unix/epoch timestamp
105
130
  */
106
131
  correctAbsoluteTimestamp(timestamp) {
132
+ this.#detectDrift();
107
133
  return timestamp - this.#localTimeDiff;
108
134
  }
109
135
 
@@ -113,6 +139,7 @@ export class TimeKeeper {
113
139
  * @returns {number}
114
140
  */
115
141
  correctRelativeTimestamp(relativeTime) {
142
+ this.#detectDrift();
116
143
  return this.correctAbsoluteTimestamp(this.convertRelativeTimestamp(relativeTime));
117
144
  }
118
145
 
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /** A special error used to short-circuit the error processing pipeline */
6
+ export class ShortCircuit extends Error {}
@@ -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
 
@@ -62,8 +62,7 @@ export function xhrFetch({
62
62
  return fetch(url, {
63
63
  headers: objHeaders,
64
64
  method,
65
- body,
66
- credentials: 'include'
65
+ body
67
66
  });
68
67
  }
69
68
 
@@ -89,12 +88,6 @@ export function xhr({
89
88
  }) {
90
89
  const request = new XMLHttpRequest();
91
90
  request.open(method, url, !sync);
92
- try {
93
- // Set cookie
94
- if ('withCredentials' in request) request.withCredentials = true;
95
- } catch (e) {
96
- // do nothing
97
- }
98
91
  headers.forEach(header => {
99
92
  request.setRequestHeader(header.key, header.value);
100
93
  });
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Copyright 2020-2026 New Relic, Inc. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ /**
6
+ * Represents script correlation data combining DOM and Performance API information
7
+ */
8
+ export class ScriptCorrelation {
9
+ /** @type {CorrelationTiming} [dom] - DOM-related information */
10
+ dom = new CorrelationTiming();
11
+ /** @type {CorrelationTiming} [performance] - Performance-related information */
12
+ performance = new CorrelationTiming();
13
+
14
+ /**
15
+ * Creates a new ScriptCorrelation instance
16
+ * @param {string} url - The cleaned URL of the script
17
+ */
18
+ constructor(url) {
19
+ /** @type {string} The cleaned URL of the script */
20
+ this.url = url;
21
+ }
22
+
23
+ /**
24
+ * Gets the script timing, using DOM timings if available, otherwise falling back to performance timings or registeredAt as appropriate. This is used to provide the most accurate script timing possible for registered entities.
25
+ * @returns {{start: number, end: number}
26
+ */
27
+ get script() {
28
+ const start = Math.max(this.dom.start, this.performance.end);
29
+ const end = Math.max(this.dom.end, this.performance.end, start);
30
+ return {
31
+ start,
32
+ end
33
+ };
34
+ }
35
+ }
36
+ class CorrelationTiming {
37
+ /** @type {number} [start] - The startTime from the performance entry */
38
+ start = 0;
39
+ /** @type {number} [end] - The responseEnd from the performance entry */
40
+ end = 0;
41
+ /** @type {*} [value] - The entry value */
42
+ value = undefined;
43
+ }