@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
@@ -13,6 +13,7 @@ var _log = require("../shared/log");
13
13
  var _utils = require("../shared/utils");
14
14
  var _traverse = require("../../../common/util/traverse");
15
15
  var _agentConstants = require("../../../common/constants/agent-constants");
16
+ var _target = require("../../../common/util/target");
16
17
  var _constants2 = require("../../../common/session/constants");
17
18
  var _constants3 = require("../../session_replay/constants");
18
19
  var _featureGates = require("../../utils/feature-gates");
@@ -62,7 +63,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
62
63
  loggingMode: this.loggingMode
63
64
  });
64
65
  }
65
- handleLog(timestamp, message, attributes = {}, level = _constants.LOG_LEVELS.INFO) {
66
+ handleLog(timestamp, message, attributes = {}, level = _constants.LOG_LEVELS.INFO, targetEntityGuid) {
67
+ if (!this.agentRef.runtime.entityManager.get(targetEntityGuid)) return (0, _console.warn)(56, this.featureName);
66
68
  if (this.blocked || !this.loggingMode) return;
67
69
  if (!attributes || typeof attributes !== 'object') attributes = {};
68
70
  if (typeof level === 'string') level = level.toUpperCase();
@@ -97,11 +99,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
97
99
  (0, _console.warn)(31, log.message.slice(0, 25) + '...');
98
100
  return;
99
101
  }
100
- if (this.events.wouldExceedMaxSize(logBytes)) {
102
+ if (this.events.wouldExceedMaxSize(logBytes, targetEntityGuid)) {
101
103
  this.reportSupportabilityMetric('Logging/Harvest/Early/Seen', this.events.byteSize() + logBytes);
102
- this.agentRef.runtime.harvester.triggerHarvestFor(this); // force a harvest synchronously to try adding again
104
+ this.agentRef.runtime.harvester.triggerHarvestFor(this, {
105
+ targetEntityGuid
106
+ }); // force a harvest synchronously to try adding again
103
107
  }
104
- if (!this.events.add(log)) {
108
+ if (!this.events.add(log, targetEntityGuid)) {
105
109
  // still failed after a harvest attempt despite not being too large would mean harvest failed with options.retry
106
110
  this.reportSupportabilityMetric(failToHarvestMessage, logBytes);
107
111
  (0, _console.warn)(31, log.message.slice(0, 25) + '...');
@@ -109,24 +113,25 @@ class Aggregate extends _aggregateBase.AggregateBase {
109
113
  this.reportSupportabilityMetric('Logging/Event/Added/Seen');
110
114
  }
111
115
  }
112
- serializer(eventBuffer) {
116
+ serializer(eventBuffer, targetEntityGuid) {
117
+ const target = this.agentRef.runtime.entityManager.get(targetEntityGuid);
113
118
  const sessionEntity = this.agentRef.runtime.session;
114
119
  return [{
115
120
  common: {
116
121
  /** Attributes in the `common` section are added to `all` logs generated in the payload */
117
122
  attributes: {
118
- 'entity.guid': this.agentRef.runtime.appMetadata?.agents?.[0]?.entityGuid,
119
- // browser entity guid as provided from RUM response
123
+ 'entity.guid': target.entityGuid,
124
+ // browser entity guid as provided API target OR the default from RUM response if not supplied
120
125
  ...(sessionEntity && {
121
126
  session: sessionEntity.state.value || '0',
122
127
  // The session ID that we generate and keep across page loads
123
- hasReplay: sessionEntity.state.sessionReplayMode === 1,
128
+ hasReplay: sessionEntity.state.sessionReplayMode === 1 && (0, _target.isContainerAgentTarget)(target, this.agentRef),
124
129
  // True if a session replay recording is running
125
130
  hasTrace: sessionEntity.state.sessionTraceMode === 1 // True if a session trace recording is running
126
131
  }),
127
132
  ptid: this.agentRef.runtime.ptid,
128
133
  // page trace id
129
- appId: this.agentRef.info.applicationID,
134
+ appId: target.applicationID || this.agentRef.info.applicationID,
130
135
  // Application ID from info object,
131
136
  standalone: Boolean(this.agentRef.info.sa),
132
137
  // copy paste (true) vs APM (false)
@@ -144,9 +149,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
144
149
  logs: (0, _traverse.applyFnToProps)(eventBuffer, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string')
145
150
  }];
146
151
  }
147
- queryStringsBuilder() {
152
+ queryStringsBuilder(_, targetEntityGuid) {
153
+ const target = this.agentRef.runtime.entityManager.get(targetEntityGuid);
148
154
  return {
149
- browser_monitoring_key: this.agentRef.info.licenseKey
155
+ browser_monitoring_key: target.licenseKey
150
156
  };
151
157
  }
152
158
 
@@ -20,10 +20,11 @@ var _constants2 = require("../constants");
20
20
  * @param {string} message - the log message string
21
21
  * @param {{[key: string]: *}} customAttributes - The log's custom attributes if any
22
22
  * @param {enum} level - the log level enum
23
+ * @param {object=} targetEntityGuid - the optional target entity guid provided by an api call
23
24
  */
24
- function bufferLog(ee, message, customAttributes = {}, level = _constants2.LOG_LEVELS.INFO) {
25
+ function bufferLog(ee, message, customAttributes = {}, level = _constants2.LOG_LEVELS.INFO, targetEntityGuid, timestamp = (0, _now.now)()) {
25
26
  (0, _handle.handle)(_constants.SUPPORTABILITY_METRIC_CHANNEL, ["API/logging/".concat(level.toLowerCase(), "/called")], undefined, _features.FEATURE_NAMES.metrics, ee);
26
- (0, _handle.handle)(_constants2.LOGGING_EVENT_EMITTER_CHANNEL, [(0, _now.now)(), message, customAttributes, level], undefined, _features.FEATURE_NAMES.logging, ee);
27
+ (0, _handle.handle)(_constants2.LOGGING_EVENT_EMITTER_CHANNEL, [timestamp, message, customAttributes, level, targetEntityGuid], undefined, _features.FEATURE_NAMES.logging, ee);
27
28
  }
28
29
 
29
30
  /**
@@ -28,8 +28,13 @@ class Aggregate extends _aggregateBase.AggregateBase {
28
28
  this.harvestOpts.aggregatorTypes = ['cm', 'sm']; // the types in EventAggregator this feature cares about
29
29
  // This feature only harvests once per potential EoL of the page, which is handled by the central harvester.
30
30
 
31
+ // this must be read/stored synchronously, as the currentScript is removed from the DOM after this script is executed and this lookup will be void
32
+ // its used to report a SM later in the lifecycle
33
+ this.agentNonce = _runtime.isBrowserScope && document.currentScript?.nonce;
31
34
  this.waitForFlags(['err']).then(([errFlag]) => {
32
35
  if (errFlag) {
36
+ this.singleChecks(); // checks that are run only one time, at script load
37
+ this.eachSessionChecks(); // the start of every time user engages with page
33
38
  this.drain();
34
39
  } else {
35
40
  this.blocked = true; // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
@@ -40,8 +45,6 @@ class Aggregate extends _aggregateBase.AggregateBase {
40
45
  // Allow features external to the metrics feature to capture SMs and CMs through the event emitter
41
46
  (0, _registerHandler.registerHandler)(_constants.SUPPORTABILITY_METRIC_CHANNEL, this.storeSupportabilityMetrics.bind(this), this.featureName, this.ee);
42
47
  (0, _registerHandler.registerHandler)(_constants.CUSTOM_METRIC_CHANNEL, this.storeEventMetrics.bind(this), this.featureName, this.ee);
43
- this.singleChecks(); // checks that are run only one time, at script load
44
- this.eachSessionChecks(); // the start of every time user engages with page
45
48
  }
46
49
  preHarvestChecks(opts) {
47
50
  return this.drained && opts.isFinalHarvest;
@@ -77,8 +80,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
77
80
  if (distMethod) this.storeSupportabilityMetrics("Generic/DistMethod/".concat(distMethod, "/Detected"));
78
81
  if (_runtime.isBrowserScope) {
79
82
  this.storeSupportabilityMetrics('Generic/Runtime/Browser/Detected');
80
- const nonce = document?.currentScript?.nonce;
81
- if (nonce && nonce !== '') {
83
+ if (this.agentNonce && this.agentNonce !== '') {
82
84
  this.storeSupportabilityMetrics('Generic/Runtime/Nonce/Detected');
83
85
  }
84
86
 
@@ -19,6 +19,8 @@ var _timeToFirstByte = require("../../../common/vitals/time-to-first-byte");
19
19
  var _now = require("../../../common/timing/now");
20
20
  var _timeKeeper = require("../../../common/timing/time-keeper");
21
21
  var _traverse = require("../../../common/util/traverse");
22
+ var _registerHandler = require("../../../common/event-emitter/register-handler");
23
+ var _target = require("../../../common/util/target");
22
24
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
23
25
  function _interopRequireWildcard(e, r) { if (!r && e && e.__esModule) return e; if (null === e || "object" != typeof e && "function" != typeof e) return { default: e }; var t = _getRequireWildcardCache(r); if (t && t.has(e)) return t.get(e); var n = { __proto__: null }, a = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var u in e) if ("default" !== u && {}.hasOwnProperty.call(e, u)) { var i = a ? Object.getOwnPropertyDescriptor(e, u) : null; i && (i.get || i.set) ? Object.defineProperty(n, u, i) : n[u] = e[u]; } return n.default = e, t && t.set(e, n), n; }
24
26
  /**
@@ -34,6 +36,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
34
36
  this.firstByteToWindowLoad = 0; // our "frontend" duration
35
37
  this.firstByteToDomContent = 0; // our "dom processing" duration
36
38
 
39
+ (0, _registerHandler.registerHandler)('send-rum', (customAttibutes, target) => {
40
+ this.sendRum(customAttibutes, target);
41
+ }, this.featureName, this.ee);
37
42
  if (!(0, _info.isValid)(agentRef.agentIdentifier)) {
38
43
  this.ee.abort();
39
44
  return (0, _console.warn)(43);
@@ -56,7 +61,17 @@ class Aggregate extends _aggregateBase.AggregateBase {
56
61
  this.sendRum();
57
62
  }
58
63
  }
59
- sendRum() {
64
+
65
+ /**
66
+ *
67
+ * @param {Function} cb A function to run once the RUM call has finished - Defaults to activateFeatures
68
+ * @param {*} customAttributes custom attributes to attach to the RUM call - Defaults to info.js
69
+ * @param {*} target The target to harvest to - Since we will not know the entityGuid before harvesting, this must be an object directly supplied from the info object or API, not an entityGuid string for lookup with the entityManager - Defaults to { licenseKey: this.agentRef.info.licenseKey, applicationID: this.agentRef.info.applicationID }
70
+ */
71
+ sendRum(customAttributes = this.agentRef.info.jsAttributes, target = {
72
+ licenseKey: this.agentRef.info.licenseKey,
73
+ applicationID: this.agentRef.info.applicationID
74
+ }) {
60
75
  const info = this.agentRef.info;
61
76
  const measures = {};
62
77
  if (info.queueTime) measures.qt = info.queueTime;
@@ -82,9 +97,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
82
97
  if (this.agentRef.runtime.session) queryParameters.fsh = Number(this.agentRef.runtime.session.isNew); // "first session harvest" aka RUM request or PageView event of a session
83
98
 
84
99
  let body;
85
- if (typeof info.jsAttributes === 'object' && Object.keys(info.jsAttributes).length > 0) {
100
+ if (typeof customAttributes === 'object' && Object.keys(customAttributes).length > 0) {
86
101
  body = (0, _traverse.applyFnToProps)({
87
- ja: info.jsAttributes
102
+ ja: customAttributes
88
103
  }, this.obfuscator.obfuscateString.bind(this.obfuscator), 'string');
89
104
  }
90
105
  if (_runtime.globalScope.performance) {
@@ -114,7 +129,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
114
129
  this.rumStartTime = (0, _now.now)();
115
130
  this.agentRef.runtime.harvester.triggerHarvestFor(this, {
116
131
  directSend: {
117
- targetApp: this.agentRef.mainAppKey,
132
+ targetApp: target,
118
133
  payload: {
119
134
  qs: queryParameters,
120
135
  body
@@ -127,20 +142,32 @@ class Aggregate extends _aggregateBase.AggregateBase {
127
142
  postHarvestCleanup({
128
143
  status,
129
144
  responseText,
130
- xhr
145
+ xhr,
146
+ targetApp
131
147
  }) {
132
148
  const rumEndTime = (0, _now.now)();
149
+ let app, flags;
150
+ try {
151
+ ({
152
+ app,
153
+ ...flags
154
+ } = JSON.parse(responseText));
155
+ this.processEntities(app.agents, targetApp);
156
+ } catch (error) {
157
+ // wont set entity stuff here, if main agent will later abort, if registered agent, nothing will happen
158
+ (0, _console.warn)(53, error);
159
+ }
160
+
161
+ /** Only run agent-wide side-effects if the harvest was for the main agent */
162
+ if (!(0, _target.isContainerAgentTarget)(targetApp, this.agentRef)) return;
133
163
  if (status >= 400 || status === 0) {
134
164
  (0, _console.warn)(18, status);
135
165
  // Adding retry logic for the rum call will be a separate change; this.blocked will need to be changed since that prevents another triggerHarvestFor()
136
166
  this.ee.abort();
137
167
  return;
138
168
  }
139
- const {
140
- app,
141
- ...flags
142
- } = JSON.parse(responseText);
143
169
  try {
170
+ // will do nothing if already done
144
171
  this.agentRef.runtime.timeKeeper.processRumRequest(xhr, this.rumStartTime, rumEndTime, app.nrServerTime);
145
172
  if (!this.agentRef.runtime.timeKeeper.ready) throw new Error('TimeKeeper not ready');
146
173
  } catch (error) {
@@ -148,10 +175,32 @@ class Aggregate extends _aggregateBase.AggregateBase {
148
175
  (0, _console.warn)(17, error);
149
176
  return;
150
177
  }
151
- this.agentRef.runtime.appMetadata = app;
152
- (0, _featureFlags.activateFeatures)(flags, this.agentIdentifier);
178
+
179
+ // set the agent runtime objects that require the rum response or entity guid
180
+ if (!Object.keys(this.agentRef.runtime.appMetadata).length) this.agentRef.runtime.appMetadata = app;
153
181
  this.drain();
154
182
  this.agentRef.runtime.harvester.startTimer();
183
+ (0, _featureFlags.activateFeatures)(flags, this.agentRef);
184
+ }
185
+ processEntities(entities, targetApp) {
186
+ if (!entities || !targetApp) return;
187
+ entities.forEach(agent => {
188
+ const entityManager = this.agentRef.runtime.entityManager;
189
+ const entityGuid = agent.entityGuid;
190
+ const entity = entityManager.get(entityGuid);
191
+ if (entity) return; // already processed
192
+
193
+ if ((0, _target.isContainerAgentTarget)(targetApp, this.agentRef)) {
194
+ entityManager.setDefaultEntity({
195
+ ...targetApp,
196
+ entityGuid
197
+ });
198
+ }
199
+ entityManager.set(agent.entityGuid, {
200
+ ...targetApp,
201
+ entityGuid
202
+ });
203
+ });
155
204
  }
156
205
  }
157
206
  exports.Aggregate = Aggregate;
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.PageViewEvent = exports.Instrument = void 0;
7
+ var _handle = require("../../../common/event-emitter/handle");
7
8
  var _instrumentBase = require("../../utils/instrument-base");
8
9
  var CONSTANTS = _interopRequireWildcard(require("../constants"));
9
10
  function _getRequireWildcardCache(e) { if ("function" != typeof WeakMap) return null; var r = new WeakMap(), t = new WeakMap(); return (_getRequireWildcardCache = function (e) { return e ? t : r; })(e); }
@@ -17,6 +18,9 @@ class Instrument extends _instrumentBase.InstrumentBase {
17
18
  static featureName = CONSTANTS.FEATURE_NAME;
18
19
  constructor(agentRef, auto = true) {
19
20
  super(agentRef, CONSTANTS.FEATURE_NAME, auto);
21
+
22
+ /** messages from the register API that can trigger a new RUM call */
23
+ this.ee.on('api-send-rum', (attrs, target) => (0, _handle.handle)('send-rum', [attrs, target], undefined, this.featureName, this.ee));
20
24
  this.importAggregator(agentRef);
21
25
  }
22
26
  }
@@ -223,6 +223,10 @@ class Aggregate extends _aggregateBase.AggregateBase {
223
223
  }
224
224
  }
225
225
  makeHarvestPayload(shouldRetryOnFail) {
226
+ const payloadOutput = {
227
+ targetApp: undefined,
228
+ payload: undefined
229
+ };
226
230
  if (this.mode !== _constants2.MODE.FULL || this.blocked) return;
227
231
  if (!this.recorder || !this.timeKeeper?.ready || !this.recorder.hasSeenSnapshot) return;
228
232
  const recorderEvents = this.recorder.getEvents();
@@ -231,7 +235,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
231
235
  const payload = this.getHarvestContents(recorderEvents);
232
236
  if (!payload.body.length) {
233
237
  this.recorder.clearBuffer();
234
- return;
238
+ return [payloadOutput];
235
239
  }
236
240
  this.reportSupportabilityMetric('SessionReplay/Harvest/Attempts');
237
241
  let len = 0;
@@ -268,7 +272,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
268
272
  }
269
273
  if (len > _agentConstants.MAX_PAYLOAD_SIZE) {
270
274
  this.abort(_constants.ABORT_REASONS.TOO_BIG, len);
271
- return;
275
+ return [payloadOutput];
272
276
  }
273
277
  // TODO -- Gracefully handle the buffer for retries.
274
278
  if (!this.agentRef.runtime.session.state.sessionReplaySentFirstChunk) this.syncWithSessionManager({
@@ -276,10 +280,8 @@ class Aggregate extends _aggregateBase.AggregateBase {
276
280
  });
277
281
  this.recorder.clearBuffer();
278
282
  if (recorderEvents.type === 'preloaded') this.agentRef.runtime.harvester.triggerHarvestFor(this);
279
- return [{
280
- targetApp: undefined,
281
- payload
282
- }]; // SR doesn't need a targetApp as it only works for the main, but format needs to make AggregateBase
283
+ payloadOutput.payload = payload;
284
+ return [payloadOutput];
283
285
  }
284
286
  getCorrectedTimestamp(node) {
285
287
  if (!node?.timestamp) return;
@@ -89,7 +89,7 @@ class Instrument extends _instrumentBase.InstrumentBase {
89
89
  });
90
90
  this.recorder.startRecording();
91
91
  this.abortHandler = this.recorder.stopRecording;
92
- } catch (e) {}
92
+ } catch (e) {} // TODO add internal error handling
93
93
  this.importAggregator(this.#agentRef, {
94
94
  recorder: this.recorder,
95
95
  errorNoticed: this.errorNoticed
@@ -26,8 +26,10 @@ class RecorderEvents {
26
26
  hasMeta = false;
27
27
  /** Payload metadata -- Should indicate that the payload being sent contains an error. Used for query/filter purposes in UI */
28
28
  hasError = false;
29
- /** Payload metadata -- Denotes whether all stylesheet elements were able to be inlined */
30
- inlinedAllStylesheets = true;
29
+ constructor(shouldInlineStylesheets = true) {
30
+ /** Payload metadata -- Denotes whether all stylesheet elements were able to be inlined */
31
+ this.inlinedAllStylesheets = shouldInlineStylesheets;
32
+ }
31
33
  add(event) {
32
34
  this.#events.add(event);
33
35
  }
@@ -16,6 +16,8 @@ var _features = require("../../../loaders/features/features");
16
16
  var _utils = require("./utils");
17
17
  var _agentConstants = require("../../../common/constants/agent-constants");
18
18
  var _aggregateBase = require("../../utils/aggregate-base");
19
+ var _console = require("../../../common/util/console");
20
+ var _invoke = require("../../../common/util/invoke");
19
21
  /**
20
22
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
21
23
  * SPDX-License-Identifier: Apache-2.0
@@ -30,10 +32,17 @@ class Recorder {
30
32
  #preloaded;
31
33
  /** flag that if true, blocks events from being "stored". Only set to true when a full snapshot has incomplete nodes (only stylesheets ATM) */
32
34
  #fixing = false;
35
+ #warnCSSOnce = (0, _invoke.single)(() => (0, _console.warn)(47)); // notifies user of potential replayer issue if fix_stylesheets is off
36
+
33
37
  constructor(parent) {
34
- this.#events = new _recorderEvents.RecorderEvents();
35
- this.#backloggedEvents = new _recorderEvents.RecorderEvents();
36
- this.#preloaded = [new _recorderEvents.RecorderEvents()];
38
+ /** The parent class that instantiated the recorder */
39
+ this.parent = parent;
40
+ /** A flag that can be set to false by failing conversions to stop the fetching process */
41
+ this.shouldFix = this.parent.agentRef.init.session_replay.fix_stylesheets;
42
+ /** Event Buffers */
43
+ this.#events = new _recorderEvents.RecorderEvents(this.shouldFix);
44
+ this.#backloggedEvents = new _recorderEvents.RecorderEvents(this.shouldFix);
45
+ this.#preloaded = [new _recorderEvents.RecorderEvents(this.shouldFix)];
37
46
  /** True when actively recording, false when paused or stopped */
38
47
  this.recording = false;
39
48
  /** The pointer to the current bucket holding rrweb events */
@@ -42,10 +51,6 @@ class Recorder {
42
51
  this.hasSeenSnapshot = false;
43
52
  /** Hold on to the last meta node, so that it can be re-inserted if the meta and snapshot nodes are broken up due to harvesting */
44
53
  this.lastMeta = false;
45
- /** The parent class that instantiated the recorder */
46
- this.parent = parent;
47
- /** A flag that can be set to false by failing conversions to stop the fetching process */
48
- this.shouldFix = this.parent.agentRef.init.session_replay.fix_stylesheets;
49
54
  /** The method to stop recording. This defaults to a noop, but is overwritten once the recording library is imported and initialized */
50
55
  this.stopRecording = () => {/* no-op until set by rrweb initializer */};
51
56
  }
@@ -72,8 +77,8 @@ class Recorder {
72
77
 
73
78
  /** Clears the buffer (this.#events), and resets all payload metadata properties */
74
79
  clearBuffer() {
75
- if (this.#preloaded[0]?.events.length) this.#preloaded.shift();else if (this.parent.mode === _constants2.MODE.ERROR) this.#backloggedEvents = this.#events;else this.#backloggedEvents = new _recorderEvents.RecorderEvents();
76
- this.#events = new _recorderEvents.RecorderEvents();
80
+ if (this.#preloaded[0]?.events.length) this.#preloaded.shift();else if (this.parent.mode === _constants2.MODE.ERROR) this.#backloggedEvents = this.#events;else this.#backloggedEvents = new _recorderEvents.RecorderEvents(this.shouldFix);
81
+ this.#events = new _recorderEvents.RecorderEvents(this.shouldFix);
77
82
  }
78
83
 
79
84
  /** Begin recording using configured recording lib */
@@ -125,12 +130,13 @@ class Recorder {
125
130
  */
126
131
  audit(event, isCheckout) {
127
132
  /** An count of stylesheet objects that were blocked from accessing contents via JS */
128
- const incompletes = _stylesheetEvaluator.stylesheetEvaluator.evaluate();
133
+ const incompletes = this.parent.agentRef.init.session_replay.fix_stylesheets ? _stylesheetEvaluator.stylesheetEvaluator.evaluate() : 0;
129
134
  const missingInlineSMTag = 'SessionReplay/Payload/Missing-Inline-Css/';
130
135
  /** only run the full fixing behavior (more costly) if fix_stylesheets is configured as on (default behavior) */
131
136
  if (!this.shouldFix) {
132
137
  if (incompletes > 0) {
133
138
  this.currentBufferTarget.inlinedAllStylesheets = false;
139
+ this.#warnCSSOnce();
134
140
  (0, _handle.handle)(_constants3.SUPPORTABILITY_METRIC_CHANNEL, [missingInlineSMTag + 'Skipped', incompletes], undefined, _features.FEATURE_NAMES.metrics, this.parent.ee);
135
141
  }
136
142
  return this.store(event, isCheckout);
@@ -200,7 +206,7 @@ class Recorder {
200
206
  this.parent.agentRef.runtime.harvester.triggerHarvestFor(this.parent);
201
207
  } else {
202
208
  // we are still in "preload" and it triggered a "stop point". Make a new set, which will get pointed at on next cycle
203
- this.#preloaded.push(new _recorderEvents.RecorderEvents());
209
+ this.#preloaded.push(new _recorderEvents.RecorderEvents(this.shouldFix));
204
210
  }
205
211
  }
206
212
  }
@@ -22,7 +22,8 @@ const ignoredEvents = {
22
22
  // we find that certain events make the data too noisy to be useful
23
23
  global: {
24
24
  mouseup: true,
25
- mousedown: true
25
+ mousedown: true,
26
+ mousemove: true
26
27
  },
27
28
  // certain events are present both in the window and in PVT metrics. PVT metrics are prefered so the window events should be ignored
28
29
  window: {
@@ -184,8 +185,8 @@ class TraceStorage {
184
185
  this.storeSTN(evt);
185
186
  }
186
187
  shouldIgnoreEvent(event, target) {
187
- const origin = (0, _eventOrigin.eventOrigin)(event.target, target, this.parent.ee);
188
188
  if (event.type in ignoredEvents.global) return true;
189
+ const origin = (0, _eventOrigin.eventOrigin)(event.target, target, this.parent.ee);
189
190
  if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true;
190
191
  return !!(!!ignoredEvents[origin] && event.type in ignoredEvents[origin]);
191
192
  }
@@ -266,7 +267,7 @@ class TraceStorage {
266
267
  }
267
268
  get() {
268
269
  return [{
269
- targetApp: this.parent.agentRef.mainAppKey,
270
+ targetApp: this.parent.agentRef.runtime.entityManager.get(),
270
271
  data: this.takeSTNs()
271
272
  }];
272
273
  }
@@ -31,7 +31,15 @@ class Aggregate extends _aggregateBase.AggregateBase {
31
31
  this.initialPageLoadInteraction.onDone.push(() => {
32
32
  // this ensures the .end() method also works with iPL
33
33
  this.initialPageLoadInteraction.forceSave = true; // unless forcibly ignored, iPL always finish by default
34
- this.interactionsToHarvest.add(this.initialPageLoadInteraction);
34
+ const ixn = this.initialPageLoadInteraction;
35
+ /** this.events (ixns to harvest) has already been set up, use it immediately */
36
+ if (this.interactionsToHarvest) this.interactionsToHarvest.add(ixn);else {
37
+ /** this.events (ixns to harvest) hasnt been initialized yet... wait for it */
38
+ this.ee.on('entity-added', () => {
39
+ this.interactionsToHarvest = this.events;
40
+ this.interactionsToHarvest.add(ixn);
41
+ });
42
+ }
35
43
  this.initialPageLoadInteraction = null;
36
44
  });
37
45
  _timeToFirstByte.timeToFirstByte.subscribe(({
@@ -132,7 +140,9 @@ class Aggregate extends _aggregateBase.AggregateBase {
132
140
  */
133
141
  if (this.interactionInProgress?.isActiveDuring(timestamp)) return this.interactionInProgress;
134
142
  let saveIxn;
135
- const interactionsBuffer = this.interactionsToHarvest.get(this.agentRef.mainAppKey)[0].data;
143
+ const [{
144
+ data: interactionsBuffer
145
+ }] = this.interactionsToHarvest.get();
136
146
  for (let idx = interactionsBuffer.length - 1; idx >= 0; idx--) {
137
147
  // reverse search for the latest completed interaction for efficiency
138
148
  const finishedInteraction = interactionsBuffer[idx];
@@ -125,7 +125,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
125
125
  }
126
126
  });
127
127
  if (agentRef.init.spa.enabled !== true) return;
128
- state.initialPageLoad = new _interaction.Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier);
128
+ state.initialPageLoad = new _interaction.Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef);
129
129
  state.initialPageLoad.save = true;
130
130
  state.prevInteraction = state.initialPageLoad;
131
131
  state.currentNode = state.initialPageLoad.root; // hint
@@ -206,7 +206,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
206
206
  // Otherwise, if no interaction is currently active, create a new node ID,
207
207
  // and let the aggregator know that we entered a new event handler callback
208
208
  // so that it has a chance to possibly start an interaction.
209
- var ixn = new _interaction.Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier);
209
+ var ixn = new _interaction.Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef);
210
210
 
211
211
  // Store the interaction as prevInteraction in case it is prematurely discarded
212
212
  state.prevInteraction = ixn;
@@ -504,7 +504,7 @@ class Aggregate extends _aggregateBase.AggregateBase {
504
504
  }, this.featureName, promiseEE);
505
505
  (0, _registerHandler.registerHandler)(INTERACTION_API + 'get', function (t) {
506
506
  var interaction;
507
- if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION];else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION];else interaction = this.ixn = new _interaction.Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier);
507
+ if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION];else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION];else interaction = this.ixn = new _interaction.Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef);
508
508
  if (!state.currentNode) {
509
509
  interaction.checkFinish();
510
510
  if (state.depth) setCurrentNode(interaction.root);
@@ -4,10 +4,8 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.Interaction = Interaction;
7
- var _info = require("../../../common/config/info");
8
7
  var _runtime = require("../../../common/constants/runtime");
9
8
  var _nreum = require("../../../common/window/nreum");
10
- var _contextualEe = require("../../../common/event-emitter/contextual-ee");
11
9
  var _interactionNode = require("./interaction-node");
12
10
  /**
13
11
  * Copyright 2020-2025 New Relic, Inc. All rights reserved.
@@ -17,11 +15,10 @@ var _interactionNode = require("./interaction-node");
17
15
  var originalSetTimeout = (0, _nreum.gosNREUMOriginals)().o.ST;
18
16
  var originalClearTimeout = (0, _nreum.gosNREUMOriginals)().o.CT;
19
17
  var lastId = {};
20
- function Interaction(eventName, timestamp, url, routeName, onFinished, agentIdentifier) {
21
- this.agentIdentifier = agentIdentifier;
22
- this.ee = _contextualEe.ee.get(agentIdentifier);
23
- lastId[agentIdentifier] = 0;
24
- this.id = ++lastId[agentIdentifier];
18
+ function Interaction(eventName, timestamp, url, routeName, onFinished, agentRef) {
19
+ this.agentRef = agentRef;
20
+ lastId[agentRef.agentIdentifier] = 0;
21
+ this.id = ++lastId[agentRef.agentIdentifier];
25
22
  this.eventName = eventName;
26
23
  this.nodes = 0;
27
24
  this.remaining = 0;
@@ -89,9 +86,9 @@ InteractionPrototype.finish = function finishInteraction() {
89
86
  if (this.onFinished) {
90
87
  this.onFinished(this);
91
88
  }
92
- Object.entries((0, _info.getInfo)(interaction.agentIdentifier).jsAttributes || {}).forEach(([attr, value]) => {
89
+ Object.entries(interaction.agentRef.info?.jsAttributes || {}).forEach(([attr, value]) => {
93
90
  if (!(attr in customAttrs)) customAttrs[attr] = value;
94
91
  });
95
92
  root.end = endTimestamp;
96
- interaction.ee.emit('interaction', [this]);
93
+ interaction.agentRef.ee.emit('interaction', [this]);
97
94
  };