@newrelic/browser-agent 1.269.0 → 1.270.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (165) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/cjs/common/constants/env.cdn.js +1 -1
  3. package/dist/cjs/common/constants/env.npm.js +1 -1
  4. package/dist/cjs/common/constants/runtime.js +1 -2
  5. package/dist/cjs/common/harvest/harvest-scheduler.js +3 -4
  6. package/dist/cjs/common/unload/eol.js +2 -5
  7. package/dist/cjs/common/util/submit-data.js +1 -1
  8. package/dist/cjs/features/ajax/aggregate/index.js +8 -17
  9. package/dist/cjs/features/ajax/instrument/index.js +8 -10
  10. package/dist/cjs/features/generic_events/aggregate/index.js +15 -22
  11. package/dist/cjs/features/generic_events/instrument/index.js +5 -8
  12. package/dist/cjs/features/jserrors/aggregate/index.js +17 -22
  13. package/dist/cjs/features/jserrors/instrument/index.js +3 -3
  14. package/dist/cjs/features/logging/aggregate/index.js +16 -23
  15. package/dist/cjs/features/logging/instrument/index.js +3 -3
  16. package/dist/cjs/features/metrics/aggregate/index.js +13 -16
  17. package/dist/cjs/features/metrics/instrument/index.js +3 -3
  18. package/dist/cjs/features/page_view_event/aggregate/index.js +15 -29
  19. package/dist/cjs/features/page_view_event/instrument/index.js +3 -3
  20. package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -23
  21. package/dist/cjs/features/page_view_timing/instrument/index.js +3 -3
  22. package/dist/cjs/features/session_replay/aggregate/index.js +15 -29
  23. package/dist/cjs/features/session_replay/instrument/index.js +7 -5
  24. package/dist/cjs/features/session_trace/aggregate/index.js +25 -31
  25. package/dist/cjs/features/session_trace/aggregate/trace/storage.js +1 -1
  26. package/dist/cjs/features/session_trace/instrument/index.js +4 -5
  27. package/dist/cjs/features/soft_navigations/aggregate/index.js +6 -11
  28. package/dist/cjs/features/soft_navigations/instrument/index.js +3 -3
  29. package/dist/cjs/features/spa/aggregate/index.js +19 -30
  30. package/dist/cjs/features/spa/instrument/index.js +4 -4
  31. package/dist/cjs/features/utils/aggregate-base.js +11 -12
  32. package/dist/cjs/features/utils/feature-base.js +5 -3
  33. package/dist/cjs/features/utils/instrument-base.js +18 -10
  34. package/dist/cjs/loaders/agent.js +1 -5
  35. package/dist/cjs/loaders/micro-agent.js +6 -9
  36. package/dist/esm/common/constants/env.cdn.js +1 -1
  37. package/dist/esm/common/constants/env.npm.js +1 -1
  38. package/dist/esm/common/constants/runtime.js +0 -1
  39. package/dist/esm/common/harvest/harvest-scheduler.js +3 -4
  40. package/dist/esm/common/unload/eol.js +2 -5
  41. package/dist/esm/common/util/submit-data.js +2 -2
  42. package/dist/esm/features/ajax/aggregate/index.js +8 -17
  43. package/dist/esm/features/ajax/instrument/index.js +8 -10
  44. package/dist/esm/features/generic_events/aggregate/index.js +11 -18
  45. package/dist/esm/features/generic_events/instrument/index.js +5 -8
  46. package/dist/esm/features/jserrors/aggregate/index.js +15 -20
  47. package/dist/esm/features/jserrors/instrument/index.js +3 -3
  48. package/dist/esm/features/logging/aggregate/index.js +16 -23
  49. package/dist/esm/features/logging/instrument/index.js +3 -3
  50. package/dist/esm/features/metrics/aggregate/index.js +8 -11
  51. package/dist/esm/features/metrics/instrument/index.js +3 -3
  52. package/dist/esm/features/page_view_event/aggregate/index.js +16 -30
  53. package/dist/esm/features/page_view_event/instrument/index.js +3 -3
  54. package/dist/esm/features/page_view_timing/aggregate/index.js +6 -23
  55. package/dist/esm/features/page_view_timing/instrument/index.js +3 -3
  56. package/dist/esm/features/session_replay/aggregate/index.js +13 -27
  57. package/dist/esm/features/session_replay/instrument/index.js +7 -5
  58. package/dist/esm/features/session_trace/aggregate/index.js +22 -28
  59. package/dist/esm/features/session_trace/aggregate/trace/storage.js +1 -1
  60. package/dist/esm/features/session_trace/instrument/index.js +4 -5
  61. package/dist/esm/features/soft_navigations/aggregate/index.js +6 -11
  62. package/dist/esm/features/soft_navigations/instrument/index.js +3 -3
  63. package/dist/esm/features/spa/aggregate/index.js +17 -28
  64. package/dist/esm/features/spa/instrument/index.js +4 -4
  65. package/dist/esm/features/utils/aggregate-base.js +13 -14
  66. package/dist/esm/features/utils/feature-base.js +5 -3
  67. package/dist/esm/features/utils/instrument-base.js +18 -10
  68. package/dist/esm/loaders/agent.js +1 -5
  69. package/dist/esm/loaders/micro-agent.js +6 -9
  70. package/dist/types/common/constants/runtime.d.ts +0 -1
  71. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  72. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  73. package/dist/types/common/unload/eol.d.ts +1 -1
  74. package/dist/types/common/unload/eol.d.ts.map +1 -1
  75. package/dist/types/features/ajax/aggregate/index.d.ts +1 -1
  76. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  77. package/dist/types/features/ajax/instrument/index.d.ts +1 -1
  78. package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
  79. package/dist/types/features/generic_events/aggregate/index.d.ts +1 -2
  80. package/dist/types/features/generic_events/aggregate/index.d.ts.map +1 -1
  81. package/dist/types/features/generic_events/instrument/index.d.ts +1 -1
  82. package/dist/types/features/generic_events/instrument/index.d.ts.map +1 -1
  83. package/dist/types/features/jserrors/aggregate/index.d.ts +1 -1
  84. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  85. package/dist/types/features/jserrors/instrument/index.d.ts +1 -1
  86. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  87. package/dist/types/features/logging/aggregate/index.d.ts +1 -2
  88. package/dist/types/features/logging/aggregate/index.d.ts.map +1 -1
  89. package/dist/types/features/logging/instrument/index.d.ts +1 -1
  90. package/dist/types/features/logging/instrument/index.d.ts.map +1 -1
  91. package/dist/types/features/metrics/aggregate/index.d.ts +1 -1
  92. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  93. package/dist/types/features/metrics/instrument/index.d.ts +1 -1
  94. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  95. package/dist/types/features/page_action/instrument/index.d.ts +1 -0
  96. package/dist/types/features/page_action/instrument/index.d.ts.map +1 -1
  97. package/dist/types/features/page_view_event/aggregate/index.d.ts +1 -1
  98. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  99. package/dist/types/features/page_view_event/instrument/index.d.ts +1 -1
  100. package/dist/types/features/page_view_event/instrument/index.d.ts.map +1 -1
  101. package/dist/types/features/page_view_timing/aggregate/index.d.ts +1 -5
  102. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  103. package/dist/types/features/page_view_timing/instrument/index.d.ts +1 -1
  104. package/dist/types/features/page_view_timing/instrument/index.d.ts.map +1 -1
  105. package/dist/types/features/session_replay/aggregate/index.d.ts +0 -1
  106. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  107. package/dist/types/features/session_replay/instrument/index.d.ts +1 -1
  108. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -1
  109. package/dist/types/features/session_trace/aggregate/index.d.ts +1 -3
  110. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  111. package/dist/types/features/session_trace/instrument/index.d.ts +1 -1
  112. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  113. package/dist/types/features/soft_navigations/aggregate/index.d.ts +1 -1
  114. package/dist/types/features/soft_navigations/aggregate/index.d.ts.map +1 -1
  115. package/dist/types/features/soft_navigations/instrument/index.d.ts +1 -1
  116. package/dist/types/features/soft_navigations/instrument/index.d.ts.map +1 -1
  117. package/dist/types/features/spa/aggregate/index.d.ts +1 -1
  118. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  119. package/dist/types/features/spa/instrument/index.d.ts +1 -1
  120. package/dist/types/features/spa/instrument/index.d.ts.map +1 -1
  121. package/dist/types/features/utils/aggregate-base.d.ts +2 -2
  122. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  123. package/dist/types/features/utils/feature-base.d.ts +2 -3
  124. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  125. package/dist/types/features/utils/instrument-base.d.ts +3 -3
  126. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  127. package/dist/types/loaders/agent.d.ts +0 -2
  128. package/dist/types/loaders/agent.d.ts.map +1 -1
  129. package/dist/types/loaders/micro-agent.d.ts +0 -2
  130. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  131. package/package.json +1 -1
  132. package/src/common/constants/__mocks__/runtime.js +0 -1
  133. package/src/common/constants/runtime.js +0 -2
  134. package/src/common/harvest/harvest-scheduler.js +3 -4
  135. package/src/common/unload/eol.js +2 -5
  136. package/src/common/util/submit-data.js +2 -2
  137. package/src/features/ajax/aggregate/index.js +8 -18
  138. package/src/features/ajax/instrument/index.js +8 -10
  139. package/src/features/generic_events/aggregate/index.js +11 -20
  140. package/src/features/generic_events/instrument/index.js +7 -10
  141. package/src/features/jserrors/aggregate/index.js +15 -20
  142. package/src/features/jserrors/instrument/index.js +3 -4
  143. package/src/features/logging/aggregate/index.js +15 -23
  144. package/src/features/logging/instrument/index.js +3 -3
  145. package/src/features/metrics/aggregate/index.js +8 -11
  146. package/src/features/metrics/instrument/index.js +3 -3
  147. package/src/features/page_view_event/aggregate/index.js +16 -22
  148. package/src/features/page_view_event/instrument/index.js +3 -3
  149. package/src/features/page_view_timing/aggregate/index.js +6 -23
  150. package/src/features/page_view_timing/instrument/index.js +3 -3
  151. package/src/features/session_replay/aggregate/index.js +13 -21
  152. package/src/features/session_replay/instrument/index.js +7 -5
  153. package/src/features/session_trace/aggregate/index.js +22 -28
  154. package/src/features/session_trace/aggregate/trace/storage.js +1 -1
  155. package/src/features/session_trace/instrument/index.js +4 -5
  156. package/src/features/soft_navigations/aggregate/index.js +6 -8
  157. package/src/features/soft_navigations/instrument/index.js +3 -3
  158. package/src/features/spa/aggregate/index.js +17 -26
  159. package/src/features/spa/instrument/index.js +4 -4
  160. package/src/features/utils/__mocks__/feature-base.js +1 -2
  161. package/src/features/utils/aggregate-base.js +13 -14
  162. package/src/features/utils/feature-base.js +6 -3
  163. package/src/features/utils/instrument-base.js +16 -10
  164. package/src/loaders/agent.js +1 -3
  165. package/src/loaders/micro-agent.js +7 -9
@@ -1,5 +1,3 @@
1
- import { getConfigurationValue } from '../../../common/config/init'
2
- import { deregisterDrain } from '../../../common/drain/drain'
3
1
  import { handle } from '../../../common/event-emitter/handle'
4
2
  import { registerHandler } from '../../../common/event-emitter/register-handler'
5
3
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
@@ -16,14 +14,14 @@ import { Interaction } from './interaction'
16
14
 
17
15
  export class Aggregate extends AggregateBase {
18
16
  static featureName = FEATURE_NAME
19
- constructor (agentIdentifier, aggregator, { domObserver }) {
20
- super(agentIdentifier, aggregator, FEATURE_NAME)
17
+ constructor (agentRef, { domObserver }) {
18
+ super(agentRef, FEATURE_NAME)
21
19
 
22
- const harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'soft_navigations.harvestTimeSeconds') || 10
20
+ const harvestTimeSeconds = agentRef.init.soft_navigations.harvestTimeSeconds || 10
23
21
  this.interactionsToHarvest = new EventBuffer()
24
22
  this.domObserver = domObserver
25
23
 
26
- this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentIdentifier)
24
+ this.initialPageLoadInteraction = new InitialPageLoadInteraction(agentRef.agentIdentifier)
27
25
  timeToFirstByte.subscribe(({ attrs }) => {
28
26
  const loadEventTime = attrs.navigationEntry.loadEventEnd
29
27
  this.initialPageLoadInteraction.forceSave = true
@@ -45,12 +43,12 @@ export class Aggregate extends AggregateBase {
45
43
  onFinished: this.onHarvestFinished.bind(this),
46
44
  retryDelay: harvestTimeSeconds,
47
45
  onUnload: () => this.interactionInProgress?.done() // return any held ajax or jserr events so they can be sent with EoL harvest
48
- }, { agentIdentifier, ee: this.ee })
46
+ }, this)
49
47
  scheduler.harvest.on('events', this.onHarvestStarted.bind(this))
50
48
  scheduler.startTimer(harvestTimeSeconds, 0)
51
49
  } else {
52
50
  this.blocked = true // if rum response determines that customer lacks entitlements for spa endpoint, this feature shouldn't harvest
53
- deregisterDrain(this.agentIdentifier, this.featureName)
51
+ this.deregisterDrain()
54
52
  }
55
53
  })
56
54
 
@@ -18,8 +18,8 @@ const UI_WAIT_INTERVAL = 1 / 10 * 1000 // assume 10 fps
18
18
 
19
19
  export class Instrument extends InstrumentBase {
20
20
  static featureName = FEATURE_NAME
21
- constructor (agentIdentifier, aggregator, auto = true) {
22
- super(agentIdentifier, aggregator, FEATURE_NAME, auto)
21
+ constructor (agentRef, auto = true) {
22
+ super(agentRef, FEATURE_NAME, auto)
23
23
  if (!isBrowserScope || !gosNREUMOriginals().o.MO) return // soft navigations is not supported outside web env or browsers without the mutation observer API
24
24
 
25
25
  const historyEE = wrapHistory(this.ee)
@@ -58,7 +58,7 @@ export class Instrument extends InstrumentBase {
58
58
  for (let eventType of INTERACTION_TRIGGERS) document.addEventListener(eventType, () => { /* no-op, this ensures the UI events are monitored by our callback above */ })
59
59
 
60
60
  this.abortHandler = abort
61
- this.importAggregator({ domObserver })
61
+ this.importAggregator(agentRef, { domObserver })
62
62
 
63
63
  function abort () {
64
64
  this.removeOnAbort?.abort()
@@ -9,8 +9,6 @@ import { shouldCollectEvent } from '../../../common/deny-list/deny-list'
9
9
  import { navTimingValues as navTiming } from '../../../common/timing/nav-timing'
10
10
  import { generateUuid } from '../../../common/ids/unique-id'
11
11
  import { Interaction } from './interaction'
12
- import { getConfigurationValue } from '../../../common/config/init'
13
- import { getRuntime } from '../../../common/config/runtime'
14
12
  import { eventListenerOpts } from '../../../common/event-listener/event-listener-opts'
15
13
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
16
14
  import { Serializer } from './serializer'
@@ -24,7 +22,6 @@ import { bundleId } from '../../../common/ids/bundle-id'
24
22
  import { loadedAsDeferredBrowserScript } from '../../../common/constants/runtime'
25
23
  import { handle } from '../../../common/event-emitter/handle'
26
24
  import { SUPPORTABILITY_METRIC_CHANNEL } from '../../metrics/constants'
27
- import { deregisterDrain } from '../../../common/drain/drain'
28
25
  import { warn } from '../../../common/util/console'
29
26
  import { EventBuffer } from '../../utils/event-buffer'
30
27
 
@@ -34,13 +31,12 @@ const {
34
31
  } = CONSTANTS
35
32
  export class Aggregate extends AggregateBase {
36
33
  static featureName = FEATURE_NAME
37
- constructor (agentIdentifier, aggregator) {
38
- super(agentIdentifier, aggregator, FEATURE_NAME)
34
+ constructor (agentRef) {
35
+ super(agentRef, FEATURE_NAME)
39
36
 
40
- const agentRuntime = getRuntime(agentIdentifier)
41
37
  this.state = {
42
- initialPageURL: agentRuntime.origin,
43
- lastSeenUrl: agentRuntime.origin,
38
+ initialPageURL: agentRef.runtime.origin,
39
+ lastSeenUrl: agentRef.runtime.origin,
44
40
  lastSeenRouteName: null,
45
41
  timerMap: {},
46
42
  timerBudget: MAX_TIMER_BUDGET,
@@ -51,10 +47,10 @@ export class Aggregate extends AggregateBase {
51
47
  pageLoaded: false,
52
48
  childTime: 0,
53
49
  depth: 0,
54
- harvestTimeSeconds: getConfigurationValue(agentIdentifier, 'spa.harvestTimeSeconds') || 10,
50
+ harvestTimeSeconds: agentRef.init.spa.harvestTimeSeconds || 10,
55
51
  interactionsToHarvest: new EventBuffer(),
56
52
  // The below feature flag is used to disable the SPA ajax fix for specific customers, see https://new-relic.atlassian.net/browse/NR-172169
57
- disableSpaFix: (getConfigurationValue(agentIdentifier, 'feature_flags') || []).indexOf('disable-spa-fix') > -1
53
+ disableSpaFix: (agentRef.init.feature_flags || []).indexOf('disable-spa-fix') > -1
58
54
  }
59
55
 
60
56
  let scheduler
@@ -62,7 +58,7 @@ export class Aggregate extends AggregateBase {
62
58
 
63
59
  const { state, serializer } = this
64
60
 
65
- const baseEE = ee.get(agentIdentifier) // <-- parent baseEE
61
+ const baseEE = ee.get(agentRef.agentIdentifier) // <-- parent baseEE
66
62
  const mutationEE = baseEE.get('mutation')
67
63
  const promiseEE = baseEE.get('promise')
68
64
  const historyEE = baseEE.get('history')
@@ -110,18 +106,18 @@ export class Aggregate extends AggregateBase {
110
106
  scheduler = new HarvestScheduler('events', {
111
107
  onFinished: onHarvestFinished,
112
108
  retryDelay: state.harvestTimeSeconds
113
- }, { agentIdentifier, ee: baseEE })
109
+ }, this)
114
110
  scheduler.harvest.on('events', onHarvestStarted)
115
111
  this.drain()
116
112
  } else {
117
113
  this.blocked = true
118
- deregisterDrain(this.agentIdentifier, this.featureName)
114
+ this.deregisterDrain()
119
115
  }
120
116
  })
121
117
 
122
- if (!isEnabled()) return
118
+ if (agentRef.init.spa.enabled !== true) return
123
119
 
124
- state.initialPageLoad = new Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
120
+ state.initialPageLoad = new Interaction('initialPageLoad', 0, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier)
125
121
  state.initialPageLoad.save = true
126
122
  state.prevInteraction = state.initialPageLoad
127
123
  state.currentNode = state.initialPageLoad.root // hint
@@ -212,7 +208,7 @@ export class Aggregate extends AggregateBase {
212
208
  // Otherwise, if no interaction is currently active, create a new node ID,
213
209
  // and let the aggregator know that we entered a new event handler callback
214
210
  // so that it has a chance to possibly start an interaction.
215
- var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
211
+ var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier)
216
212
 
217
213
  // Store the interaction as prevInteraction in case it is prematurely discarded
218
214
  state.prevInteraction = ixn
@@ -310,7 +306,7 @@ export class Aggregate extends AggregateBase {
310
306
  this.sent = true
311
307
  node.dt = this.dt
312
308
  if (node.dt?.timestamp) {
313
- node.dt.timestamp = agentRuntime.timeKeeper.correctAbsoluteTimestamp(node.dt.timestamp)
309
+ node.dt.timestamp = agentRef.runtime.timeKeeper.correctAbsoluteTimestamp(node.dt.timestamp)
314
310
  }
315
311
  node.jsEnd = node.start = this.startTime
316
312
  node[INTERACTION][REMAINING]++
@@ -410,7 +406,7 @@ export class Aggregate extends AggregateBase {
410
406
  if (dtPayload && this[SPA_NODE]) {
411
407
  this[SPA_NODE].dt = dtPayload
412
408
  if (this[SPA_NODE].dt?.timestamp) {
413
- this[SPA_NODE].dt.timestamp = agentRuntime.timeKeeper.correctAbsoluteTimestamp(this[SPA_NODE].dt.timestamp)
409
+ this[SPA_NODE].dt.timestamp = agentRef.runtime.timeKeeper.correctAbsoluteTimestamp(this[SPA_NODE].dt.timestamp)
414
410
  }
415
411
  }
416
412
  }
@@ -548,7 +544,7 @@ export class Aggregate extends AggregateBase {
548
544
  var interaction
549
545
  if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION]
550
546
  else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION]
551
- else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
547
+ else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentRef.agentIdentifier)
552
548
  if (!state.currentNode) {
553
549
  interaction.checkFinish()
554
550
  if (state.depth) setCurrentNode(interaction.root)
@@ -702,9 +698,9 @@ export class Aggregate extends AggregateBase {
702
698
  register('function-err', function (args, obj, error) {
703
699
  if (!state.currentNode) return
704
700
  error.__newrelic ??= {}
705
- error.__newrelic[agentIdentifier] = { interactionId: state.currentNode.interaction.id }
701
+ error.__newrelic[agentRef.agentIdentifier] = { interactionId: state.currentNode.interaction.id }
706
702
  if (state.currentNode.type && state.currentNode.type !== 'interaction') {
707
- error.__newrelic[agentIdentifier].interactionNodeId = state.currentNode.id
703
+ error.__newrelic[agentRef.agentIdentifier].interactionNodeId = state.currentNode.id
708
704
  }
709
705
  }, this.featureName, baseEE)
710
706
 
@@ -751,10 +747,5 @@ export class Aggregate extends AggregateBase {
751
747
  scheduler?.scheduleHarvest(0)
752
748
  if (!scheduler) warn(19)
753
749
  }
754
-
755
- function isEnabled () {
756
- var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled')
757
- return enabled !== false
758
- }
759
750
  }
760
751
  }
@@ -25,8 +25,8 @@ const {
25
25
  */
26
26
  export class Instrument extends InstrumentBase {
27
27
  static featureName = FEATURE_NAME
28
- constructor (agentIdentifier, aggregator, auto = true) {
29
- super(agentIdentifier, aggregator, FEATURE_NAME, auto)
28
+ constructor (agentRef, auto = true) {
29
+ super(agentRef, FEATURE_NAME, auto)
30
30
  if (!isBrowserScope) return // SPA not supported outside web env
31
31
 
32
32
  try {
@@ -54,7 +54,7 @@ export class Instrument extends InstrumentBase {
54
54
  promiseEE.on(CB_END, endTimestamp)
55
55
  jsonpEE.on(CB_END, endTimestamp)
56
56
 
57
- this.ee.on('fn-err', (...args) => { if (!args[2]?.__newrelic?.[agentIdentifier]) handle('function-err', [...args], undefined, this.featureName, this.ee) })
57
+ this.ee.on('fn-err', (...args) => { if (!args[2]?.__newrelic?.[agentRef.agentIdentifier]) handle('function-err', [...args], undefined, this.featureName, this.ee) })
58
58
 
59
59
  this.ee.buffer([FN_START, FN_END, 'xhr-resolved'], this.featureName)
60
60
  eventsEE.buffer([FN_START], this.featureName)
@@ -110,7 +110,7 @@ export class Instrument extends InstrumentBase {
110
110
  }
111
111
 
112
112
  this.abortHandler = this.#abort
113
- this.importAggregator()
113
+ this.importAggregator(agentRef)
114
114
  }
115
115
 
116
116
  /** Restoration and resource release tasks to be done if SPA loader is being aborted. Unwind changes to globals and subscription to DOM events. */
@@ -1,6 +1,5 @@
1
- export const FeatureBase = jest.fn(function (agentIdentifier, aggregator, featureName) {
1
+ export const FeatureBase = jest.fn(function (agentIdentifier, featureName) {
2
2
  this.agentIdentifier = agentIdentifier
3
- this.aggregator = aggregator
4
3
  this.featureName = featureName
5
4
 
6
5
  this.ee = {
@@ -1,17 +1,17 @@
1
1
  import { FeatureBase } from './feature-base'
2
- import { getInfo, isValid } from '../../common/config/info'
3
- import { getRuntime } from '../../common/config/runtime'
2
+ import { isValid } from '../../common/config/info'
4
3
  import { configure } from '../../loaders/configure/configure'
5
4
  import { gosCDN } from '../../common/window/nreum'
6
- import { deregisterDrain, drain } from '../../common/drain/drain'
5
+ import { drain } from '../../common/drain/drain'
7
6
  import { activatedFeatures } from '../../common/util/feature-flags'
8
7
  import { Obfuscator } from '../../common/util/obfuscate'
9
8
 
10
9
  export class AggregateBase extends FeatureBase {
11
- constructor (...args) {
12
- super(...args)
13
- this.checkConfiguration()
14
- this.obfuscator = getRuntime(this.agentIdentifier).obfuscator
10
+ constructor (agentRef, featureName) {
11
+ super(agentRef.agentIdentifier, featureName)
12
+ this.agentRef = agentRef
13
+ this.checkConfiguration(agentRef)
14
+ this.obfuscator = agentRef.runtime.obfuscator
15
15
  }
16
16
 
17
17
  /**
@@ -38,7 +38,7 @@ export class AggregateBase extends FeatureBase {
38
38
  return flagsPromise.catch(err => {
39
39
  this.ee.emit('internal-error', [err])
40
40
  this.blocked = true
41
- deregisterDrain(this.agentIdentifier, this.featureName)
41
+ this.deregisterDrain()
42
42
  })
43
43
  }
44
44
 
@@ -51,7 +51,7 @@ export class AggregateBase extends FeatureBase {
51
51
  * Checks for additional `jsAttributes` items to support backward compatibility with implementations of the agent where
52
52
  * loader configurations may appear after the loader code is executed.
53
53
  */
54
- checkConfiguration () {
54
+ checkConfiguration (existingAgent) {
55
55
  // NOTE: This check has to happen at aggregator load time
56
56
  if (!isValid(this.agentIdentifier)) {
57
57
  const cdn = gosCDN()
@@ -59,7 +59,7 @@ export class AggregateBase extends FeatureBase {
59
59
  try {
60
60
  jsAttributes = {
61
61
  ...jsAttributes,
62
- ...getInfo(this.agentIdentifier)?.jsAttributes
62
+ ...existingAgent.info?.jsAttributes
63
63
  }
64
64
  } catch (err) {
65
65
  // do nothing
@@ -70,13 +70,12 @@ export class AggregateBase extends FeatureBase {
70
70
  ...cdn.info,
71
71
  jsAttributes
72
72
  },
73
- runtime: getRuntime(this.agentIdentifier)
73
+ runtime: existingAgent.runtime
74
74
  })
75
75
  }
76
76
 
77
- const runtime = getRuntime(this.agentIdentifier)
78
- if (!runtime.obfuscator) {
79
- runtime.obfuscator = new Obfuscator(this.agentIdentifier)
77
+ if (!existingAgent.runtime.obfuscator) {
78
+ existingAgent.runtime.obfuscator = new Obfuscator(this.agentIdentifier)
80
79
  }
81
80
  }
82
81
  }
@@ -1,11 +1,10 @@
1
1
  import { ee } from '../../common/event-emitter/contextual-ee'
2
+ import { deregisterDrain } from '../../common/drain/drain'
2
3
 
3
4
  export class FeatureBase {
4
- constructor (agentIdentifier, aggregator, featureName) {
5
+ constructor (agentIdentifier, featureName) {
5
6
  /** @type {string} */
6
7
  this.agentIdentifier = agentIdentifier
7
- /** @type {import('../../common/aggregate/aggregator').Aggregator} */
8
- this.aggregator = aggregator
9
8
  /** @type {import('../../common/event-emitter/contextual-ee').ee} */
10
9
  this.ee = ee.get(agentIdentifier)
11
10
  /** @type {string} */
@@ -17,4 +16,8 @@ export class FeatureBase {
17
16
  */
18
17
  this.blocked = false
19
18
  }
19
+
20
+ deregisterDrain () {
21
+ deregisterDrain(this.agentIdentifier, this.featureName)
22
+ }
20
23
  }
@@ -10,7 +10,6 @@ import { onWindowLoad } from '../../common/window/load'
10
10
  import { isBrowserScope } from '../../common/constants/runtime'
11
11
  import { warn } from '../../common/util/console'
12
12
  import { FEATURE_NAMES } from '../../loaders/features/features'
13
- import { getConfigurationValue } from '../../common/config/init'
14
13
  import { hasReplayPrerequisite } from '../session_replay/shared/utils'
15
14
  import { canEnableSessionTracking } from './feature-gates'
16
15
  import { single } from '../../common/util/invoke'
@@ -23,14 +22,13 @@ export class InstrumentBase extends FeatureBase {
23
22
  /**
24
23
  * Instantiate InstrumentBase.
25
24
  * @param {string} agentIdentifier - The unique ID of the instantiated agent (relative to global scope).
26
- * @param {import('../../common/aggregate/aggregator').Aggregator} aggregator - The shared Aggregator that will handle batching and reporting of data.
27
25
  * @param {string} featureName - The name of the feature module (used to construct file path).
28
26
  * @param {boolean} [auto=true] - Determines whether the feature should automatically register to have the draining
29
27
  * of its pooled instrumentation data handled by the agent's centralized drain functionality, rather than draining
30
28
  * immediately. Primarily useful for fine-grained control in tests.
31
29
  */
32
- constructor (agentIdentifier, aggregator, featureName, auto = true) {
33
- super(agentIdentifier, aggregator, featureName)
30
+ constructor (agentRef, featureName, auto = true) {
31
+ super(agentRef.agentIdentifier, featureName)
34
32
  this.auto = auto
35
33
 
36
34
  /** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
@@ -50,16 +48,16 @@ export class InstrumentBase extends FeatureBase {
50
48
  this.onAggregateImported = undefined
51
49
 
52
50
  /** used in conjunction with newrelic.start() to defer harvesting in features */
53
- if (getConfigurationValue(this.agentIdentifier, `${this.featureName}.autoStart`) === false) this.auto = false
51
+ if (agentRef.init[this.featureName].autoStart === false) this.auto = false
54
52
  /** if the feature requires opt-in (!auto-start), it will get registered once the api has been called */
55
- if (this.auto) registerDrain(agentIdentifier, featureName)
53
+ if (this.auto) registerDrain(agentRef.agentIdentifier, featureName)
56
54
  else {
57
55
  this.ee.on('manual-start-all', single(() => {
58
56
  // register the feature to drain only once the API has been called, it will drain when importAggregator finishes for all the features
59
57
  // called by the api in that cycle
60
- registerDrain(this.agentIdentifier, this.featureName)
58
+ registerDrain(agentRef.agentIdentifier, this.featureName)
61
59
  this.auto = true
62
- this.importAggregator()
60
+ this.importAggregator(agentRef)
63
61
  }))
64
62
  }
65
63
  }
@@ -67,10 +65,11 @@ export class InstrumentBase extends FeatureBase {
67
65
  /**
68
66
  * Lazy-load the latter part of the feature: its aggregator. This method is called by the first part of the feature
69
67
  * (the instrumentation) when instrumentation is complete.
68
+ * @param agentRef - reference to the base agent ancestor that this feature belongs to
70
69
  * @param {Object} [argsObjFromInstrument] - any values or references to pass down to aggregate
71
70
  * @returns void
72
71
  */
73
- importAggregator (argsObjFromInstrument = {}) {
72
+ importAggregator (agentRef, argsObjFromInstrument = {}) {
74
73
  if (this.featAggregate || !this.auto) return
75
74
 
76
75
  let loadedSuccessfully
@@ -91,6 +90,13 @@ export class InstrumentBase extends FeatureBase {
91
90
  if (this.featureName === FEATURE_NAMES.sessionReplay) this.abortHandler?.() // SR should stop recording if session DNE
92
91
  }
93
92
 
93
+ // Create a single Aggregator for this agent if DNE yet; to be used by jserror endpoint features.
94
+ if (!agentRef.sharedAggregator) {
95
+ agentRef.sharedAggregator = import(/* webpackChunkName: "shared-aggregator" */ '../../common/aggregate/aggregator')
96
+ const { Aggregator } = await agentRef.sharedAggregator
97
+ agentRef.sharedAggregator = new Aggregator()
98
+ } else await agentRef.sharedAggregator // if another feature is already importing the aggregator, wait for it to finish
99
+
94
100
  /**
95
101
  * Note this try-catch differs from the one in Agent.run() in that it's placed later in a page's lifecycle and
96
102
  * it's only responsible for aborting its one specific feature, rather than all.
@@ -103,7 +109,7 @@ export class InstrumentBase extends FeatureBase {
103
109
  }
104
110
  const { lazyFeatureLoader } = await import(/* webpackChunkName: "lazy-feature-loader" */ './lazy-feature-loader')
105
111
  const { Aggregate } = await lazyFeatureLoader(this.featureName, 'aggregate')
106
- this.featAggregate = new Aggregate(this.agentIdentifier, this.aggregator, argsObjFromInstrument)
112
+ this.featAggregate = new Aggregate(agentRef, argsObjFromInstrument)
107
113
  loadedSuccessfully(true)
108
114
  } catch (e) {
109
115
  warn(34, e)
@@ -10,7 +10,6 @@ import { featurePriority, FEATURE_NAMES } from './features/features'
10
10
  // required features
11
11
  import { Instrument as PageViewEvent } from '../features/page_view_event/instrument'
12
12
  // common files
13
- import { Aggregator } from '../common/aggregate/aggregator'
14
13
  import { gosNREUM, setNREUMInitializedAgent } from '../common/window/nreum'
15
14
  import { warn } from '../common/util/console'
16
15
  import { globalScope } from '../common/constants/runtime'
@@ -34,7 +33,6 @@ export class Agent extends AgentBase {
34
33
  return
35
34
  }
36
35
 
37
- this.sharedAggregator = new Aggregator({ agentIdentifier: this.agentIdentifier })
38
36
  this.features = {}
39
37
  setNREUMInitializedAgent(this.agentIdentifier, this) // append this agent onto the global NREUM.initializedAgents
40
38
 
@@ -80,7 +78,7 @@ export class Agent extends AgentBase {
80
78
  })
81
79
  }
82
80
 
83
- this.features[InstrumentCtor.featureName] = new InstrumentCtor(this.agentIdentifier, this.sharedAggregator)
81
+ this.features[InstrumentCtor.featureName] = new InstrumentCtor(this)
84
82
  })
85
83
  } catch (err) {
86
84
  warn(22, err)
@@ -3,7 +3,6 @@ import { Instrument as PVE } from '../features/page_view_event/instrument'
3
3
  import { getEnabledFeatures } from './features/enabled-features'
4
4
  import { configure } from './configure/configure'
5
5
  // core files
6
- import { Aggregator } from '../common/aggregate/aggregator'
7
6
  import { setNREUMInitializedAgent } from '../common/window/nreum'
8
7
  import { getInfo } from '../common/config/info'
9
8
  import { getConfiguration, getConfigurationValue } from '../common/config/init'
@@ -11,7 +10,6 @@ import { getLoaderConfig } from '../common/config/loader-config'
11
10
  import { getRuntime } from '../common/config/runtime'
12
11
  import { FEATURE_NAMES } from './features/features'
13
12
  import { warn } from '../common/util/console'
14
- import { onWindowLoad } from '../common/window/load'
15
13
  import { AgentBase } from './agent-base'
16
14
 
17
15
  const nonAutoFeatures = [
@@ -34,7 +32,6 @@ export class MicroAgent extends AgentBase {
34
32
  constructor (options, agentIdentifier) {
35
33
  super(agentIdentifier)
36
34
 
37
- this.sharedAggregator = new Aggregator({ agentIdentifier: this.agentIdentifier })
38
35
  this.features = {}
39
36
  setNREUMInitializedAgent(this.agentIdentifier, this)
40
37
 
@@ -77,21 +74,22 @@ export class MicroAgent extends AgentBase {
77
74
 
78
75
  try {
79
76
  // a biproduct of doing this is that the "session manager" is automatically handled through importing this feature
80
- this.features.page_view_event = new PVE(this.agentIdentifier, this.sharedAggregator)
77
+ this.features.page_view_event = new PVE(this)
81
78
  } catch (err) {
82
79
  warn(24, err)
83
80
  }
84
81
 
85
- onWindowLoad(() => {
86
- // these features do not import an "instrument" file, meaning they are only hooked up to the API.
82
+ this.features.page_view_event.onAggregateImported.then(() => {
83
+ /* The following features do not import an "instrument" file, meaning they are only hooked up to the API.
84
+ Since the missing instrument-base class handles drain-gating (racing behavior) and PVE handles some setup, these are chained until after PVE has finished initializing
85
+ so as to avoid the race condition of things like session and sharedAggregator not being ready by features that uses them right away. */
87
86
  nonAutoFeatures.forEach(f => {
88
87
  if (enabledFeatures[f] && features.includes(f)) {
89
88
  import(/* webpackChunkName: "lazy-feature-loader" */ '../features/utils/lazy-feature-loader').then(({ lazyFeatureLoader }) => {
90
89
  return lazyFeatureLoader(f, 'aggregate')
91
90
  }).then(({ Aggregate }) => {
92
- this.features[f] = new Aggregate(this.agentIdentifier, this.sharedAggregator)
93
- }).catch(err =>
94
- warn(25, err))
91
+ this.features[f] = new Aggregate(this)
92
+ }).catch(err => warn(25, err))
95
93
  }
96
94
  })
97
95
  })