@newrelic/browser-agent 1.288.1 → 1.289.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 (154) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/cjs/common/config/info.js +7 -17
  3. package/dist/cjs/common/config/init.js +6 -34
  4. package/dist/cjs/common/config/loader-config.js +6 -16
  5. package/dist/cjs/common/config/runtime.js +21 -27
  6. package/dist/cjs/common/constants/env.cdn.js +1 -1
  7. package/dist/cjs/common/constants/env.npm.js +1 -1
  8. package/dist/cjs/common/event-emitter/contextual-ee.js +1 -2
  9. package/dist/cjs/common/serialize/bel-serializer.js +1 -3
  10. package/dist/cjs/common/timing/time-keeper.js +2 -3
  11. package/dist/cjs/features/ajax/aggregate/index.js +1 -1
  12. package/dist/cjs/features/ajax/instrument/distributed-tracing.js +10 -26
  13. package/dist/cjs/features/ajax/instrument/index.js +1 -1
  14. package/dist/cjs/features/logging/aggregate/index.js +1 -1
  15. package/dist/cjs/features/page_view_event/aggregate/index.js +2 -2
  16. package/dist/cjs/features/page_view_timing/aggregate/index.js +1 -1
  17. package/dist/cjs/features/session_replay/aggregate/index.js +1 -1
  18. package/dist/cjs/features/session_replay/instrument/index.js +3 -3
  19. package/dist/cjs/features/session_replay/shared/utils.js +5 -6
  20. package/dist/cjs/features/session_trace/instrument/index.js +1 -1
  21. package/dist/cjs/features/soft_navigations/aggregate/ajax-node.js +3 -3
  22. package/dist/cjs/features/soft_navigations/aggregate/bel-node.js +3 -3
  23. package/dist/cjs/features/soft_navigations/aggregate/index.js +7 -7
  24. package/dist/cjs/features/soft_navigations/aggregate/initial-page-load-interaction.js +4 -6
  25. package/dist/cjs/features/soft_navigations/aggregate/interaction.js +5 -6
  26. package/dist/cjs/features/spa/aggregate/index.js +1 -1
  27. package/dist/cjs/features/spa/aggregate/interaction.js +1 -1
  28. package/dist/cjs/features/spa/aggregate/serializer.js +8 -11
  29. package/dist/cjs/features/utils/aggregate-base.js +1 -1
  30. package/dist/cjs/features/utils/feature-gates.js +2 -3
  31. package/dist/cjs/features/utils/instrument-base.js +4 -4
  32. package/dist/cjs/loaders/agent.js +1 -1
  33. package/dist/cjs/loaders/api/api.js +1 -11
  34. package/dist/cjs/loaders/configure/configure.js +7 -7
  35. package/dist/cjs/loaders/features/enabled-features.js +2 -6
  36. package/dist/cjs/loaders/micro-agent.js +1 -1
  37. package/dist/esm/common/config/info.js +6 -16
  38. package/dist/esm/common/config/init.js +4 -31
  39. package/dist/esm/common/config/loader-config.js +4 -14
  40. package/dist/esm/common/config/runtime.js +19 -25
  41. package/dist/esm/common/constants/env.cdn.js +1 -1
  42. package/dist/esm/common/constants/env.npm.js +1 -1
  43. package/dist/esm/common/event-emitter/contextual-ee.js +1 -2
  44. package/dist/esm/common/serialize/bel-serializer.js +1 -3
  45. package/dist/esm/common/timing/time-keeper.js +2 -3
  46. package/dist/esm/features/ajax/aggregate/index.js +1 -1
  47. package/dist/esm/features/ajax/instrument/distributed-tracing.js +10 -26
  48. package/dist/esm/features/ajax/instrument/index.js +1 -1
  49. package/dist/esm/features/logging/aggregate/index.js +1 -1
  50. package/dist/esm/features/page_view_event/aggregate/index.js +2 -2
  51. package/dist/esm/features/page_view_timing/aggregate/index.js +1 -1
  52. package/dist/esm/features/session_replay/aggregate/index.js +1 -1
  53. package/dist/esm/features/session_replay/instrument/index.js +3 -3
  54. package/dist/esm/features/session_replay/shared/utils.js +5 -6
  55. package/dist/esm/features/session_trace/instrument/index.js +1 -1
  56. package/dist/esm/features/soft_navigations/aggregate/ajax-node.js +3 -3
  57. package/dist/esm/features/soft_navigations/aggregate/bel-node.js +3 -3
  58. package/dist/esm/features/soft_navigations/aggregate/index.js +7 -7
  59. package/dist/esm/features/soft_navigations/aggregate/initial-page-load-interaction.js +4 -6
  60. package/dist/esm/features/soft_navigations/aggregate/interaction.js +5 -6
  61. package/dist/esm/features/spa/aggregate/index.js +1 -1
  62. package/dist/esm/features/spa/aggregate/interaction.js +1 -2
  63. package/dist/esm/features/spa/aggregate/serializer.js +8 -11
  64. package/dist/esm/features/utils/aggregate-base.js +1 -1
  65. package/dist/esm/features/utils/feature-gates.js +2 -3
  66. package/dist/esm/features/utils/instrument-base.js +4 -4
  67. package/dist/esm/loaders/agent.js +1 -1
  68. package/dist/esm/loaders/api/api.js +1 -11
  69. package/dist/esm/loaders/configure/configure.js +10 -10
  70. package/dist/esm/loaders/features/enabled-features.js +2 -6
  71. package/dist/esm/loaders/micro-agent.js +1 -1
  72. package/dist/tsconfig.tsbuildinfo +1 -1
  73. package/dist/types/common/config/info.d.ts +2 -3
  74. package/dist/types/common/config/info.d.ts.map +1 -1
  75. package/dist/types/common/config/init.d.ts +1 -3
  76. package/dist/types/common/config/init.d.ts.map +1 -1
  77. package/dist/types/common/config/loader-config.d.ts +1 -2
  78. package/dist/types/common/config/loader-config.d.ts.map +1 -1
  79. package/dist/types/common/config/runtime.d.ts +1 -2
  80. package/dist/types/common/config/runtime.d.ts.map +1 -1
  81. package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
  82. package/dist/types/common/serialize/bel-serializer.d.ts +1 -1
  83. package/dist/types/common/serialize/bel-serializer.d.ts.map +1 -1
  84. package/dist/types/common/timing/time-keeper.d.ts +1 -1
  85. package/dist/types/common/timing/time-keeper.d.ts.map +1 -1
  86. package/dist/types/features/ajax/instrument/distributed-tracing.d.ts +3 -4
  87. package/dist/types/features/ajax/instrument/distributed-tracing.d.ts.map +1 -1
  88. package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
  89. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  90. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  91. package/dist/types/features/session_replay/shared/utils.d.ts +2 -2
  92. package/dist/types/features/session_replay/shared/utils.d.ts.map +1 -1
  93. package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts +1 -1
  94. package/dist/types/features/soft_navigations/aggregate/ajax-node.d.ts.map +1 -1
  95. package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts +3 -2
  96. package/dist/types/features/soft_navigations/aggregate/bel-node.d.ts.map +1 -1
  97. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  98. package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts +1 -1
  99. package/dist/types/features/soft_navigations/aggregate/initial-page-load-interaction.d.ts.map +1 -1
  100. package/dist/types/features/soft_navigations/aggregate/interaction.d.ts +1 -1
  101. package/dist/types/features/soft_navigations/aggregate/interaction.d.ts.map +1 -1
  102. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  103. package/dist/types/features/spa/aggregate/interaction.d.ts.map +1 -1
  104. package/dist/types/features/spa/aggregate/serializer.d.ts +4 -2
  105. package/dist/types/features/spa/aggregate/serializer.d.ts.map +1 -1
  106. package/dist/types/features/utils/feature-gates.d.ts +1 -1
  107. package/dist/types/features/utils/feature-gates.d.ts.map +1 -1
  108. package/dist/types/loaders/api/api.d.ts.map +1 -1
  109. package/dist/types/loaders/features/enabled-features.d.ts +1 -1
  110. package/dist/types/loaders/features/enabled-features.d.ts.map +1 -1
  111. package/package.json +1 -1
  112. package/src/common/config/info.js +6 -18
  113. package/src/common/config/init.js +3 -33
  114. package/src/common/config/loader-config.js +3 -15
  115. package/src/common/config/runtime.js +11 -28
  116. package/src/common/event-emitter/contextual-ee.js +1 -2
  117. package/src/common/serialize/bel-serializer.js +1 -3
  118. package/src/common/timing/time-keeper.js +2 -3
  119. package/src/features/ajax/aggregate/index.js +1 -1
  120. package/src/features/ajax/instrument/distributed-tracing.js +10 -29
  121. package/src/features/ajax/instrument/index.js +1 -1
  122. package/src/features/logging/aggregate/index.js +1 -1
  123. package/src/features/page_view_event/aggregate/index.js +2 -2
  124. package/src/features/page_view_timing/aggregate/index.js +1 -1
  125. package/src/features/session_replay/aggregate/index.js +1 -1
  126. package/src/features/session_replay/instrument/index.js +3 -3
  127. package/src/features/session_replay/shared/utils.js +5 -6
  128. package/src/features/session_trace/instrument/index.js +1 -1
  129. package/src/features/soft_navigations/aggregate/ajax-node.js +3 -3
  130. package/src/features/soft_navigations/aggregate/bel-node.js +3 -3
  131. package/src/features/soft_navigations/aggregate/index.js +7 -7
  132. package/src/features/soft_navigations/aggregate/initial-page-load-interaction.js +4 -6
  133. package/src/features/soft_navigations/aggregate/interaction.js +5 -6
  134. package/src/features/spa/aggregate/index.js +1 -1
  135. package/src/features/spa/aggregate/interaction.js +1 -2
  136. package/src/features/spa/aggregate/serializer.js +8 -11
  137. package/src/features/utils/aggregate-base.js +1 -1
  138. package/src/features/utils/feature-gates.js +2 -3
  139. package/src/features/utils/instrument-base.js +4 -4
  140. package/src/loaders/agent.js +1 -1
  141. package/src/loaders/api/api.js +3 -5
  142. package/src/loaders/configure/configure.js +10 -10
  143. package/src/loaders/features/enabled-features.js +2 -7
  144. package/src/loaders/micro-agent.js +1 -1
  145. package/dist/cjs/common/context/shared-context.js +0 -31
  146. package/dist/esm/common/context/shared-context.js +0 -23
  147. package/dist/types/common/context/shared-context.d.ts +0 -5
  148. package/dist/types/common/context/shared-context.d.ts.map +0 -1
  149. package/src/common/config/__mocks__/info.js +0 -7
  150. package/src/common/config/__mocks__/init.js +0 -7
  151. package/src/common/config/__mocks__/loader-config.js +0 -6
  152. package/src/common/config/__mocks__/runtime.js +0 -6
  153. package/src/common/context/__mocks__/shared-context.js +0 -15
  154. package/src/common/context/shared-context.js +0 -25
@@ -2,22 +2,17 @@
2
2
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import { getConfiguration, getConfigurationValue } from '../../../common/config/init';
6
- import { getLoaderConfig } from '../../../common/config/loader-config';
7
5
  import { generateSpanId, generateTraceId } from '../../../common/ids/unique-id';
8
6
  import { parseUrl } from '../../../common/url/parse-url';
9
7
  import { globalScope } from '../../../common/constants/runtime';
10
8
  import { stringify } from '../../../common/util/stringify';
11
9
  export class DT {
12
- constructor(agentIdentifier) {
13
- this.agentIdentifier = agentIdentifier;
10
+ constructor(agentRef) {
11
+ this.agentRef = agentRef;
14
12
  }
15
13
  generateTracePayload(parsedOrigin) {
16
- if (!this.shouldGenerateTrace(parsedOrigin)) {
17
- return null;
18
- }
19
- var loaderConfig = getLoaderConfig(this.agentIdentifier);
20
- if (!loaderConfig) {
14
+ const loaderConfig = this.agentRef.loader_config;
15
+ if (!this.shouldGenerateTrace(parsedOrigin) || !loaderConfig) {
21
16
  return null;
22
17
  }
23
18
  var accountId = (loaderConfig.accountID || '').toString() || null;
@@ -79,18 +74,14 @@ export class DT {
79
74
  // return true if DT is enabled and the origin is allowed, either by being
80
75
  // same-origin, or included in the allowed list
81
76
  shouldGenerateTrace(parsedOrigin) {
82
- return this.isDtEnabled() && this.isAllowedOrigin(parsedOrigin);
77
+ return this.agentRef.init?.distributed_tracing && this.isAllowedOrigin(parsedOrigin);
83
78
  }
84
79
  isAllowedOrigin(parsedOrigin) {
85
80
  var allowed = false;
86
- var dtConfig = {};
87
- var dt = getConfigurationValue(this.agentIdentifier, 'distributed_tracing');
88
- if (dt) {
89
- dtConfig = getConfiguration(this.agentIdentifier).distributed_tracing;
90
- }
81
+ const dtConfig = this.agentRef.init?.distributed_tracing;
91
82
  if (parsedOrigin.sameOrigin) {
92
83
  allowed = true;
93
- } else if (dtConfig.allowed_origins instanceof Array) {
84
+ } else if (dtConfig?.allowed_origins instanceof Array) {
94
85
  for (var i = 0; i < dtConfig.allowed_origins.length; i++) {
95
86
  var allowedOrigin = parseUrl(dtConfig.allowed_origins[i]);
96
87
  if (parsedOrigin.hostname === allowedOrigin.hostname && parsedOrigin.protocol === allowedOrigin.protocol && parsedOrigin.port === allowedOrigin.port) {
@@ -101,31 +92,24 @@ export class DT {
101
92
  }
102
93
  return allowed;
103
94
  }
104
- isDtEnabled() {
105
- var dt = getConfigurationValue(this.agentIdentifier, 'distributed_tracing');
106
- if (dt) {
107
- return !!dt.enabled;
108
- }
109
- return false;
110
- }
111
95
 
112
96
  // exclude the newrelic header for same-origin calls
113
97
  excludeNewrelicHeader() {
114
- var dt = getConfigurationValue(this.agentIdentifier, 'distributed_tracing');
98
+ var dt = this.agentRef.init?.distributed_tracing;
115
99
  if (dt) {
116
100
  return !!dt.exclude_newrelic_header;
117
101
  }
118
102
  return false;
119
103
  }
120
104
  useNewrelicHeaderForCors() {
121
- var dt = getConfigurationValue(this.agentIdentifier, 'distributed_tracing');
105
+ var dt = this.agentRef.init?.distributed_tracing;
122
106
  if (dt) {
123
107
  return dt.cors_use_newrelic_header !== false;
124
108
  }
125
109
  return false;
126
110
  }
127
111
  useTraceContextHeadersForCors() {
128
- var dt = getConfigurationValue(this.agentIdentifier, 'distributed_tracing');
112
+ var dt = this.agentRef.init?.distributed_tracing;
129
113
  if (dt) {
130
114
  return !!dt.cors_use_tracecontext_headers;
131
115
  }
@@ -28,7 +28,7 @@ export class Instrument extends InstrumentBase {
28
28
  static featureName = FEATURE_NAME;
29
29
  constructor(agentRef, auto = true) {
30
30
  super(agentRef, FEATURE_NAME, auto);
31
- this.dt = new DT(agentRef.agentIdentifier);
31
+ this.dt = new DT(agentRef);
32
32
  this.handler = (type, args, ctx, group) => handle(type, args, ctx, group, this.ee);
33
33
 
34
34
  // this is a best (but imperfect) effort at capturing AJAX calls that may have fired before the agent was instantiated
@@ -19,7 +19,7 @@ export class Aggregate extends AggregateBase {
19
19
  static featureName = FEATURE_NAME;
20
20
  constructor(agentRef) {
21
21
  super(agentRef, FEATURE_NAME);
22
- this.isSessionTrackingEnabled = canEnableSessionTracking(this.agentIdentifier) && this.agentRef.runtime.session;
22
+ this.isSessionTrackingEnabled = canEnableSessionTracking(agentRef.init) && agentRef.runtime.session;
23
23
 
24
24
  // The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
25
25
  this.ee.on(SESSION_EVENTS.RESET, () => {
@@ -30,11 +30,11 @@ export class Aggregate extends AggregateBase {
30
30
  registerHandler('send-rum', (customAttibutes, target) => {
31
31
  this.sendRum(customAttibutes, target);
32
32
  }, this.featureName, this.ee);
33
- if (!isValid(agentRef.agentIdentifier)) {
33
+ if (!isValid(agentRef.info)) {
34
34
  this.ee.abort();
35
35
  return warn(43);
36
36
  }
37
- agentRef.runtime.timeKeeper = new TimeKeeper(agentRef.agentIdentifier);
37
+ agentRef.runtime.timeKeeper = new TimeKeeper(agentRef.runtime.session);
38
38
  if (isBrowserScope) {
39
39
  timeToFirstByte.subscribe(({
40
40
  value,
@@ -133,7 +133,7 @@ export class Aggregate extends AggregateBase {
133
133
 
134
134
  // serialize array of timing data
135
135
  serializer(eventBuffer) {
136
- var addString = getAddStringContext(this.agentIdentifier);
136
+ var addString = getAddStringContext(this.agentRef.runtime.obfuscator);
137
137
  var payload = 'bel.6;';
138
138
  for (var i = 0; i < eventBuffer.length; i++) {
139
139
  var timing = eventBuffer[i];
@@ -45,7 +45,7 @@ export class Aggregate extends AggregateBase {
45
45
  this.recorder = args?.recorder;
46
46
  this.errorNoticed = args?.errorNoticed || false;
47
47
  this.harvestOpts.raw = true;
48
- this.isSessionTrackingEnabled = canEnableSessionTracking(this.agentIdentifier) && !!this.agentRef.runtime.session;
48
+ this.isSessionTrackingEnabled = canEnableSessionTracking(agentRef.init) && !!agentRef.runtime.session;
49
49
  this.reportSupportabilityMetric('Config/SessionReplay/Enabled');
50
50
 
51
51
  // The SessionEntity class can emit a message indicating the session was cleared and reset (expiry, inactivity). This feature must abort and never resume if that occurs.
@@ -23,7 +23,7 @@ export class Instrument extends InstrumentBase {
23
23
  try {
24
24
  session = JSON.parse(localStorage.getItem("".concat(PREFIX, "_").concat(DEFAULT_KEY)));
25
25
  } catch (err) {}
26
- if (hasReplayPrerequisite(agentRef.agentIdentifier)) {
26
+ if (hasReplayPrerequisite(agentRef.init)) {
27
27
  this.ee.on(SR_EVENT_EMITTER_TYPES.RECORD, () => this.#apiStartOrRestartReplay());
28
28
  }
29
29
  if (this.#canPreloadRecorder(session)) {
@@ -53,12 +53,12 @@ export class Instrument extends InstrumentBase {
53
53
  // this might be a new session if entity initializes: conservatively start recording if first-time config allows
54
54
  // Note: users with SR enabled, as well as these other configs enabled by-default, will be penalized by the recorder overhead EVEN IF they don't actually have or get
55
55
  // entitlement or sampling decision, or otherwise intentionally opted-in for the feature.
56
- return isPreloadAllowed(this.agentIdentifier);
56
+ return isPreloadAllowed(this.#agentRef.init);
57
57
  } else if (session.sessionReplayMode === MODE.FULL || session.sessionReplayMode === MODE.ERROR) {
58
58
  return true; // existing sessions get to continue recording, regardless of this page's configs or if it has expired (conservatively)
59
59
  } else {
60
60
  // SR mode was OFF but may potentially be turned on if session resets and configs allows the new session to have replay...
61
- return isPreloadAllowed(this.agentIdentifier);
61
+ return isPreloadAllowed(this.#agentRef.init);
62
62
  }
63
63
  }
64
64
  #alreadyStarted = false;
@@ -3,18 +3,17 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { gosNREUMOriginals } from '../../../common/window/nreum';
6
- import { getConfigurationValue } from '../../../common/config/init';
7
6
  import { canEnableSessionTracking } from '../../utils/feature-gates';
8
7
  import { originTime } from '../../../common/constants/runtime';
9
- export function hasReplayPrerequisite(agentId) {
8
+ export function hasReplayPrerequisite(agentInit) {
10
9
  return !!gosNREUMOriginals().o.MO &&
11
10
  // Session Replay cannot work without Mutation Observer
12
- canEnableSessionTracking(agentId) &&
11
+ canEnableSessionTracking(agentInit) &&
13
12
  // requires session tracking to be running (hence "session" replay...)
14
- getConfigurationValue(agentId, 'session_trace.enabled') === true; // Session Replay as of now is tightly coupled with Session Trace in the UI
13
+ agentInit?.session_trace.enabled === true; // Session Replay as of now is tightly coupled with Session Trace in the UI
15
14
  }
16
- export function isPreloadAllowed(agentId) {
17
- return getConfigurationValue(agentId, 'session_replay.preload') === true && hasReplayPrerequisite(agentId);
15
+ export function isPreloadAllowed(agentInit) {
16
+ return agentInit?.session_replay.preload === true && hasReplayPrerequisite(agentInit);
18
17
  }
19
18
  export function buildNRMetaNode(timestamp, timeKeeper) {
20
19
  const correctedTimestamp = timeKeeper.correctAbsoluteTimestamp(timestamp);
@@ -24,7 +24,7 @@ export class Instrument extends InstrumentBase {
24
24
  static featureName = FEATURE_NAME;
25
25
  constructor(agentRef, auto = true) {
26
26
  super(agentRef, FEATURE_NAME, auto);
27
- const canTrackSession = canEnableSessionTracking(this.agentIdentifier);
27
+ const canTrackSession = canEnableSessionTracking(agentRef.init);
28
28
  if (!canTrackSession) {
29
29
  this.deregisterDrain();
30
30
  return;
@@ -6,8 +6,8 @@ import { addCustomAttributes, getAddStringContext, nullable, numeric } from '../
6
6
  import { NODE_TYPE } from '../constants';
7
7
  import { BelNode } from './bel-node';
8
8
  export class AjaxNode extends BelNode {
9
- constructor(agentIdentifier, ajaxEvent) {
10
- super(agentIdentifier);
9
+ constructor(agentRef, ajaxEvent) {
10
+ super(agentRef);
11
11
  this.belType = NODE_TYPE.AJAX;
12
12
  this.method = ajaxEvent.method;
13
13
  this.status = ajaxEvent.status;
@@ -24,7 +24,7 @@ export class AjaxNode extends BelNode {
24
24
  this.end = ajaxEvent.endTime;
25
25
  }
26
26
  serialize(parentStartTimestamp) {
27
- const addString = getAddStringContext(this.agentIdentifier);
27
+ const addString = getAddStringContext(this.obfuscator);
28
28
  const nodeList = [];
29
29
 
30
30
  // IMPORTANT: The order in which addString is called matters and correlates to the order in which string shows up in the harvest payload. Do not re-order the following code.
@@ -12,9 +12,9 @@ export class BelNode {
12
12
  callbackEnd = 0;
13
13
  callbackDuration = 0;
14
14
  nodeId = ++nodesSeen;
15
- constructor(agentIdentifier) {
16
- if (!agentIdentifier) throw new Error('Interaction is missing core attributes');
17
- this.agentIdentifier = agentIdentifier;
15
+ constructor(agentRef) {
16
+ this.obfuscator = agentRef.runtime.obfuscator;
17
+ this.info = agentRef.info;
18
18
  }
19
19
  addChild(child) {
20
20
  this.children.push(child);
@@ -20,7 +20,7 @@ export class Aggregate extends AggregateBase {
20
20
  super(agentRef, FEATURE_NAME);
21
21
  this.interactionsToHarvest = this.events;
22
22
  this.domObserver = domObserver;
23
- this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentRef.agentIdentifier);
23
+ this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentRef);
24
24
  this.initialPageLoadInteraction.onDone.push(() => {
25
25
  // this ensures the .end() method also works with iPL
26
26
  if (agentRef.runtime.session?.isNew) this.initialPageLoadInteraction.customAttributes.isFirstOfSession = true; // mark the hard page load as first of its session
@@ -84,7 +84,7 @@ export class Aggregate extends AggregateBase {
84
84
  if (this.interactionInProgress?.done() === false) return; // current in-progress is blocked from closing, e.g. by 'waitForEnd' api option
85
85
 
86
86
  const oldURL = eventName === INTERACTION_TRIGGERS[3] ? this.latestHistoryUrl : undefined; // see related comment in 'newURL' handler above, 'popstate'
87
- this.interactionInProgress = new Interaction(this.agentIdentifier, eventName, startedAt, this.latestRouteSetByApi, oldURL);
87
+ this.interactionInProgress = new Interaction(this.agentRef, eventName, startedAt, this.latestRouteSetByApi, oldURL);
88
88
  if (eventName === INTERACTION_TRIGGERS[0]) {
89
89
  // 'click'
90
90
  const sourceElemText = getActionText(sourceElem);
@@ -154,15 +154,15 @@ export class Aggregate extends AggregateBase {
154
154
  // no interaction was happening when this ajax started, so give it back to Ajax feature for processing
155
155
  handle('returnAjax', [event], undefined, FEATURE_NAMES.ajax, this.ee);
156
156
  } else {
157
- if (associatedInteraction.status === INTERACTION_STATUS.FIN) processAjax(this.agentIdentifier, event, associatedInteraction); // tack ajax onto the ixn object awaiting harvest
157
+ if (associatedInteraction.status === INTERACTION_STATUS.FIN) processAjax(this.agentRef, event, associatedInteraction); // tack ajax onto the ixn object awaiting harvest
158
158
  else {
159
159
  // same thing as above, just at a later time -- if the interaction in progress is cancelled, just send the event back to ajax feat unmodified
160
- associatedInteraction.on('finished', () => processAjax(this.agentIdentifier, event, associatedInteraction));
160
+ associatedInteraction.on('finished', () => processAjax(this.agentRef, event, associatedInteraction));
161
161
  associatedInteraction.on('cancelled', () => handle('returnAjax', [event], undefined, FEATURE_NAMES.ajax, this.ee));
162
162
  }
163
163
  }
164
- function processAjax(agentId, event, parentInteraction) {
165
- const newNode = new AjaxNode(agentId, event);
164
+ function processAjax(agent, event, parentInteraction) {
165
+ const newNode = new AjaxNode(agent, event);
166
166
  parentInteraction.addChild(newNode);
167
167
  }
168
168
  }
@@ -201,7 +201,7 @@ export class Aggregate extends AggregateBase {
201
201
  if (this.associatedInteraction?.trigger === IPL_TRIGGER_NAME) this.associatedInteraction = null; // the api get-interaction method cannot target IPL
202
202
  if (!this.associatedInteraction) {
203
203
  // This new api-driven interaction will be the target of any subsequent .interaction() call, until it is closed by EITHER .end() OR the regular seenHistoryAndDomChange process.
204
- this.associatedInteraction = thisClass.interactionInProgress = new Interaction(thisClass.agentIdentifier, API_TRIGGER_NAME, time, thisClass.latestRouteSetByApi);
204
+ this.associatedInteraction = thisClass.interactionInProgress = new Interaction(thisClass.agentRef, API_TRIGGER_NAME, time, thisClass.latestRouteSetByApi);
205
205
  thisClass.domObserver.observe(document.body, {
206
206
  attributes: true,
207
207
  childList: true,
@@ -7,14 +7,12 @@ import { Interaction } from './interaction';
7
7
  import { numeric } from '../../../common/serialize/bel-serializer';
8
8
  import { firstPaint } from '../../../common/vitals/first-paint';
9
9
  import { firstContentfulPaint } from '../../../common/vitals/first-contentful-paint';
10
- import { getInfo } from '../../../common/config/info';
11
10
  import { IPL_TRIGGER_NAME } from '../constants';
12
11
  export class InitialPageLoadInteraction extends Interaction {
13
- constructor(agentIdentifier) {
14
- super(agentIdentifier, IPL_TRIGGER_NAME, 0, null);
15
- const agentInfo = getInfo(agentIdentifier);
16
- this.queueTime = agentInfo.queueTime;
17
- this.appTime = agentInfo.applicationTime;
12
+ constructor(agentRef) {
13
+ super(agentRef, IPL_TRIGGER_NAME, 0, null);
14
+ this.queueTime = agentRef.info.queueTime;
15
+ this.appTime = agentRef.info.applicationTime;
18
16
  }
19
17
  get firstPaint() {
20
18
  return firstPaint.current.value;
@@ -2,7 +2,6 @@
2
2
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import { getInfo } from '../../../common/config/info';
6
5
  import { globalScope, initialLocation } from '../../../common/constants/runtime';
7
6
  import { generateUuid } from '../../../common/ids/unique-id';
8
7
  import { addCustomAttributes, getAddStringContext, nullable, numeric } from '../../../common/serialize/bel-serializer';
@@ -31,8 +30,8 @@ export class Interaction extends BelNode {
31
30
  keepOpenUntilEndApi = false;
32
31
  onDone = [];
33
32
  cancellationTimer;
34
- constructor(agentIdentifier, uiEvent, uiEventTimestamp, currentRouteKnown, currentUrl) {
35
- super(agentIdentifier);
33
+ constructor(agentRef, uiEvent, uiEventTimestamp, currentRouteKnown, currentUrl) {
34
+ super(agentRef);
36
35
  this.belType = NODE_TYPE.INTERACTION;
37
36
  this.trigger = uiEvent;
38
37
  this.start = uiEventTimestamp;
@@ -74,7 +73,7 @@ export class Interaction extends BelNode {
74
73
  clearTimeout(this.cancellationTimer);
75
74
  this.end = Math.max(this.domTimestamp, this.historyTimestamp, customEndTime);
76
75
  this.customAttributes = {
77
- ...getInfo(this.agentIdentifier).jsAttributes,
76
+ ...this.info.jsAttributes,
78
77
  ...this.customAttributes
79
78
  }; // attrs specific to this interaction should have precedence over the general custom attrs
80
79
  this.status = INTERACTION_STATUS.FIN;
@@ -109,7 +108,7 @@ export class Interaction extends BelNode {
109
108
  get navTiming() {}
110
109
  serialize(firstStartTimeOfPayload) {
111
110
  const isFirstIxnOfPayload = firstStartTimeOfPayload === undefined;
112
- const addString = getAddStringContext(this.agentIdentifier);
111
+ const addString = getAddStringContext(this.obfuscator);
113
112
  const nodeList = [];
114
113
  let ixnType;
115
114
  if (this.trigger === IPL_TRIGGER_NAME) ixnType = INTERACTION_TYPE.INITIAL_PAGE_LOAD;else if (this.newURL !== this.oldURL) ixnType = INTERACTION_TYPE.ROUTE_CHANGE;else ixnType = INTERACTION_TYPE.UNSPECIFIED;
@@ -127,7 +126,7 @@ export class Interaction extends BelNode {
127
126
  // not relative
128
127
  addString(this.trigger), addString(cleanURL(this.initialPageURL, true)), addString(cleanURL(this.oldURL, true)), addString(cleanURL(this.newURL, true)), addString(this.customName), ixnType, nullable(this.queueTime, numeric, true) + nullable(this.appTime, numeric, true) + nullable(this.oldRoute, addString, true) + nullable(this.newRoute, addString, true) + addString(this.id), addString(this.nodeId), nullable(this.firstPaint, numeric, true) + nullable(this.firstContentfulPaint, numeric)];
129
128
  const allAttachedNodes = addCustomAttributes(this.customAttributes || {}, addString); // start with all custom attributes
130
- if (getInfo(this.agentIdentifier).atts) allAttachedNodes.push('a,' + addString(getInfo(this.agentIdentifier).atts)); // add apm provided attributes
129
+ if (this.info.atts) allAttachedNodes.push('a,' + addString(this.info.atts)); // add apm provided attributes
131
130
  /* Querypack encoder+decoder quirkiness:
132
131
  - If first ixn node of payload is being processed, its children's start time must be offset by this node's start. (firstStartTime should be undefined.)
133
132
  - Else for subsequent ixns in the same payload, we go back to using that first ixn node's start to offset their children's start. */
@@ -60,7 +60,7 @@ export class Aggregate extends AggregateBase {
60
60
  // The below feature flag is used to disable the SPA ajax fix for specific customers, see https://new-relic.atlassian.net/browse/NR-172169
61
61
  disableSpaFix: (agentRef.init.feature_flags || []).indexOf('disable-spa-fix') > -1
62
62
  };
63
- this.spaSerializerClass = new Serializer(this);
63
+ this.spaSerializerClass = new Serializer(agentRef);
64
64
  const classThis = this;
65
65
  const baseEE = ee.get(agentRef.agentIdentifier); // <-- parent baseEE
66
66
  const mutationEE = baseEE.get('mutation');
@@ -2,7 +2,6 @@
2
2
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
-
6
5
  import { initialLocation } from '../../../common/constants/runtime';
7
6
  import { gosNREUMOriginals } from '../../../common/window/nreum';
8
7
  import { InteractionNode } from './interaction-node';
@@ -80,7 +79,7 @@ InteractionPrototype.finish = function finishInteraction() {
80
79
  if (this.onFinished) {
81
80
  this.onFinished(this);
82
81
  }
83
- Object.entries(interaction.agentRef.info?.jsAttributes || {}).forEach(([attr, value]) => {
82
+ Object.entries(interaction.agentRef.info.jsAttributes || {}).forEach(([attr, value]) => {
84
83
  if (!(attr in customAttrs)) customAttrs[attr] = value;
85
84
  });
86
85
  root.end = endTimestamp;
@@ -4,11 +4,10 @@
4
4
  */
5
5
  import { cleanURL } from '../../../common/url/clean-url';
6
6
  import { nullable, numeric, getAddStringContext, addCustomAttributes } from '../../../common/serialize/bel-serializer';
7
- import { SharedContext } from '../../../common/context/shared-context';
8
- import { getInfo } from '../../../common/config/info';
9
- export class Serializer extends SharedContext {
10
- constructor(parent) {
11
- super(parent);
7
+ export class Serializer {
8
+ constructor(agentRef) {
9
+ this.obfuscator = agentRef.runtime.obfuscator;
10
+ this.info = agentRef.info;
12
11
 
13
12
  /**
14
13
  * This variable is used to calculate an interactions ending offset when the
@@ -20,19 +19,17 @@ export class Serializer extends SharedContext {
20
19
  this.firstTimestamp = undefined;
21
20
  }
22
21
  serializeMultiple(interactions, offset, navTiming) {
23
- const info = getInfo(this.sharedContext.agentIdentifier);
24
- var addString = getAddStringContext(this.sharedContext.agentIdentifier);
22
+ var addString = getAddStringContext(this.obfuscator);
25
23
  var serialized = 'bel.7';
26
24
  interactions.forEach(interaction => {
27
- serialized += ';' + this.serializeInteraction(interaction.root, offset, navTiming, interaction.routeChange, addString, info);
25
+ serialized += ';' + this.serializeInteraction(interaction.root, offset, navTiming, interaction.routeChange, addString, this.info);
28
26
  });
29
27
  this.firstTimestamp = undefined;
30
28
  return serialized;
31
29
  }
32
30
  serializeSingle(root, offset, navTiming, isRouteChange) {
33
- const info = getInfo(this.sharedContext.agentIdentifier);
34
- var addString = getAddStringContext(this.sharedContext.agentIdentifier);
35
- var serialized = 'bel.7;' + this.serializeInteraction(root, offset, navTiming, isRouteChange, addString, info);
31
+ var addString = getAddStringContext(this.obfuscator);
32
+ var serialized = 'bel.7;' + this.serializeInteraction(root, offset, navTiming, isRouteChange, addString, this.info);
36
33
  this.firstTimestamp = undefined;
37
34
  return serialized;
38
35
  }
@@ -161,7 +161,7 @@ export class AggregateBase extends FeatureBase {
161
161
  */
162
162
  checkConfiguration(existingAgent) {
163
163
  // NOTE: This check has to happen at aggregator load time
164
- if (!isValid(this.agentIdentifier)) {
164
+ if (!isValid(existingAgent.info)) {
165
165
  const cdn = gosCDN();
166
166
  let jsAttributes = {
167
167
  ...cdn.info?.jsAttributes
@@ -2,7 +2,6 @@
2
2
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- import { getConfigurationValue } from '../../common/config/init';
6
5
  import { isBrowserScope } from '../../common/constants/runtime';
7
6
 
8
7
  /**
@@ -10,6 +9,6 @@ import { isBrowserScope } from '../../common/constants/runtime';
10
9
  * @param {string} agentId
11
10
  * @returns {boolean}
12
11
  */
13
- export const canEnableSessionTracking = agentId => {
14
- return isBrowserScope && getConfigurationValue(agentId, 'privacy.cookies_enabled') === true;
12
+ export const canEnableSessionTracking = agentInit => {
13
+ return isBrowserScope && agentInit?.privacy.cookies_enabled === true;
15
14
  };
@@ -81,7 +81,7 @@ export class InstrumentBase extends FeatureBase {
81
81
  const importLater = async () => {
82
82
  let session;
83
83
  try {
84
- if (canEnableSessionTracking(this.agentIdentifier)) {
84
+ if (canEnableSessionTracking(agentRef.init)) {
85
85
  // would require some setup before certain features start
86
86
  const {
87
87
  setupAgentSession
@@ -99,7 +99,7 @@ export class InstrumentBase extends FeatureBase {
99
99
  * it's only responsible for aborting its one specific feature, rather than all.
100
100
  */
101
101
  try {
102
- if (!this.#shouldImportAgg(this.featureName, session)) {
102
+ if (!this.#shouldImportAgg(this.featureName, session, agentRef.init)) {
103
103
  drain(this.agentIdentifier, this.featureName);
104
104
  loadedSuccessfully(false); // aggregate module isn't loaded at all
105
105
  return;
@@ -134,11 +134,11 @@ export class InstrumentBase extends FeatureBase {
134
134
  * @param {import('../../common/session/session-entity').SessionEntity} session
135
135
  * @returns
136
136
  */
137
- #shouldImportAgg(featureName, session) {
137
+ #shouldImportAgg(featureName, session, agentInit) {
138
138
  switch (featureName) {
139
139
  case FEATURE_NAMES.sessionReplay:
140
140
  // the session manager must be initialized successfully for Replay & Trace features
141
- return hasReplayPrerequisite(this.agentIdentifier) && !!session;
141
+ return hasReplayPrerequisite(agentInit) && !!session;
142
142
  case FEATURE_NAMES.sessionTrace:
143
143
  return !!session;
144
144
  default:
@@ -73,7 +73,7 @@ export class Agent extends AgentBase {
73
73
  run() {
74
74
  // Attempt to initialize all the requested features (sequentially in prio order & synchronously), with any failure aborting the whole process.
75
75
  try {
76
- const enabledFeatures = getEnabledFeatures(this.agentIdentifier);
76
+ const enabledFeatures = getEnabledFeatures(this.init);
77
77
  const featuresToStart = [...this.desiredFeatures];
78
78
  featuresToStart.sort((a, b) => featurePriority[a.featureName] - featurePriority[b.featureName]);
79
79
  featuresToStart.forEach(InstrumentCtor => {
@@ -118,17 +118,7 @@ export function setAPI(agent, forceDrain) {
118
118
  */
119
119
  function appendJsAttribute(key, value, apiName, addToBrowserStorage) {
120
120
  const currentInfo = agent.info;
121
- if (value === null) {
122
- delete currentInfo.jsAttributes[key];
123
- } else {
124
- agent.info = {
125
- ...agent.info,
126
- jsAttributes: {
127
- ...currentInfo.jsAttributes,
128
- [key]: value
129
- }
130
- };
131
- }
121
+ if (value === null) delete currentInfo.jsAttributes[key];else currentInfo.jsAttributes[key] = value;
132
122
  return apiCall(prefix, apiName, true, !!addToBrowserStorage || value === null ? 'session' : undefined)(key, value);
133
123
  }
134
124
  agent.setCustomAttribute = function (name, value, persistAttribute = false) {
@@ -4,15 +4,15 @@
4
4
  */
5
5
  import { setAPI, setTopLevelCallers } from '../api/api';
6
6
  import { addToNREUM, gosCDN } from '../../common/window/nreum';
7
- import { setInfo } from '../../common/config/info';
8
- import { setConfiguration } from '../../common/config/init';
9
- import { setLoaderConfig } from '../../common/config/loader-config';
10
- import { setRuntime } from '../../common/config/runtime';
7
+ import { mergeInfo } from '../../common/config/info';
8
+ import { mergeInit } from '../../common/config/init';
9
+ import { mergeRuntime } from '../../common/config/runtime';
11
10
  import { activatedFeatures } from '../../common/util/feature-flags';
12
11
  import { isWorkerScope } from '../../common/constants/runtime';
13
12
  import { redefinePublicPath } from './public-path';
14
13
  import { ee } from '../../common/event-emitter/contextual-ee';
15
14
  import { dispatchGlobalEvent } from '../../common/dispatch/global-event';
15
+ import { mergeLoaderConfig } from '../../common/config/loader-config';
16
16
  const alreadySetOnce = new Set(); // the configure() function can run multiple times in agent lifecycle for different agents
17
17
 
18
18
  /**
@@ -28,23 +28,22 @@ export function configure(agent, opts = {}, loaderType, forceDrain) {
28
28
  runtime = {},
29
29
  exposed = true
30
30
  } = opts;
31
- runtime.loaderType = loaderType;
32
- const nr = gosCDN();
33
31
  if (!info) {
32
+ const nr = gosCDN();
34
33
  init = nr.init;
35
34
  info = nr.info;
36
35
  // eslint-disable-next-line camelcase
37
36
  loader_config = nr.loader_config;
38
37
  }
39
- setConfiguration(agent.agentIdentifier, init || {});
38
+ agent.init = mergeInit(init || {});
40
39
  // eslint-disable-next-line camelcase
41
- setLoaderConfig(agent.agentIdentifier, loader_config || {});
40
+ agent.loader_config = mergeLoaderConfig(loader_config || {});
42
41
  info.jsAttributes ??= {};
43
42
  if (isWorkerScope) {
44
43
  // add a default attr to all worker payloads
45
44
  info.jsAttributes.isWorker = true;
46
45
  }
47
- setInfo(agent.agentIdentifier, info);
46
+ agent.info = mergeInfo(info);
48
47
  const updatedInit = agent.init;
49
48
  const internalTrafficList = [info.beacon, info.errorBeacon];
50
49
  if (!alreadySetOnce.has(agent.agentIdentifier)) {
@@ -61,7 +60,8 @@ export function configure(agent, opts = {}, loaderType, forceDrain) {
61
60
  }
62
61
  runtime.denyList = [...(updatedInit.ajax.deny_list || []), ...(updatedInit.ajax.block_internal ? internalTrafficList : [])];
63
62
  runtime.ptid = agent.agentIdentifier;
64
- setRuntime(agent.agentIdentifier, runtime);
63
+ runtime.loaderType = loaderType;
64
+ agent.runtime = mergeRuntime(runtime);
65
65
  if (!alreadySetOnce.has(agent.agentIdentifier)) {
66
66
  agent.ee = ee.get(agent.agentIdentifier);
67
67
  agent.exposed = exposed;
@@ -3,15 +3,11 @@
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
5
  import { FEATURE_NAMES } from './features';
6
- import { getConfigurationValue } from '../../common/config/init';
7
6
  const featureNames = Object.values(FEATURE_NAMES);
8
- function isEnabled(name, agentIdentifier) {
9
- return getConfigurationValue(agentIdentifier, "".concat(name, ".enabled")) === true;
10
- }
11
- export function getEnabledFeatures(agentIdentifier) {
7
+ export function getEnabledFeatures(agentInit) {
12
8
  const enabledFeatures = {};
13
9
  featureNames.forEach(featureName => {
14
- enabledFeatures[featureName] = isEnabled(featureName, agentIdentifier);
10
+ enabledFeatures[featureName] = !!agentInit[featureName]?.enabled;
15
11
  });
16
12
  return enabledFeatures;
17
13
  }
@@ -44,7 +44,7 @@ export class MicroAgent extends MicroAgentBase {
44
44
  try {
45
45
  if (featureNames === undefined || Array.isArray(featureNames) && featureNames.length === 0) featureNames = nonAutoFeatures;else if (typeof featureNames === 'string') featureNames = [featureNames];
46
46
  if (featureNames.some(f => !nonAutoFeatures.includes(f))) warn(37, nonAutoFeatures);
47
- const enabledFeatures = getEnabledFeatures(this.agentIdentifier);
47
+ const enabledFeatures = getEnabledFeatures(this.init);
48
48
  try {
49
49
  // a biproduct of doing this is that the "session manager" is automatically handled through importing this feature
50
50
  this.features.page_view_event = new PVE(this);