@newrelic/browser-agent 1.285.0 → 1.287.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 (180) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +6 -0
  3. package/dist/cjs/common/config/init-types.js +96 -0
  4. package/dist/cjs/common/config/init.js +9 -79
  5. package/dist/cjs/common/config/runtime.js +7 -6
  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/dom/selector-path.js +1 -1
  9. package/dist/cjs/common/harvest/harvester.js +3 -3
  10. package/dist/cjs/common/util/feature-flags.js +6 -6
  11. package/dist/cjs/common/util/target.js +34 -0
  12. package/dist/cjs/features/ajax/aggregate/index.js +2 -1
  13. package/dist/cjs/features/generic_events/aggregate/index.js +10 -6
  14. package/dist/cjs/features/jserrors/aggregate/index.js +44 -22
  15. package/dist/cjs/features/logging/aggregate/index.js +17 -11
  16. package/dist/cjs/features/logging/shared/utils.js +3 -2
  17. package/dist/cjs/features/metrics/aggregate/index.js +6 -4
  18. package/dist/cjs/features/page_view_event/aggregate/index.js +60 -11
  19. package/dist/cjs/features/page_view_event/instrument/index.js +4 -0
  20. package/dist/cjs/features/session_replay/aggregate/index.js +8 -6
  21. package/dist/cjs/features/session_replay/instrument/index.js +1 -1
  22. package/dist/cjs/features/session_replay/shared/recorder-events.js +4 -2
  23. package/dist/cjs/features/session_replay/shared/recorder.js +17 -11
  24. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +4 -3
  25. package/dist/cjs/features/soft_navigations/aggregate/index.js +12 -2
  26. package/dist/cjs/features/spa/aggregate/index.js +3 -3
  27. package/dist/cjs/features/spa/aggregate/interaction.js +6 -9
  28. package/dist/cjs/features/utils/aggregate-base.js +51 -24
  29. package/dist/cjs/features/utils/entity-manager.js +47 -0
  30. package/dist/cjs/features/utils/event-store-manager.js +79 -54
  31. package/dist/cjs/features/utils/nr1-debugger.js +1 -1
  32. package/dist/cjs/interfaces/registered-entity.js +114 -0
  33. package/dist/cjs/loaders/agent-base.js +1 -1
  34. package/dist/cjs/loaders/agent.js +3 -1
  35. package/dist/cjs/loaders/api/api-methods.js +1 -1
  36. package/dist/cjs/loaders/api/api.js +97 -69
  37. package/dist/cjs/loaders/api/apiAsync.js +19 -22
  38. package/dist/cjs/loaders/api/register-api-types.js +35 -0
  39. package/dist/cjs/loaders/api/register-api.js +165 -0
  40. package/dist/cjs/loaders/configure/configure.js +12 -15
  41. package/dist/cjs/loaders/micro-agent-base.js +17 -1
  42. package/dist/cjs/loaders/micro-agent.js +4 -1
  43. package/dist/esm/common/config/init-types.js +92 -0
  44. package/dist/esm/common/config/init.js +9 -79
  45. package/dist/esm/common/config/runtime.js +7 -6
  46. package/dist/esm/common/constants/env.cdn.js +1 -1
  47. package/dist/esm/common/constants/env.npm.js +1 -1
  48. package/dist/esm/common/dom/selector-path.js +1 -1
  49. package/dist/esm/common/harvest/harvester.js +3 -3
  50. package/dist/esm/common/util/feature-flags.js +6 -6
  51. package/dist/esm/common/util/target.js +27 -0
  52. package/dist/esm/features/ajax/aggregate/index.js +2 -1
  53. package/dist/esm/features/generic_events/aggregate/index.js +10 -6
  54. package/dist/esm/features/jserrors/aggregate/index.js +44 -22
  55. package/dist/esm/features/logging/aggregate/index.js +17 -11
  56. package/dist/esm/features/logging/shared/utils.js +3 -2
  57. package/dist/esm/features/metrics/aggregate/index.js +6 -4
  58. package/dist/esm/features/page_view_event/aggregate/index.js +60 -11
  59. package/dist/esm/features/page_view_event/instrument/index.js +4 -0
  60. package/dist/esm/features/session_replay/aggregate/index.js +8 -6
  61. package/dist/esm/features/session_replay/instrument/index.js +1 -1
  62. package/dist/esm/features/session_replay/shared/recorder-events.js +4 -2
  63. package/dist/esm/features/session_replay/shared/recorder.js +17 -11
  64. package/dist/esm/features/session_trace/aggregate/trace/storage.js +4 -3
  65. package/dist/esm/features/soft_navigations/aggregate/index.js +12 -2
  66. package/dist/esm/features/spa/aggregate/index.js +3 -3
  67. package/dist/esm/features/spa/aggregate/interaction.js +6 -9
  68. package/dist/esm/features/utils/aggregate-base.js +51 -24
  69. package/dist/esm/features/utils/entity-manager.js +40 -0
  70. package/dist/esm/features/utils/event-store-manager.js +79 -54
  71. package/dist/esm/features/utils/nr1-debugger.js +1 -1
  72. package/dist/esm/interfaces/registered-entity.js +107 -0
  73. package/dist/esm/loaders/agent-base.js +1 -1
  74. package/dist/esm/loaders/agent.js +3 -1
  75. package/dist/esm/loaders/api/api-methods.js +1 -1
  76. package/dist/esm/loaders/api/api.js +95 -67
  77. package/dist/esm/loaders/api/apiAsync.js +14 -17
  78. package/dist/esm/loaders/api/register-api-types.js +33 -0
  79. package/dist/esm/loaders/api/register-api.js +159 -0
  80. package/dist/esm/loaders/configure/configure.js +13 -16
  81. package/dist/esm/loaders/micro-agent-base.js +17 -1
  82. package/dist/esm/loaders/micro-agent.js +4 -1
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/dist/types/common/config/init-types.d.ts +275 -0
  85. package/dist/types/common/config/init-types.d.ts.map +1 -0
  86. package/dist/types/common/config/init.d.ts +1 -262
  87. package/dist/types/common/config/init.d.ts.map +1 -1
  88. package/dist/types/common/config/runtime.d.ts.map +1 -1
  89. package/dist/types/common/dom/selector-path.d.ts.map +1 -1
  90. package/dist/types/common/util/feature-flags.d.ts +1 -1
  91. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  92. package/dist/types/common/util/target.d.ts +18 -0
  93. package/dist/types/common/util/target.d.ts.map +1 -0
  94. package/dist/types/features/ajax/aggregate/index.d.ts +1 -1
  95. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  96. package/dist/types/features/generic_events/aggregate/index.d.ts +2 -1
  97. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  98. package/dist/types/features/jserrors/aggregate/index.d.ts +9 -1
  99. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  100. package/dist/types/features/logging/aggregate/index.d.ts +3 -3
  101. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  102. package/dist/types/features/logging/shared/utils.d.ts +2 -1
  103. package/dist/types/features/logging/shared/utils.d.ts.map +1 -1
  104. package/dist/types/features/metrics/aggregate/index.d.ts +1 -0
  105. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  106. package/dist/types/features/page_view_event/aggregate/index.d.ts +10 -2
  107. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  108. package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
  109. package/dist/types/features/session_replay/aggregate/index.d.ts +2 -11
  110. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  111. package/dist/types/features/session_replay/shared/recorder-events.d.ts +1 -0
  112. package/dist/types/features/session_replay/shared/recorder-events.d.ts.map +1 -1
  113. package/dist/types/features/session_replay/shared/recorder.d.ts +4 -4
  114. package/dist/types/features/session_replay/shared/recorder.d.ts.map +1 -1
  115. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  116. package/dist/types/features/spa/aggregate/interaction.d.ts +3 -4
  117. package/dist/types/features/spa/aggregate/interaction.d.ts.map +1 -1
  118. package/dist/types/features/utils/aggregate-base.d.ts +22 -5
  119. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  120. package/dist/types/features/utils/entity-manager.d.ts +15 -0
  121. package/dist/types/features/utils/entity-manager.d.ts.map +1 -0
  122. package/dist/types/features/utils/event-store-manager.d.ts +48 -24
  123. package/dist/types/features/utils/event-store-manager.d.ts.map +1 -1
  124. package/dist/types/interfaces/registered-entity.d.ts +72 -0
  125. package/dist/types/interfaces/registered-entity.d.ts.map +1 -0
  126. package/dist/types/loaders/agent.d.ts +2 -1
  127. package/dist/types/loaders/agent.d.ts.map +1 -1
  128. package/dist/types/loaders/api/api.d.ts +1 -20
  129. package/dist/types/loaders/api/api.d.ts.map +1 -1
  130. package/dist/types/loaders/api/apiAsync.d.ts +1 -1
  131. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  132. package/dist/types/loaders/api/register-api-types.d.ts +56 -0
  133. package/dist/types/loaders/api/register-api-types.d.ts.map +1 -0
  134. package/dist/types/loaders/api/register-api.d.ts +14 -0
  135. package/dist/types/loaders/api/register-api.d.ts.map +1 -0
  136. package/dist/types/loaders/configure/configure.d.ts +1 -0
  137. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  138. package/dist/types/loaders/micro-agent-base.d.ts +17 -0
  139. package/dist/types/loaders/micro-agent-base.d.ts.map +1 -1
  140. package/dist/types/loaders/micro-agent.d.ts +2 -0
  141. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  142. package/package.json +10 -1
  143. package/src/common/config/init-types.js +92 -0
  144. package/src/common/config/init.js +9 -79
  145. package/src/common/config/runtime.js +7 -6
  146. package/src/common/dom/selector-path.js +1 -3
  147. package/src/common/harvest/harvester.js +3 -3
  148. package/src/common/util/feature-flags.js +6 -6
  149. package/src/common/util/target.js +27 -0
  150. package/src/features/ajax/aggregate/index.js +2 -1
  151. package/src/features/generic_events/aggregate/index.js +8 -6
  152. package/src/features/jserrors/aggregate/index.js +42 -20
  153. package/src/features/logging/aggregate/index.js +14 -10
  154. package/src/features/logging/shared/utils.js +3 -2
  155. package/src/features/metrics/aggregate/index.js +7 -5
  156. package/src/features/page_view_event/aggregate/index.js +50 -8
  157. package/src/features/page_view_event/instrument/index.js +4 -0
  158. package/src/features/session_replay/aggregate/index.js +6 -3
  159. package/src/features/session_replay/instrument/index.js +1 -1
  160. package/src/features/session_replay/shared/recorder-events.js +5 -2
  161. package/src/features/session_replay/shared/recorder.js +17 -11
  162. package/src/features/session_trace/aggregate/trace/storage.js +3 -3
  163. package/src/features/soft_navigations/aggregate/index.js +11 -2
  164. package/src/features/spa/aggregate/index.js +3 -3
  165. package/src/features/spa/aggregate/interaction.js +6 -9
  166. package/src/features/utils/aggregate-base.js +56 -24
  167. package/src/features/utils/entity-manager.js +45 -0
  168. package/src/features/utils/event-store-manager.js +72 -49
  169. package/src/features/utils/nr1-debugger.js +1 -1
  170. package/src/interfaces/registered-entity.js +107 -0
  171. package/src/loaders/agent-base.js +2 -2
  172. package/src/loaders/agent.js +4 -1
  173. package/src/loaders/api/api-methods.js +1 -1
  174. package/src/loaders/api/api.js +94 -62
  175. package/src/loaders/api/apiAsync.js +14 -18
  176. package/src/loaders/api/register-api-types.js +33 -0
  177. package/src/loaders/api/register-api.js +152 -0
  178. package/src/loaders/configure/configure.js +12 -12
  179. package/src/loaders/micro-agent-base.js +18 -2
  180. package/src/loaders/micro-agent.js +5 -1
@@ -14,21 +14,47 @@ var _obfuscate = require("../../common/util/obfuscate");
14
14
  var _features = require("../../loaders/features/features");
15
15
  var _eventStoreManager = require("./event-store-manager");
16
16
  var _harvester = require("../../common/harvest/harvester");
17
+ var _console = require("../../common/util/console");
18
+ var _entityManager = require("./entity-manager");
19
+ var _eventBuffer = require("./event-buffer");
17
20
  var _handle = require("../../common/event-emitter/handle");
18
21
  var _constants = require("../metrics/constants");
22
+ var _eventAggregator = require("../../common/aggregate/event-aggregator");
19
23
  /**
20
24
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
21
25
  * SPDX-License-Identifier: Apache-2.0
22
26
  */
23
27
 
24
28
  class AggregateBase extends _featureBase.FeatureBase {
29
+ /**
30
+ * Create an AggregateBase instance.
31
+ * @param {Object} agentRef The reference to the agent instance.
32
+ * @param {string} featureName The name of the feature creating the instance.
33
+ */
25
34
  constructor(agentRef, featureName) {
26
35
  super(agentRef.agentIdentifier, featureName);
27
36
  this.agentRef = agentRef;
28
37
  this.checkConfiguration(agentRef);
29
38
  this.doOnceForAllAggregate(agentRef);
39
+ this.harvestOpts = {}; // features aggregate classes can define custom opts for when their harvest is called
40
+
41
+ const agentEntityGuid = this.agentRef?.runtime?.appMetadata?.agents?.[0]?.entityGuid;
42
+ if (agentEntityGuid) {
43
+ this.#setupEventStore(agentEntityGuid); // if there's no entity guid, wont dont anything, and will wait for rum flags
44
+ } else {
45
+ this.ee.on('entity-added', entity => {
46
+ this.#setupEventStore(entity.entityGuid);
47
+ });
48
+ }
49
+ }
30
50
 
31
- // This switch needs to be after doOnceForAllAggregate which may new sharedAggregator and reset mainAppKey.
51
+ /**
52
+ * sets up the event store for the feature. It must wait for the entity guid to be available before setting up the event store. This is called once the rum response is received with an entityGuid.
53
+ * @param {string} entityGuid
54
+ * @returns {void}
55
+ */
56
+ #setupEventStore(entityGuid) {
57
+ if (this.events || !entityGuid) return;
32
58
  switch (this.featureName) {
33
59
  // SessionTrace + Replay have their own storage mechanisms.
34
60
  case _features.FEATURE_NAMES.sessionTrace:
@@ -37,16 +63,15 @@ class AggregateBase extends _featureBase.FeatureBase {
37
63
  // Jserror and Metric features uses a singleton EventAggregator instead of a regular EventBuffer.
38
64
  case _features.FEATURE_NAMES.jserrors:
39
65
  case _features.FEATURE_NAMES.metrics:
40
- this.events = agentRef.sharedAggregator;
66
+ this.events = this.agentRef.sharedAggregator ??= new _eventStoreManager.EventStoreManager(this.agentRef, _eventAggregator.EventAggregator, entityGuid, 'shared_aggregator');
41
67
  break;
42
68
  /** All other features get EventBuffer in the ESM by default. Note: PVE is included here, but event buffer will always be empty so future harvests will still not happen by interval or EOL.
43
69
  This was necessary to prevent race cond. issues where the event buffer was checked before the feature could "block" itself.
44
70
  Its easier to just keep an empty event buffer in place. */
45
71
  default:
46
- this.events = new _eventStoreManager.EventStoreManager(agentRef.mainAppKey, 1, agentRef.agentIdentifier, this.featureName);
72
+ this.events = new _eventStoreManager.EventStoreManager(this.agentRef, _eventBuffer.EventBuffer, entityGuid, this.featureName);
47
73
  break;
48
74
  }
49
- this.harvestOpts = {}; // features aggregate classes can define custom opts for when their harvest is called
50
75
  }
51
76
 
52
77
  /**
@@ -76,6 +101,10 @@ class AggregateBase extends _featureBase.FeatureBase {
76
101
  this.deregisterDrain();
77
102
  });
78
103
  }
104
+
105
+ /**
106
+ * Stages the feature to be drained
107
+ */
79
108
  drain() {
80
109
  (0, _drain.drain)(this.agentIdentifier, this.featureName);
81
110
  this.drained = true;
@@ -87,28 +116,29 @@ class AggregateBase extends _featureBase.FeatureBase {
87
116
  /**
88
117
  * Return harvest payload. A "serializer" function can be defined on a derived class to format the payload.
89
118
  * @param {Boolean} shouldRetryOnFail - harvester flag to backup payload for retry later if harvest request fails; this should be moved to harvester logic
90
- * @param {object|undefined} opts.target - the target app passed onto the event store manager to determine which app's data to return; if none provided, all apps data will be returned
119
+ * @param {object|undefined} opts - opts passed from the harvester to help form the payload
120
+ * @param {string} opts.targetEntityGuid - the entity guid of the target app
91
121
  * @returns {Array} Final payload tagged with their targeting browser app. The value of `payload` can be undefined if there are no pending events for an app. This should be a minimum length of 1.
92
122
  */
93
123
  makeHarvestPayload(shouldRetryOnFail = false, opts = {}) {
94
- if (this.events.isEmpty(this.harvestOpts, opts.target)) return;
124
+ if (!this.events || this.events.isEmpty(this.harvestOpts, opts.targetEntityGuid)) return;
95
125
  // Other conditions and things to do when preparing harvest that is required.
96
126
  if (this.preHarvestChecks && !this.preHarvestChecks(opts)) return;
97
- if (shouldRetryOnFail) this.events.save(this.harvestOpts, opts.target);
98
- const returnedDataArr = this.events.get(this.harvestOpts, opts.target);
99
- if (!returnedDataArr.length) throw new Error('Unexpected problem encountered. There should be at least one app for harvest!');
100
- this.events.clear(this.harvestOpts, opts.target);
127
+ if (shouldRetryOnFail) this.events.save(this.harvestOpts, opts.targetEntityGuid);
128
+ const returnedDataArr = this.events.get(this.harvestOpts, opts.targetEntityGuid);
129
+ if (!returnedDataArr.length) return (0, _console.warn)(52);
130
+ this.events.clear(this.harvestOpts, opts.targetEntityGuid);
101
131
  return returnedDataArr.map(({
102
132
  targetApp,
103
133
  data
104
134
  }) => {
105
135
  // A serializer or formatter assists in creating the payload `body` from stored events on harvest when defined by derived feature class.
106
- const body = this.serializer ? this.serializer(data) : data;
136
+ const body = this.serializer ? this.serializer(data, targetApp?.entityGuid) : data;
107
137
  const payload = {
108
138
  body
109
139
  };
110
140
  // Constructs the payload `qs` for relevant features on harvest.
111
- if (this.queryStringsBuilder) payload.qs = this.queryStringsBuilder(data);
141
+ if (this.queryStringsBuilder) payload.qs = this.queryStringsBuilder(data, targetApp?.entityGuid);
112
142
  return {
113
143
  targetApp,
114
144
  payload
@@ -119,11 +149,15 @@ class AggregateBase extends _featureBase.FeatureBase {
119
149
  /**
120
150
  * Cleanup task after a harvest.
121
151
  * @param {object} result - the cbResult object from the harvester's send method
152
+ * @param {object=} result.targetApp - the target app object that was used to point the harvest to the correct app
153
+ * @param {string=} result.targetApp.entityGuid - the entity guid of the target app
154
+ * @param {boolean=} result.sent - whether the harvest was sent successfully
155
+ * @param {boolean=} result.retry - whether the harvest should be retried
122
156
  */
123
157
  postHarvestCleanup(result = {}) {
124
158
  const harvestFailed = result.sent && result.retry;
125
- if (harvestFailed) this.events.reloadSave(this.harvestOpts, result.targetApp);
126
- this.events.clearSave(this.harvestOpts, result.targetApp);
159
+ if (harvestFailed) this.events.reloadSave(this.harvestOpts, result.targetApp?.entityGuid);
160
+ this.events.clearSave(this.harvestOpts, result.targetApp?.entityGuid);
127
161
  }
128
162
 
129
163
  /**
@@ -145,16 +179,14 @@ class AggregateBase extends _featureBase.FeatureBase {
145
179
  } catch (err) {
146
180
  // do nothing
147
181
  }
148
- (0, _configure.configure)({
149
- agentIdentifier: this.agentIdentifier
150
- }, {
182
+ (0, _configure.configure)(existingAgent, {
151
183
  ...cdn,
152
184
  info: {
153
185
  ...cdn.info,
154
186
  jsAttributes
155
187
  },
156
188
  runtime: existingAgent.runtime
157
- });
189
+ }, existingAgent.runtime.loaderType);
158
190
  }
159
191
  }
160
192
 
@@ -165,12 +197,7 @@ class AggregateBase extends _featureBase.FeatureBase {
165
197
  doOnceForAllAggregate(agentRef) {
166
198
  if (!agentRef.runtime.obfuscator) agentRef.runtime.obfuscator = new _obfuscate.Obfuscator(agentRef);
167
199
  this.obfuscator = agentRef.runtime.obfuscator;
168
- if (!agentRef.mainAppKey) agentRef.mainAppKey = {
169
- licenseKey: agentRef.info.licenseKey,
170
- appId: agentRef.info.applicationID
171
- };
172
- // Create a single Aggregator for this agent if DNE yet; to be used by jserror endpoint features.
173
- if (!agentRef.sharedAggregator) agentRef.sharedAggregator = new _eventStoreManager.EventStoreManager(agentRef.mainAppKey, 2, agentRef.agentIdentifier, 'shared_aggregator');
200
+ if (!agentRef.runtime.entityManager) agentRef.runtime.entityManager = new _entityManager.EntityManager(this.agentRef);
174
201
  if (!agentRef.runtime.harvester) agentRef.runtime.harvester = new _harvester.Harvester(agentRef);
175
202
  }
176
203
 
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.EntityManager = void 0;
7
+ /**
8
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
9
+ * SPDX-License-Identifier: Apache-2.0
10
+ */
11
+
12
+ class EntityManager {
13
+ #entities = new Map();
14
+ #entityGuidLookup = {};
15
+ #defaultEntity = null;
16
+ constructor(agentRef) {
17
+ this.agentRef = agentRef;
18
+ this.#defaultEntity = {
19
+ licenseKey: agentRef.info.licenseKey,
20
+ applicationID: agentRef.info.applicationID
21
+ };
22
+ }
23
+ get(entityGuid) {
24
+ if (!entityGuid) return this.#defaultEntity;
25
+ return this.#entities.get(entityGuid);
26
+ }
27
+ getEntityGuidFor(licenseKey, applicationID) {
28
+ if (!this.#entityGuidLookup[licenseKey] || !this.#entityGuidLookup[applicationID]) return;
29
+ return this.#entityGuidLookup[licenseKey].filter(x => this.#entityGuidLookup[applicationID].includes(x))[0];
30
+ }
31
+ set(entityGuid, entity) {
32
+ if (this.#entities.has(entityGuid)) return;
33
+ this.#entities.set(entityGuid, entity);
34
+ this.#entityGuidLookup[entity.licenseKey] ??= [];
35
+ this.#entityGuidLookup[entity.licenseKey].push(entityGuid);
36
+ this.#entityGuidLookup[entity.applicationID] ??= [];
37
+ this.#entityGuidLookup[entity.applicationID].push(entityGuid);
38
+ this.agentRef.ee.emit('entity-added', [entity]);
39
+ }
40
+ clear() {
41
+ this.#entities.clear();
42
+ }
43
+ setDefaultEntity(entity) {
44
+ this.#defaultEntity = entity;
45
+ }
46
+ }
47
+ exports.EntityManager = EntityManager;
@@ -4,10 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.EventStoreManager = void 0;
7
- var _eventAggregator = require("../../common/aggregate/event-aggregator");
8
7
  var _globalEvent = require("../../common/dispatch/global-event");
9
8
  var _featureFlags = require("../../common/util/feature-flags");
10
- var _eventBuffer = require("./event-buffer");
11
9
  /**
12
10
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
13
11
  * SPDX-License-Identifier: Apache-2.0
@@ -19,31 +17,39 @@ var _eventBuffer = require("./event-buffer");
19
17
  */
20
18
  class EventStoreManager {
21
19
  /**
22
- * @param {object} defaultTarget - should contain licenseKey and appId of the main app from NREUM.info at startup
23
- * @param {1|2} storageChoice - the type of storage to use in this manager; 'EventBuffer' (1), 'EventAggregator' (2)
24
- * @param {string} agentIdentifier - agent identifier used in inspection events
25
- * @param {string} featureName - feature name used in inspection events for non-shared aggregators
20
+ * @param {object} agentRef - reference to base agent class
21
+ * @param {EventBuffer|EventAggregator} storageClass - the type of storage to use in this manager; 'EventBuffer' (1), 'EventAggregator' (2)
26
22
  */
27
- constructor(defaultTarget, storageChoice, agentIdentifier, featureName) {
28
- this.mainApp = defaultTarget;
29
- this.StorageClass = storageChoice === 1 ? _eventBuffer.EventBuffer : _eventAggregator.EventAggregator;
23
+ constructor(agentRef, storageClass, defaultEntityGuid, featureName) {
24
+ this.agentRef = agentRef;
25
+ this.entityManager = agentRef.runtime.entityManager;
26
+ this.StorageClass = storageClass;
30
27
  this.appStorageMap = new Map();
31
- this.appStorageMap.set(defaultTarget, new this.StorageClass());
32
- this.agentIdentifier = agentIdentifier;
28
+ this.defaultEntity = this.#getEventStore(defaultEntityGuid);
33
29
  this.featureName = featureName;
34
30
  }
35
31
 
32
+ /**
33
+ * Always returns a storage instance. Creates one if one does not exist. If a lookup is not provided, uses the DEFAULT namespace
34
+ * @param {string=} targetEntityGuid the lookup
35
+ * @returns {*} ALWAYS returns a storage instance
36
+ */
37
+ #getEventStore(targetEntityGuid) {
38
+ if (!targetEntityGuid) return this.defaultEntity;
39
+ if (!this.appStorageMap.has(targetEntityGuid)) this.appStorageMap.set(targetEntityGuid, new this.StorageClass());
40
+ return this.appStorageMap.get(targetEntityGuid);
41
+ }
42
+
36
43
  // This class must contain an union of all methods from all supported storage classes and conceptualize away the target app argument.
37
44
 
38
45
  /**
46
+ * Calls the isEmpty method on the underlying storage class. If target is provided, runs just for the target, otherwise runs for all apps.
39
47
  * @param {object} optsIfPresent - exists if called during harvest interval, @see AggregateBase.makeHarvestPayload
40
48
  * @param {object} target - specific app's storage to check; if not provided, this method takes into account all apps recorded by this manager
41
49
  * @returns {boolean} True if the target's storage is empty, or target does not exist in map (defaults to all storages)
42
50
  */
43
- isEmpty(optsIfPresent, target) {
44
- if (target) {
45
- if (!this.appStorageMap.has(target)) return true;else return this.appStorageMap.get(target).isEmpty(optsIfPresent);
46
- }
51
+ isEmpty(optsIfPresent, targetEntityGuid) {
52
+ if (targetEntityGuid) return this.#getEventStore(targetEntityGuid).isEmpty(optsIfPresent);
47
53
  for (const eventStore of this.appStorageMap.values()) {
48
54
  if (!eventStore.isEmpty(optsIfPresent)) return false;
49
55
  }
@@ -51,78 +57,97 @@ class EventStoreManager {
51
57
  }
52
58
 
53
59
  /**
60
+ * Calls the add method on the underlying storage class.
54
61
  * @param {string} event - the event element to store
55
- * @param {object} target - the app to store event under; if not provided, this method adds to the main app from NREUM.info
62
+ * @param {object} targetEntityGuid - the entity guid lookup to store event under; if not provided, this method adds to the default
56
63
  * @returns {boolean} True if the event was successfully added
57
64
  */
58
- add(event, target) {
65
+ add(event, targetEntityGuid) {
59
66
  (0, _globalEvent.dispatchGlobalEvent)({
60
- agentIdentifier: this.agentIdentifier,
61
- loaded: !!_featureFlags.activatedFeatures?.[this.agentIdentifier],
67
+ agentIdentifier: this.agentRef.agentIdentifier,
68
+ drained: !!_featureFlags.activatedFeatures?.[this.agentRef.agentIdentifier],
62
69
  type: 'data',
63
70
  name: 'buffer',
64
71
  feature: this.featureName,
65
72
  data: event
66
73
  });
67
- if (target && !this.appStorageMap.has(target)) this.appStorageMap.set(target, new this.StorageClass());
68
- return this.appStorageMap.get(target || this.mainApp).add(event);
74
+ return this.#getEventStore(targetEntityGuid).add(event);
69
75
  }
70
76
 
71
77
  /** This is only used by the Metrics feature which has no need to add metric under a different app atm. */
72
78
  addMetric(type, name, params, value) {
73
- return this.appStorageMap.get(this.mainApp).addMetric(type, name, params, value);
79
+ return this.#getEventStore().addMetric(type, name, params, value);
74
80
  }
75
81
 
76
82
  /**
77
- * @param {object} optsIfPresent - exists if called during harvest interval, @see AggregateBase.makeHarvestPayload
78
- * @param {object} target - specific app to fetch; if not provided, this method fetches from all apps
83
+ * Calls the get method on the underlying storage class. If target is provided, runs just for the target, otherwise runs for all apps.
84
+ * @param {object=} opts - exists if called during harvest interval, @see AggregateBase.makeHarvestPayload
85
+ * @param {object=} target - specific app to fetch; if not provided, this method fetches from all apps
79
86
  * @returns {Array} Objects of `data` labeled with their respective `target` app to be sent to
80
87
  */
81
- get(optsIfPresent, target) {
82
- if (target) return [{
83
- targetApp: target,
84
- data: this.appStorageMap.get(target)?.get(optsIfPresent)
88
+ get(opts, targetEntityGuid) {
89
+ if (targetEntityGuid) return [{
90
+ targetApp: this.entityManager.get(targetEntityGuid),
91
+ data: this.#getEventStore(targetEntityGuid).get(opts)
85
92
  }];
86
93
  const allPayloads = [];
87
- this.appStorageMap.forEach((eventStore, recordedTarget) => {
88
- allPayloads.push({
89
- targetApp: recordedTarget,
90
- data: eventStore.get(optsIfPresent)
94
+ this.appStorageMap.forEach((eventStore, targetEntityGuid) => {
95
+ const targetApp = this.entityManager.get(targetEntityGuid);
96
+ if (targetApp) allPayloads.push({
97
+ targetApp,
98
+ data: eventStore.get(opts)
91
99
  });
92
100
  });
93
101
  return allPayloads;
94
102
  }
95
- byteSize(target) {
96
- return this.appStorageMap.get(target || this.mainApp).byteSize();
103
+
104
+ /**
105
+ * Calls the byteSize method on the underlying storage class
106
+ * @param {*} targetEntityGuid
107
+ * @returns
108
+ */
109
+ byteSize(targetEntityGuid) {
110
+ return this.#getEventStore(targetEntityGuid).byteSize();
97
111
  }
98
- wouldExceedMaxSize(incomingSize, target) {
99
- return this.appStorageMap.get(target || this.mainApp).wouldExceedMaxSize(incomingSize);
112
+
113
+ /**
114
+ * Calls the wouldExceedMaxSize method on the underlying storage class
115
+ * @param {*} incomingSize
116
+ * @param {*} targetEntityGuid
117
+ * @returns
118
+ */
119
+ wouldExceedMaxSize(incomingSize, targetEntityGuid) {
120
+ return this.#getEventStore(targetEntityGuid).wouldExceedMaxSize(incomingSize);
100
121
  }
101
- save(optsIfPresent, target) {
102
- if (target) return this.appStorageMap.get(target)?.save(optsIfPresent);
122
+
123
+ /**
124
+ * Calls the save method on the underlying storage class. If target is provided, runs just for the target, otherwise runs for all apps.
125
+ * @param {*} optsIfPresent
126
+ * @param {*} targetEntityGuid
127
+ * @returns
128
+ */
129
+ save(optsIfPresent, targetEntityGuid) {
130
+ if (targetEntityGuid) return this.#getEventStore(targetEntityGuid).save(optsIfPresent);
103
131
  this.appStorageMap.forEach(eventStore => eventStore.save(optsIfPresent));
104
132
  }
105
- clear(optsIfPresent, target) {
106
- if (target) return this.appStorageMap.get(target)?.clear(optsIfPresent);
133
+
134
+ /**
135
+ * Calls the clear method on the underlying storage class. If target is provided, runs just for the target, otherwise runs for all apps.
136
+ * @param {*} optsIfPresent
137
+ * @param {*} targetEntityGuid
138
+ * @returns
139
+ */
140
+ clear(optsIfPresent, targetEntityGuid) {
141
+ if (targetEntityGuid) return this.#getEventStore(targetEntityGuid).clear(optsIfPresent);
107
142
  this.appStorageMap.forEach(eventStore => eventStore.clear(optsIfPresent));
108
143
  }
109
144
 
110
145
  // Unlike the methods above, the following will have a target as they are called by AggregateBase.postHarvestCleanup callback on harvest finish after getting & sending the data.
111
- reloadSave(optsIfPresent, target) {
112
- if (!target) {
113
- // -- remove this block once the old harvest.js & harvest-schedule.js are deleted!
114
- this.appStorageMap.forEach(eventStore => eventStore.reloadSave(optsIfPresent));
115
- return;
116
- }
117
- return this.appStorageMap.get(target)?.reloadSave(optsIfPresent);
146
+ reloadSave(optsIfPresent, targetEntityGuid) {
147
+ return this.#getEventStore(targetEntityGuid).reloadSave(optsIfPresent);
118
148
  }
119
- clearSave(optsIfPresent, target) {
120
- if (!target) {
121
- // -- remove this block once the old harvest.js & harvest-schedule.js are deleted!
122
- this.appStorageMap.forEach(eventStore => eventStore.clearSave(optsIfPresent));
123
- return;
124
- }
125
- return this.appStorageMap.get(target)?.clearSave(optsIfPresent);
149
+ clearSave(optsIfPresent, targetEntityGuid) {
150
+ return this.#getEventStore(targetEntityGuid).clearSave(optsIfPresent);
126
151
  }
127
152
  }
128
153
  exports.EventStoreManager = EventStoreManager;
@@ -13,7 +13,7 @@ var _nreum = require("../../common/window/nreum");
13
13
  const debugId = 1;
14
14
  const newrelic = (0, _nreum.gosCDN)();
15
15
  function debugNR1(agentIdentifier, location, event, otherprops = {}, debugName = 'SR') {
16
- const api = agentIdentifier ? newrelic.initializedAgents[agentIdentifier].api.addPageAction : newrelic.addPageAction;
16
+ const api = agentIdentifier ? newrelic.initializedAgents[agentIdentifier].addPageAction : newrelic.addPageAction;
17
17
  let url;
18
18
  try {
19
19
  const locURL = new URL(window.location);
@@ -0,0 +1,114 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.RegisteredEntity = void 0;
7
+ var _console = require("../common/util/console");
8
+ /**
9
+ * Copyright 2020-2025 New Relic, Inc. All rights reserved.
10
+ * SPDX-License-Identifier: Apache-2.0
11
+ */
12
+
13
+ /**
14
+ * @typedef {import('../loaders/api/register-api-types').RegisterAPI} RegisterAPI
15
+ * @typedef {import('../loaders/api/register-api-types').RegisterAPIMetadata} RegisterAPIMetadata
16
+ * @typedef {import('../loaders/api/register-api-types').RegisterAPIConstructor} RegisterAPIConstructor
17
+ */
18
+
19
+ /**
20
+ * @experimental
21
+ * IMPORTANT: This feature is being developed for use internally and is not in a public-facing production-ready state.
22
+ * It is not recommended for use in production environments and will not receive support for issues.
23
+ *
24
+ * An interface for registering an external caller to report through the base agent to a different target than the base agent.
25
+ */
26
+ class RegisteredEntity {
27
+ /** @type {RegisterAPIMetadata} */
28
+ metadata = {
29
+ target: {},
30
+ customAttributes: {}
31
+ };
32
+
33
+ /**
34
+ *
35
+ * @param {RegisterAPIConstructor} opts The options for setting up the registered entity.
36
+ */
37
+ constructor(opts) {
38
+ try {
39
+ if (!window?.newrelic) return (0, _console.warn)(51);
40
+ Object.assign(this, window?.newrelic?.register(opts) || {});
41
+ } catch (err) {
42
+ (0, _console.warn)(50, err);
43
+ }
44
+ }
45
+
46
+ /**
47
+ * Reports a browser PageAction event along with a name and optional attributes to the registered target.
48
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/addpageaction/}
49
+ * @param {string} name Name or category of the action. Reported as the actionName attribute.
50
+ * @param {object} [attributes] JSON object with one or more key/value pairs. For example: {key:"value"}. The key is reported as its own PageAction attribute with the specified values.
51
+ */
52
+ addPageAction(name, attributes) {
53
+ /** this method will be overset once register is successful */
54
+ (0, _console.warn)(35, 'addPageAction');
55
+ }
56
+
57
+ /**
58
+ * Adds a user-defined attribute name and value to subsequent events on the page for the registered target. Note -- the persist flag does not work with the register API.
59
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setcustomattribute/}
60
+ * @param {string} name Name of the attribute. Appears as column in the PageView event. It will also appear as a column in the PageAction event if you are using it.
61
+ * @param {string|number|boolean|null} value Value of the attribute. Appears as the value in the named attribute column in the PageView event. It will appear as a column in the PageAction event if you are using it. Custom attribute values cannot be complex objects, only simple types such as Strings, Integers and Booleans. Passing a null value unsets any existing attribute of the same name.
62
+ * @param {boolean} [persist] Default false. If set to true, the name-value pair will also be set into the browser's storage API. Then on the following instrumented pages that load within the same session, the pair will be re-applied as a custom attribute.
63
+ */
64
+ setCustomAttribute(name, value, persist) {
65
+ /** this method will be overset once register is successful */
66
+ (0, _console.warn)(35, 'setCustomAttribute');
67
+ }
68
+
69
+ /**
70
+ * Identifies a browser error without disrupting your app's operations for the registered target.
71
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/noticeerror/}
72
+ * @param {Error|string} error Provide a meaningful error message that you can use when analyzing data on browser's JavaScript errors page.
73
+ * @param {object} [customAttributes] An object containing name/value pairs representing custom attributes.
74
+ */
75
+ noticeError(error, customAttributes) {
76
+ /** this method will be overset once register is successful */
77
+ (0, _console.warn)(35, 'noticeError');
78
+ }
79
+
80
+ /**
81
+ * Adds a user-defined identifier string to subsequent events on the page for the registered taret.
82
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setuserid/}
83
+ * @param {string|null} value A string identifier for the end-user, useful for tying all browser events to specific users. The value parameter does not have to be unique. If IDs should be unique, the caller is responsible for that validation. Passing a null value unsets any existing user ID.
84
+ */
85
+ setUserId(value) {
86
+ /** this method will be overset once register is successful */
87
+ (0, _console.warn)(35, 'setUserId');
88
+ }
89
+
90
+ /**
91
+ * Adds a user-defined application version string to subsequent events on the page for the registered target.
92
+ * This decorates all payloads with an attribute of `application.version` which is queryable in NR1.
93
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/setapplicationversion/}
94
+ * @param {string|null} value A string identifier for the application version, useful for
95
+ * tying all browser events to a specific release tag. The value parameter does not
96
+ * have to be unique. Passing a null value unsets any existing value.
97
+ */
98
+ setApplicationVersion(value) {
99
+ /** this method will be overset once register is successful */
100
+ (0, _console.warn)(35, 'setApplicationVersion');
101
+ }
102
+
103
+ /**
104
+ * Capture a single log for the registered target.
105
+ * {@link https://docs.newrelic.com/docs/browser/new-relic-browser/browser-apis/log/}
106
+ * @param {string} message String to be captured as log message
107
+ * @param {{customAttributes?: object, level?: 'ERROR'|'TRACE'|'DEBUG'|'INFO'|'WARN'}} [options] customAttributes defaults to `{}` if not assigned, level defaults to `info` if not assigned.
108
+ */
109
+ log(message, options) {
110
+ /** this method will be overset once register is successful */
111
+ (0, _console.warn)(35, 'setCustomAttribute');
112
+ }
113
+ }
114
+ exports.RegisteredEntity = RegisteredEntity;
@@ -25,7 +25,7 @@ class AgentBase extends _microAgentBase.MicroAgentBase {
25
25
  * @param {...any} args
26
26
  */
27
27
  #callMethod(methodName, ...args) {
28
- if (typeof this.api?.[methodName] !== 'function') (0, _console.warn)(35, methodName);else return this.api[methodName](...args);
28
+ if (this[methodName] === AgentBase.prototype[methodName] || this[methodName] === _microAgentBase.MicroAgentBase.prototype[methodName]) (0, _console.warn)(35, methodName);else return this[methodName](...args);
29
29
  }
30
30
 
31
31
  /**
@@ -76,6 +76,9 @@ class Agent extends _agentBase.AgentBase {
76
76
  runtime: this.runtime
77
77
  };
78
78
  }
79
+ get api() {
80
+ return this;
81
+ }
79
82
  run() {
80
83
  // Attempt to initialize all the requested features (sequentially in prio order & synchronously), with any failure aborting the whole process.
81
84
  try {
@@ -103,7 +106,6 @@ class Agent extends _agentBase.AgentBase {
103
106
  this.features[featName].abortHandler?.();
104
107
  }
105
108
  const newrelic = (0, _nreum.gosNREUM)();
106
- delete newrelic.initializedAgents[this.agentIdentifier]?.api; // prevent further calls to agent-specific APIs (see "configure.js")
107
109
  delete newrelic.initializedAgents[this.agentIdentifier]?.features; // GC mem used internally by features
108
110
  delete this.sharedAggregator;
109
111
  // Keep the initialized agent object with its configs for troubleshooting purposes.
@@ -10,5 +10,5 @@ var _constants = require("../../features/session_replay/constants");
10
10
  * SPDX-License-Identifier: Apache-2.0
11
11
  */
12
12
 
13
- const apiMethods = exports.apiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'recordCustomEvent', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', _constants.SR_EVENT_EMITTER_TYPES.RECORD, _constants.SR_EVENT_EMITTER_TYPES.PAUSE, 'log', 'wrapLogger'];
13
+ const apiMethods = exports.apiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease', 'recordCustomEvent', 'addPageAction', 'setCurrentRouteName', 'setPageViewName', 'setCustomAttribute', 'interaction', 'noticeError', 'setUserId', 'setApplicationVersion', 'start', _constants.SR_EVENT_EMITTER_TYPES.RECORD, _constants.SR_EVENT_EMITTER_TYPES.PAUSE, 'log', 'wrapLogger', 'register'];
14
14
  const asyncApiMethods = exports.asyncApiMethods = ['setErrorHandler', 'finished', 'addToTrace', 'addRelease'];