@newrelic/browser-agent 1.237.1 → 1.239.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 (307) hide show
  1. package/dist/cjs/common/config/state/init.js +21 -13
  2. package/dist/cjs/common/config/state/runtime.js +0 -4
  3. package/dist/cjs/common/constants/env.cdn.js +1 -1
  4. package/dist/cjs/common/constants/env.npm.js +1 -1
  5. package/dist/cjs/common/constants/runtime.js +3 -3
  6. package/dist/cjs/common/constants/shared-channel.js +3 -1
  7. package/dist/cjs/common/deny-list/deny-list.js +3 -9
  8. package/dist/cjs/common/drain/drain.js +1 -1
  9. package/dist/cjs/common/event-emitter/contextual-ee.js +24 -32
  10. package/dist/cjs/common/event-emitter/event-context.js +12 -0
  11. package/dist/cjs/common/harvest/harvest-scheduler.js +2 -4
  12. package/dist/cjs/common/harvest/harvest.js +4 -7
  13. package/dist/cjs/common/ids/bundle-id.js +19 -0
  14. package/dist/cjs/common/serialize/bel-serializer.js +1 -1
  15. package/dist/cjs/common/session/session-entity.js +16 -12
  16. package/dist/cjs/common/storage/first-party-cookies.js +5 -4
  17. package/dist/cjs/common/storage/local-storage.js +3 -2
  18. package/dist/cjs/common/timer/interaction-timer.js +14 -6
  19. package/dist/cjs/common/timing/nav-timing.js +1 -1
  20. package/dist/cjs/common/unload/eol.js +4 -30
  21. package/dist/cjs/common/util/feature-flags.js +14 -15
  22. package/dist/cjs/common/util/invoke.js +3 -1
  23. package/dist/cjs/common/util/obfuscate.js +3 -5
  24. package/dist/cjs/common/util/traverse.js +1 -0
  25. package/dist/cjs/common/window/page-visibility.js +1 -2
  26. package/dist/cjs/common/wrap/wrap-events.js +3 -2
  27. package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
  28. package/dist/cjs/common/wrap/wrap-function.js +15 -46
  29. package/dist/cjs/common/wrap/wrap-jsonp.js +1 -1
  30. package/dist/cjs/common/wrap/wrap-mutation.js +1 -2
  31. package/dist/cjs/common/wrap/wrap-promise.js +2 -3
  32. package/dist/cjs/common/wrap/wrap-xhr.js +23 -27
  33. package/dist/cjs/features/ajax/aggregate/index.js +5 -7
  34. package/dist/cjs/features/ajax/instrument/distributed-tracing.js +8 -12
  35. package/dist/cjs/features/ajax/instrument/index.js +66 -24
  36. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +0 -1
  37. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +4 -4
  38. package/dist/cjs/features/jserrors/aggregate/index.js +4 -5
  39. package/dist/cjs/features/metrics/aggregate/framework-detection.js +103 -7
  40. package/dist/cjs/features/metrics/aggregate/index.js +20 -37
  41. package/dist/cjs/features/metrics/instrument/index.js +0 -2
  42. package/dist/cjs/features/page_action/aggregate/index.js +17 -19
  43. package/dist/cjs/features/page_view_event/aggregate/index.js +1 -2
  44. package/dist/cjs/features/page_view_event/instrument/index.js +4 -2
  45. package/dist/cjs/features/page_view_timing/aggregate/index.js +6 -7
  46. package/dist/cjs/features/session_replay/aggregate/index.js +5 -3
  47. package/dist/cjs/features/session_trace/aggregate/index.js +22 -16
  48. package/dist/cjs/features/spa/aggregate/index.js +14 -20
  49. package/dist/cjs/features/spa/aggregate/interaction.js +0 -2
  50. package/dist/cjs/features/spa/aggregate/serializer.js +1 -1
  51. package/dist/cjs/features/utils/aggregate-base.js +4 -0
  52. package/dist/cjs/features/utils/handler-cache.js +3 -1
  53. package/dist/cjs/features/utils/instrument-base.js +24 -6
  54. package/dist/cjs/loaders/agent-base.js +23 -0
  55. package/dist/cjs/loaders/agent.js +7 -7
  56. package/dist/cjs/loaders/api/api.js +34 -4
  57. package/dist/cjs/loaders/api/apiAsync.js +19 -20
  58. package/dist/cjs/loaders/api/interaction-types.js +11 -4
  59. package/dist/cjs/loaders/configure/configure.js +3 -0
  60. package/dist/cjs/loaders/micro-agent.js +20 -3
  61. package/dist/esm/common/config/state/init.js +21 -13
  62. package/dist/esm/common/config/state/runtime.js +0 -4
  63. package/dist/esm/common/constants/env.cdn.js +1 -1
  64. package/dist/esm/common/constants/env.npm.js +1 -1
  65. package/dist/esm/common/constants/runtime.js +1 -1
  66. package/dist/esm/common/constants/shared-channel.js +3 -1
  67. package/dist/esm/common/deny-list/deny-list.js +3 -9
  68. package/dist/esm/common/drain/drain.js +1 -1
  69. package/dist/esm/common/event-emitter/contextual-ee.js +22 -29
  70. package/dist/esm/common/event-emitter/event-context.js +5 -0
  71. package/dist/esm/common/harvest/harvest-scheduler.js +2 -4
  72. package/dist/esm/common/harvest/harvest.js +4 -7
  73. package/dist/esm/common/ids/bundle-id.js +13 -0
  74. package/dist/esm/common/serialize/bel-serializer.js +1 -1
  75. package/dist/esm/common/session/session-entity.js +16 -12
  76. package/dist/esm/common/storage/first-party-cookies.js +5 -4
  77. package/dist/esm/common/storage/local-storage.js +3 -2
  78. package/dist/esm/common/timer/interaction-timer.js +14 -6
  79. package/dist/esm/common/timing/nav-timing.js +1 -1
  80. package/dist/esm/common/unload/eol.js +5 -31
  81. package/dist/esm/common/util/feature-flags.js +14 -15
  82. package/dist/esm/common/util/invoke.js +3 -1
  83. package/dist/esm/common/util/obfuscate.js +3 -5
  84. package/dist/esm/common/util/traverse.js +1 -0
  85. package/dist/esm/common/window/page-visibility.js +1 -2
  86. package/dist/esm/common/wrap/wrap-events.js +4 -3
  87. package/dist/esm/common/wrap/wrap-fetch.js +2 -4
  88. package/dist/esm/common/wrap/wrap-function.js +15 -44
  89. package/dist/esm/common/wrap/wrap-jsonp.js +1 -1
  90. package/dist/esm/common/wrap/wrap-mutation.js +2 -3
  91. package/dist/esm/common/wrap/wrap-promise.js +3 -4
  92. package/dist/esm/common/wrap/wrap-xhr.js +23 -27
  93. package/dist/esm/features/ajax/aggregate/index.js +5 -7
  94. package/dist/esm/features/ajax/instrument/distributed-tracing.js +8 -12
  95. package/dist/esm/features/ajax/instrument/index.js +67 -25
  96. package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +0 -1
  97. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +4 -4
  98. package/dist/esm/features/jserrors/aggregate/index.js +4 -5
  99. package/dist/esm/features/metrics/aggregate/framework-detection.js +103 -7
  100. package/dist/esm/features/metrics/aggregate/index.js +22 -39
  101. package/dist/esm/features/metrics/instrument/index.js +1 -3
  102. package/dist/esm/features/page_action/aggregate/index.js +17 -19
  103. package/dist/esm/features/page_view_event/aggregate/index.js +1 -2
  104. package/dist/esm/features/page_view_event/instrument/index.js +4 -2
  105. package/dist/esm/features/page_view_timing/aggregate/index.js +7 -8
  106. package/dist/esm/features/session_replay/aggregate/index.js +4 -2
  107. package/dist/esm/features/session_trace/aggregate/index.js +22 -16
  108. package/dist/esm/features/spa/aggregate/index.js +14 -20
  109. package/dist/esm/features/spa/aggregate/interaction.js +0 -2
  110. package/dist/esm/features/spa/aggregate/serializer.js +1 -1
  111. package/dist/esm/features/utils/aggregate-base.js +4 -0
  112. package/dist/esm/features/utils/handler-cache.js +3 -1
  113. package/dist/esm/features/utils/instrument-base.js +24 -6
  114. package/dist/esm/loaders/agent-base.js +23 -0
  115. package/dist/esm/loaders/agent.js +7 -7
  116. package/dist/esm/loaders/api/api.js +34 -4
  117. package/dist/esm/loaders/api/apiAsync.js +19 -20
  118. package/dist/esm/loaders/api/interaction-types.js +11 -4
  119. package/dist/esm/loaders/configure/configure.js +3 -0
  120. package/dist/esm/loaders/features/enabled-features.js +1 -1
  121. package/dist/esm/loaders/micro-agent.js +21 -4
  122. package/dist/types/common/config/state/init.d.ts.map +1 -1
  123. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  124. package/dist/types/common/constants/runtime.d.ts +1 -1
  125. package/dist/types/common/constants/runtime.d.ts.map +1 -1
  126. package/dist/types/common/event-emitter/contextual-ee.d.ts +22 -2
  127. package/dist/types/common/event-emitter/contextual-ee.d.ts.map +1 -1
  128. package/dist/types/common/event-emitter/event-context.d.ts +5 -0
  129. package/dist/types/common/event-emitter/event-context.d.ts.map +1 -0
  130. package/dist/types/common/event-emitter/register-handler.d.ts +1 -1
  131. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  132. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  133. package/dist/types/common/ids/bundle-id.d.ts +5 -0
  134. package/dist/types/common/ids/bundle-id.d.ts.map +1 -0
  135. package/dist/types/common/session/session-entity.d.ts +12 -15
  136. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  137. package/dist/types/common/storage/first-party-cookies.d.ts +1 -1
  138. package/dist/types/common/storage/first-party-cookies.d.ts.map +1 -1
  139. package/dist/types/common/storage/local-storage.d.ts.map +1 -1
  140. package/dist/types/common/timer/interaction-timer.d.ts +3 -0
  141. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
  142. package/dist/types/common/unload/eol.d.ts +1 -2
  143. package/dist/types/common/unload/eol.d.ts.map +1 -1
  144. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  145. package/dist/types/common/util/obfuscate.d.ts.map +1 -1
  146. package/dist/types/common/util/traverse.d.ts.map +1 -1
  147. package/dist/types/common/window/nreum.d.ts +2 -2
  148. package/dist/types/common/window/page-visibility.d.ts.map +1 -1
  149. package/dist/types/common/wrap/wrap-events.d.ts.map +1 -1
  150. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  151. package/dist/types/common/wrap/wrap-function.d.ts +1 -19
  152. package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
  153. package/dist/types/common/wrap/wrap-mutation.d.ts.map +1 -1
  154. package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
  155. package/dist/types/common/wrap/wrap-xhr.d.ts.map +1 -1
  156. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  157. package/dist/types/features/ajax/instrument/distributed-tracing.d.ts +1 -1
  158. package/dist/types/features/ajax/instrument/distributed-tracing.d.ts.map +1 -1
  159. package/dist/types/features/ajax/instrument/index.d.ts.map +1 -1
  160. package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts.map +1 -1
  161. package/dist/types/features/jserrors/aggregate/index.d.ts +1 -1
  162. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  163. package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -1
  164. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  165. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  166. package/dist/types/features/page_action/aggregate/index.d.ts +2 -2
  167. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  168. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  169. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  170. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -1
  171. package/dist/types/features/session_trace/aggregate/index.d.ts +5 -0
  172. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  173. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  174. package/dist/types/features/spa/aggregate/interaction.d.ts.map +1 -1
  175. package/dist/types/features/utils/aggregate-base.d.ts +1 -0
  176. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -1
  177. package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
  178. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  179. package/dist/types/loaders/agent-base.d.ts +15 -0
  180. package/dist/types/loaders/agent-base.d.ts.map +1 -1
  181. package/dist/types/loaders/agent.d.ts +1 -1
  182. package/dist/types/loaders/agent.d.ts.map +1 -1
  183. package/dist/types/loaders/api/api.d.ts +7 -0
  184. package/dist/types/loaders/api/api.d.ts.map +1 -1
  185. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  186. package/dist/types/loaders/api/interaction-types.d.ts +18 -7
  187. package/dist/types/loaders/api/interaction-types.d.ts.map +1 -1
  188. package/dist/types/loaders/configure/configure.d.ts +2 -0
  189. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  190. package/dist/types/loaders/features/features.d.ts +9 -9
  191. package/dist/types/loaders/micro-agent.d.ts +7 -1
  192. package/dist/types/loaders/micro-agent.d.ts.map +1 -1
  193. package/package.json +62 -38
  194. package/src/common/aggregate/aggregator.test.js +107 -0
  195. package/src/common/config/state/configurable.test.js +73 -0
  196. package/src/common/config/state/info.test.js +31 -0
  197. package/src/common/config/state/init.js +13 -12
  198. package/src/common/config/state/init.test.js +28 -0
  199. package/src/common/config/state/loader-config.test.js +21 -0
  200. package/src/common/config/state/runtime.js +0 -2
  201. package/src/common/config/state/runtime.test.js +21 -0
  202. package/src/common/constants/__mocks__/runtime.js +1 -1
  203. package/src/common/constants/runtime.js +1 -1
  204. package/src/common/constants/runtime.test.js +2 -2
  205. package/src/common/constants/shared-channel.js +1 -1
  206. package/src/common/deny-list/deny-list.js +3 -11
  207. package/src/common/deny-list/deny-list.test.js +103 -30
  208. package/src/common/drain/drain.js +1 -1
  209. package/src/common/drain/drain.test.js +74 -0
  210. package/src/common/event-emitter/{contextual-ee.test.js → contextual-ee.component-test.js} +15 -32
  211. package/src/common/event-emitter/contextual-ee.js +26 -37
  212. package/src/common/event-emitter/event-context.js +5 -0
  213. package/src/common/harvest/harvest-scheduler.js +2 -5
  214. package/src/common/harvest/harvest-scheduler.test.js +2 -6
  215. package/src/common/harvest/harvest.js +4 -7
  216. package/src/common/harvest/harvest.test.js +1 -3
  217. package/src/common/ids/__mocks__/bundle-id.js +2 -0
  218. package/src/common/ids/__mocks__/unique-id.js +17 -0
  219. package/src/common/ids/bundle-id.js +13 -0
  220. package/src/common/ids/id.test.js +6 -6
  221. package/src/common/serialize/bel-serializer.js +1 -1
  222. package/src/common/session/session-entity.component-test.js +3 -2
  223. package/src/common/session/session-entity.js +11 -9
  224. package/src/common/storage/first-party-cookies.js +5 -4
  225. package/src/common/storage/local-storage.js +3 -2
  226. package/src/common/timer/interaction-timer.component-test.js +52 -7
  227. package/src/common/timer/interaction-timer.js +15 -6
  228. package/src/common/timer/timer.test.js +0 -1
  229. package/src/common/timing/nav-timing.js +1 -1
  230. package/src/common/unload/eol.js +5 -31
  231. package/src/common/url/__mocks__/parse-url.js +15 -0
  232. package/src/common/url/{encode.component-test.js → encode.test.js} +1 -0
  233. package/src/common/util/__mocks__/get-or-set.js +5 -0
  234. package/src/common/util/__mocks__/invoke.js +1 -0
  235. package/src/common/util/data-size.test.js +0 -1
  236. package/src/common/util/feature-flags.js +15 -17
  237. package/src/common/util/feature-flags.test.js +4 -8
  238. package/src/common/util/invoke.js +1 -1
  239. package/src/common/util/obfuscate.js +3 -5
  240. package/src/common/util/submit-data.test.js +1 -1
  241. package/src/common/util/traverse.js +1 -0
  242. package/src/common/window/__mocks__/nreum.js +12 -0
  243. package/src/common/window/page-visibility.js +1 -2
  244. package/src/common/wrap/wrap-events.js +4 -3
  245. package/src/common/wrap/wrap-fetch.js +2 -4
  246. package/src/common/wrap/wrap-function.js +16 -44
  247. package/src/common/wrap/wrap-jsonp.js +1 -1
  248. package/src/common/wrap/wrap-mutation.js +2 -3
  249. package/src/common/wrap/{wrap-promise.test.js → wrap-promise.component-test.js} +2 -32
  250. package/src/common/wrap/wrap-promise.js +3 -4
  251. package/src/common/wrap/wrap-xhr.js +24 -28
  252. package/src/features/ajax/aggregate/index.js +5 -7
  253. package/src/features/ajax/instrument/distributed-tracing.js +8 -12
  254. package/src/features/ajax/instrument/distributed-tracing.test.js +375 -0
  255. package/src/features/ajax/instrument/index.js +62 -27
  256. package/src/features/jserrors/aggregate/canonical-function-name.js +0 -2
  257. package/src/features/jserrors/aggregate/compute-stack-trace.js +4 -4
  258. package/src/features/jserrors/aggregate/compute-stack-trace.test.js +1 -1
  259. package/src/features/jserrors/aggregate/index.js +4 -5
  260. package/src/features/metrics/aggregate/framework-detection.js +129 -8
  261. package/src/features/metrics/aggregate/framework-detection.test.js +213 -82
  262. package/src/features/metrics/aggregate/index.js +22 -45
  263. package/src/features/metrics/instrument/index.js +1 -3
  264. package/src/features/page_action/aggregate/index.js +12 -13
  265. package/src/features/page_view_event/aggregate/index.js +1 -2
  266. package/src/features/page_view_event/instrument/index.js +2 -2
  267. package/src/features/page_view_timing/aggregate/index.js +7 -8
  268. package/src/features/session_replay/aggregate/index.component-test.js +3 -15
  269. package/src/features/session_replay/aggregate/index.js +4 -2
  270. package/src/features/session_trace/aggregate/index.js +22 -16
  271. package/src/features/spa/aggregate/index.js +14 -20
  272. package/src/features/spa/aggregate/interaction.js +0 -2
  273. package/src/features/spa/aggregate/serializer.js +1 -1
  274. package/src/features/utils/aggregate-base.js +5 -0
  275. package/src/features/utils/aggregate-base.test.js +2 -1
  276. package/src/features/utils/handler-cache.js +3 -2
  277. package/src/features/utils/instrument-base.js +25 -6
  278. package/src/features/utils/instrument-base.test.js +2 -2
  279. package/src/loaders/agent-base.js +23 -0
  280. package/src/loaders/agent.js +7 -7
  281. package/src/loaders/api/api.component-test.js +45 -0
  282. package/src/loaders/api/api.js +34 -4
  283. package/src/loaders/api/api.test.js +85 -0
  284. package/src/loaders/api/apiAsync.js +19 -20
  285. package/src/loaders/api/apiAsync.test.js +17 -0
  286. package/src/loaders/api/interaction-types.js +11 -4
  287. package/src/loaders/configure/configure.js +3 -0
  288. package/src/loaders/features/enabled-features.js +1 -1
  289. package/src/loaders/micro-agent.js +22 -4
  290. package/dist/cjs/features/metrics/aggregate/endpoint-map.js +0 -14
  291. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +0 -14
  292. package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +0 -53
  293. package/dist/esm/features/metrics/aggregate/endpoint-map.js +0 -7
  294. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +0 -8
  295. package/dist/esm/features/metrics/aggregate/polyfill-detection.js +0 -47
  296. package/dist/types/features/metrics/aggregate/endpoint-map.d.ts +0 -8
  297. package/dist/types/features/metrics/aggregate/endpoint-map.d.ts.map +0 -1
  298. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +0 -6
  299. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +0 -1
  300. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +0 -7
  301. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +0 -1
  302. package/src/features/metrics/aggregate/endpoint-map.js +0 -7
  303. package/src/features/metrics/aggregate/polyfill-detection.es5.js +0 -8
  304. package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +0 -16
  305. package/src/features/metrics/aggregate/polyfill-detection.js +0 -48
  306. package/src/features/metrics/aggregate/polyfill-detection.test.js +0 -163
  307. /package/src/common/url/{protocol.component-test.js → protocol.test.js} +0 -0
@@ -1,7 +1,5 @@
1
1
  import { InstrumentBase } from '../../utils/instrument-base'
2
- import { FEATURE_NAME, SUPPORTABILITY_METRIC_CHANNEL } from '../constants'
3
- import { handle } from '../../../common/event-emitter/handle'
4
- import { FEATURE_NAMES } from '../../../loaders/features/features'
2
+ import { FEATURE_NAME } from '../constants'
5
3
 
6
4
  export class Instrument extends InstrumentBase {
7
5
  static featureName = FEATURE_NAME
@@ -10,7 +10,6 @@ import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
10
10
  import { cleanURL } from '../../../common/url/clean-url'
11
11
  import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config'
12
12
  import { FEATURE_NAME } from '../constants'
13
- import { drain } from '../../../common/drain/drain'
14
13
  import { isBrowserScope } from '../../../common/constants/runtime'
15
14
  import { AggregateBase } from '../../utils/aggregate-base'
16
15
 
@@ -21,8 +20,8 @@ export class Aggregate extends AggregateBase {
21
20
  this.eventsPerMinute = 240
22
21
  this.harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'page_action.harvestTimeSeconds') || getConfigurationValue(this.agentIdentifier, 'ins.harvestTimeSeconds') || 30
23
22
  this.eventsPerHarvest = this.eventsPerMinute * this.harvestTimeSeconds / 60
24
- this.referrerUrl
25
- this.currentEvents
23
+ this.referrerUrl = undefined
24
+ this.currentEvents = undefined
26
25
 
27
26
  this.events = []
28
27
 
@@ -32,17 +31,17 @@ export class Aggregate extends AggregateBase {
32
31
 
33
32
  register('api-addPageAction', (...args) => this.addPageAction(...args), this.featureName, this.ee)
34
33
 
35
- var scheduler = new HarvestScheduler('ins', { onFinished: (...args) => this.onHarvestFinished(...args) }, this)
36
- scheduler.harvest.on('ins', (...args) => this.onHarvestStarted(...args))
37
- this.ee.on(`drain-${this.featureName}`, () => { if (!this.blocked) scheduler.startTimer(this.harvestTimeSeconds, 0) })
38
-
39
- // if rum response determines that customer lacks entitlements for ins endpoint, block it
40
- register('block-ins', () => {
41
- this.blocked = true
42
- scheduler.stopTimer(true)
43
- }, this.featureName, this.ee)
34
+ this.waitForFlags(['ins']).then(([enabled]) => {
35
+ if (enabled) {
36
+ const scheduler = new HarvestScheduler('ins', { onFinished: (...args) => this.onHarvestFinished(...args) }, this)
37
+ scheduler.harvest.on('ins', (...args) => this.onHarvestStarted(...args))
38
+ scheduler.startTimer(this.harvestTimeSeconds, 0)
39
+ } else {
40
+ this.blocked = true
41
+ }
42
+ })
44
43
 
45
- drain(this.agentIdentifier, this.featureName)
44
+ this.drain()
46
45
  }
47
46
 
48
47
  onHarvestStarted (options) {
@@ -9,7 +9,6 @@ import { getConfigurationValue, getInfo, getRuntime } from '../../../common/conf
9
9
  import { Harvest } from '../../../common/harvest/harvest'
10
10
  import * as CONSTANTS from '../constants'
11
11
  import { getActivatedFeaturesFlags } from './initialized-features'
12
- import { drain } from '../../../common/drain/drain'
13
12
  import { activateFeatures } from '../../../common/util/feature-flags'
14
13
  import { warn } from '../../../common/util/console'
15
14
  import { AggregateBase } from '../../utils/aggregate-base'
@@ -131,7 +130,7 @@ export class Aggregate extends AggregateBase {
131
130
 
132
131
  try {
133
132
  activateFeatures(JSON.parse(responseText), this.agentIdentifier)
134
- drain(this.agentIdentifier, this.featureName)
133
+ this.drain()
135
134
  } catch (err) {
136
135
  this.ee.abort()
137
136
  warn('RUM call failed. Agent shutting down.')
@@ -14,11 +14,11 @@ export class Instrument extends InstrumentBase {
14
14
 
15
15
  if ((typeof PerformanceNavigationTiming === 'undefined' || isiOS) && typeof PerformanceTiming !== 'undefined') {
16
16
  // For majority browser versions in which PNT exists, we can get load timings later from the nav entry (in the aggregate portion). At minimum, PT should exist for main window.
17
- // *cli Mar'23 - iOS 15.2 & 15.4 testing in Sauce still fails with onTTFB. Hence, all iOS will fallback to this for now. Unknown if this is similar in nature to iOS_below16 bug.
17
+ // *cli Mar'23 - iOS 15.2 & 15.4 testing in Sauce still fails with onTTFB. Hence, all iOS will fallback to this for now. Unknown if this is similar in nature to iOSBelow16 bug.
18
18
  const agentRuntime = getRuntime(agentIdentifier)
19
19
 
20
20
  agentRuntime[CONSTANTS.TTFB] = Math.max(Date.now() - agentRuntime.offset, 0)
21
- onDOMContentLoaded(() => agentRuntime[CONSTANTS.FBTDC] = Math.max(now() - agentRuntime[CONSTANTS.TTFB], 0))
21
+ onDOMContentLoaded(() => { agentRuntime[CONSTANTS.FBTDC] = Math.max(now() - agentRuntime[CONSTANTS.TTFB], 0) })
22
22
  onWindowLoad(() => {
23
23
  const timeNow = now()
24
24
  agentRuntime[CONSTANTS.FBTWL] = Math.max(timeNow - agentRuntime[CONSTANTS.TTFB], 0)
@@ -6,7 +6,7 @@
6
6
  import { onFCP, onFID, onLCP, onCLS, onINP } from 'web-vitals'
7
7
  import { onFirstPaint } from '../first-paint'
8
8
  import { onLongTask } from '../long-tasks'
9
- import { iOS_below16 } from '../../../common/constants/runtime'
9
+ import { iOSBelow16 } from '../../../common/constants/runtime'
10
10
  import { nullable, numeric, getAddStringContext, addCustomAttributes } from '../../../common/serialize/bel-serializer'
11
11
  import { mapOwn } from '../../../common/util/map-own'
12
12
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
@@ -15,7 +15,6 @@ import { cleanURL } from '../../../common/url/clean-url'
15
15
  import { handle } from '../../../common/event-emitter/handle'
16
16
  import { getInfo, getConfigurationValue, getRuntime } from '../../../common/config/config'
17
17
  import { FEATURE_NAME } from '../constants'
18
- import { drain } from '../../../common/drain/drain'
19
18
  import { FEATURE_NAMES } from '../../../loaders/features/features'
20
19
  import { AggregateBase } from '../../utils/aggregate-base'
21
20
 
@@ -41,7 +40,7 @@ export class Aggregate extends AggregateBase {
41
40
  })
42
41
 
43
42
  /* First Contentful Paint - As of WV v3, it still imperfectly tries to detect document vis state asap and isn't supposed to report if page starts hidden. */
44
- if (iOS_below16) {
43
+ if (iOSBelow16) {
45
44
  try {
46
45
  if (!pageStartedHidden) { // see ios-version.js for detail on this following bug case; tldr: buffered flag doesn't work but getEntriesByType does
47
46
  const paintEntries = performance.getEntriesByType('paint')
@@ -101,7 +100,7 @@ export class Aggregate extends AggregateBase {
101
100
 
102
101
  /* Cumulative Layout Shift - We don't have to limit this callback since cls is stored as a state and only sent as attribute on other timings.
103
102
  reportAllChanges ensures our tracked cls has the most recent rolling value to attach to 'unload' and 'pagehide'. */
104
- onCLS(({ value }) => this.cls = value, { reportAllChanges: true })
103
+ onCLS(({ value }) => { this.cls = value }, { reportAllChanges: true })
105
104
 
106
105
  /* Interaction-to-Next-Paint */
107
106
  onINP(({ name, value, id }) => this.addTiming(name.toLowerCase(), value, { metricId: id }))
@@ -128,7 +127,7 @@ export class Aggregate extends AggregateBase {
128
127
  // send initial data sooner, then start regular
129
128
  this.ee.on(`drain-${this.featureName}`, () => { this.scheduler.startTimer(harvestTimeSeconds, initialHarvestSeconds) })
130
129
 
131
- drain(this.agentIdentifier, this.featureName)
130
+ this.drain()
132
131
  }
133
132
 
134
133
  // takes an attributes object and appends connection attributes if available
@@ -185,9 +184,9 @@ export class Aggregate extends AggregateBase {
185
184
  }
186
185
 
187
186
  this.timings.push({
188
- name: name,
189
- value: value,
190
- attrs: attrs
187
+ name,
188
+ value,
189
+ attrs
191
190
  })
192
191
 
193
192
  handle('pvtAdded', [name, value, attrs], undefined, FEATURE_NAMES.sessionTrace, this.ee)
@@ -13,6 +13,7 @@ class LocalMemory {
13
13
  try {
14
14
  return this.state[key]
15
15
  } catch (err) {
16
+ // Error is ignored
16
17
  return ''
17
18
  }
18
19
  }
@@ -22,7 +23,7 @@ class LocalMemory {
22
23
  if (value === undefined || value === null) return this.remove(key)
23
24
  this.state[key] = value
24
25
  } catch (err) {
25
- return
26
+ // Error is ignored
26
27
  }
27
28
  }
28
29
 
@@ -30,7 +31,7 @@ class LocalMemory {
30
31
  try {
31
32
  delete this.state[key]
32
33
  } catch (err) {
33
- return
34
+ // Error is ignored
34
35
  }
35
36
  }
36
37
  }
@@ -102,7 +103,6 @@ describe('Session Replay', () => {
102
103
  sr.ee.emit('rumresp-sr', [true])
103
104
  await wait(1)
104
105
  expect(session.state.sessionReplay).toEqual(sr.mode)
105
- return
106
106
  })
107
107
 
108
108
  test('Session SR mode matches SR mode -- OFF', async () => {
@@ -110,7 +110,6 @@ describe('Session Replay', () => {
110
110
  sr.ee.emit('rumresp-sr', [true])
111
111
  await wait(1)
112
112
  expect(session.state.sessionReplay).toEqual(sr.mode)
113
- return
114
113
  })
115
114
  })
116
115
 
@@ -127,7 +126,6 @@ describe('Session Replay', () => {
127
126
  await wait(1)
128
127
  expect(sr.initialized).toEqual(true)
129
128
  expect(sr.recording).toEqual(false)
130
- return
131
129
  })
132
130
 
133
131
  test('Does not run if cookies_enabled is false', async () => {
@@ -137,7 +135,6 @@ describe('Session Replay', () => {
137
135
  await wait(1)
138
136
  expect(sr.initialized).toEqual(false)
139
137
  expect(sr.recording).toEqual(false)
140
- return
141
138
  })
142
139
 
143
140
  test('Does not run if session_trace is disabled', async () => {
@@ -147,7 +144,6 @@ describe('Session Replay', () => {
147
144
  await wait(1)
148
145
  expect(sr.initialized).toEqual(false)
149
146
  expect(sr.recording).toEqual(false)
150
- return
151
147
  })
152
148
  })
153
149
 
@@ -157,7 +153,6 @@ describe('Session Replay', () => {
157
153
  sr.ee.emit('rumresp-sr', [true])
158
154
  await wait(1)
159
155
  expect(sr.mode).toEqual(MODE.FULL)
160
- return
161
156
  })
162
157
 
163
158
  test('New Session -- Full 1 Error 0 === FULL', async () => {
@@ -165,7 +160,6 @@ describe('Session Replay', () => {
165
160
  sr.ee.emit('rumresp-sr', [true])
166
161
  await wait(1)
167
162
  expect(sr.mode).toEqual(MODE.FULL)
168
- return
169
163
  })
170
164
 
171
165
  test('New Session -- Full 0 Error 1 === ERROR', async () => {
@@ -173,7 +167,6 @@ describe('Session Replay', () => {
173
167
  sr.ee.emit('rumresp-sr', [true])
174
168
  await wait(1)
175
169
  expect(sr.mode).toEqual(MODE.ERROR)
176
- return
177
170
  })
178
171
 
179
172
  test('New Session -- Full 0 Error 0 === OFF', async () => {
@@ -181,7 +174,6 @@ describe('Session Replay', () => {
181
174
  sr.ee.emit('rumresp-sr', [true])
182
175
  await wait(1)
183
176
  expect(sr.mode).toEqual(MODE.OFF)
184
- return
185
177
  })
186
178
 
187
179
  test('Existing Session -- Should inherit mode from session entity and ignore samples', async () => {
@@ -194,7 +186,6 @@ describe('Session Replay', () => {
194
186
  sr.ee.emit('rumresp-sr', [true])
195
187
  await wait(1)
196
188
  expect(sr.mode).toEqual(MODE.FULL)
197
- return
198
189
  })
199
190
  })
200
191
 
@@ -206,7 +197,6 @@ describe('Session Replay', () => {
206
197
  await wait(1)
207
198
  expect(sr.mode).toEqual(MODE.FULL)
208
199
  expect(sr.scheduler.started).toEqual(true)
209
- return
210
200
  })
211
201
 
212
202
  test('An error AFTER rrweb import changes mode and starts harvester', async () => {
@@ -218,7 +208,6 @@ describe('Session Replay', () => {
218
208
  sr.ee.emit('errorAgg')
219
209
  expect(sr.mode).toEqual(MODE.FULL)
220
210
  expect(sr.scheduler.started).toEqual(true)
221
- return
222
211
  })
223
212
  })
224
213
 
@@ -296,7 +285,6 @@ describe('Session Replay', () => {
296
285
  const spy = jest.spyOn(sr.scheduler, 'runHarvest')
297
286
  setConfiguration(agentIdentifier, { ...init })
298
287
  sr.payloadBytesEstimation = (MAX_PAYLOAD_SIZE + 1) / AVG_COMPRESSION
299
- const before = Date.now()
300
288
  sr.ee.emit('rumresp-sr', [true])
301
289
  await wait(1)
302
290
  expect(spy).not.toHaveBeenCalled()
@@ -10,7 +10,6 @@
10
10
  * functionality is validated and a full user experience is curated.
11
11
  */
12
12
 
13
- import { drain } from '../../../common/drain/drain'
14
13
  import { registerHandler } from '../../../common/event-emitter/register-handler'
15
14
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
16
15
  import { FEATURE_NAME } from '../constants'
@@ -20,6 +19,7 @@ import { SESSION_EVENTS, MODE } from '../../../common/session/session-entity'
20
19
  import { AggregateBase } from '../../utils/aggregate-base'
21
20
  import { sharedChannel } from '../../../common/constants/shared-channel'
22
21
  import { obj as encodeObj } from '../../../common/url/encode'
22
+ import { warn } from '../../../common/util/console'
23
23
 
24
24
  // would be better to get this dynamically in some way
25
25
  export const RRWEB_VERSION = '2.0.0-alpha.8'
@@ -127,7 +127,7 @@ export class Aggregate extends AggregateBase {
127
127
  Math.random() < getConfigurationValue(this.agentIdentifier, 'session_replay.sampleRate')
128
128
  )).then(() => sharedChannel.onReplayReady(this.mode)) // notify watchers that replay started with the mode
129
129
 
130
- drain(this.agentIdentifier, this.featureName)
130
+ this.drain()
131
131
  }
132
132
  }
133
133
 
@@ -173,12 +173,14 @@ export class Aggregate extends AggregateBase {
173
173
  }
174
174
 
175
175
  try {
176
+ // Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
176
177
  recorder = (await import(/* webpackChunkName: "recorder" */'rrweb')).record
177
178
  } catch (err) {
178
179
  return this.abort()
179
180
  }
180
181
 
181
182
  try {
183
+ // Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
182
184
  const { gzipSync, strToU8 } = await import(/* webpackChunkName: "compressor" */'fflate')
183
185
  gzipper = gzipSync
184
186
  u8 = strToU8
@@ -8,7 +8,6 @@ import { parseUrl } from '../../../common/url/parse-url'
8
8
  import { getConfigurationValue, getRuntime } from '../../../common/config/config'
9
9
  import { now } from '../../../common/timing/now'
10
10
  import { FEATURE_NAME } from '../constants'
11
- import { drain } from '../../../common/drain/drain'
12
11
  import { HandlerCache } from '../../utils/handler-cache'
13
12
  import { MODE, SESSION_EVENTS } from '../../../common/session/session-entity'
14
13
  import { getSessionReplayMode } from '../../session_replay/replay-mode'
@@ -50,9 +49,13 @@ export class Aggregate extends AggregateBase {
50
49
  this.sentTrace = null
51
50
  this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10
52
51
  this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000
52
+ /**
53
+ * Standalone (mode) refers to the legacy version of ST before the idea of 'session' or the Replay feature existed.
54
+ * It has some different behavior vs when used in tandem with replay. */
53
55
  this.isStandalone = false
54
56
  const operationalGate = new HandlerCache() // acts as a controller-intermediary that can enable or disable this feature's collection dynamically
55
57
  const sessionEntity = this.agentRuntime.session
58
+ this.operationalGate = operationalGate
56
59
 
57
60
  /* --- The following section deals with user sessions concept & contains non-trivial control flow. --- */
58
61
  const controlTraceOp = (traceMode) => {
@@ -119,7 +122,7 @@ export class Aggregate extends AggregateBase {
119
122
  else if (updatedTraceMode === MODE.FULL && this.#scheduler && !this.#scheduler.started) this.#scheduler.runHarvest({ needResponse: true })
120
123
  mostRecentModeKnown = updatedTraceMode
121
124
  })
122
- this.ee.on(SESSION_EVENTS.PAUSE, () => mostRecentModeKnown = sessionEntity.state.sessionTraceMode)
125
+ this.ee.on(SESSION_EVENTS.PAUSE, () => { mostRecentModeKnown = sessionEntity.state.sessionTraceMode })
123
126
 
124
127
  if (!sessionEntity.isNew) { // inherit the same mode as existing session's Trace
125
128
  if (sessionEntity.state.sessionReplay === MODE.OFF) this.isStandalone = true
@@ -152,7 +155,7 @@ export class Aggregate extends AggregateBase {
152
155
  registerHandler('bstApi', (...args) => operationalGate.settle(() => this.storeSTN(...args)), this.featureName, this.ee)
153
156
  registerHandler('errorAgg', (...args) => operationalGate.settle(() => this.storeErrorAgg(...args)), this.featureName, this.ee)
154
157
  registerHandler('pvtAdded', (...args) => operationalGate.settle(() => this.processPVT(...args)), this.featureName, this.ee)
155
- drain(this.agentIdentifier, this.featureName)
158
+ this.drain()
156
159
  }
157
160
 
158
161
  startTracing (startupBuffer, dontStartHarvestYet = false) {
@@ -189,16 +192,16 @@ export class Aggregate extends AggregateBase {
189
192
  }
190
193
 
191
194
  #prepareHarvest (options) {
192
- /* Standalone refers to the legacy version of ST before the idea of 'session' or the Replay feature existed.
193
- It has a different behavior on returning a payload for harvest than when used in tandem with either of those concepts. */
194
195
  if (this.isStandalone) {
195
- if (now() > MAX_TRACE_DURATION) { // been collecting for over the longest duration we should run for, empty trace object so ST has nothing to send
196
- this.#scheduler.stopTimer()
197
- this.trace = {}
196
+ if (this.ptid && now() >= MAX_TRACE_DURATION) {
197
+ // Perform a final harvest once we hit or exceed the max session trace time
198
+ options.isFinalHarvest = true
199
+ this.operationalGate.permanentlyDecide(false)
200
+ this.#scheduler.stopTimer(true)
201
+ } else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
202
+ // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
198
203
  return
199
204
  }
200
- // Only harvest when more than some threshold of nodes are pending, after the very first harvest.
201
- if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
202
205
  } else {
203
206
  // -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
204
207
  // if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
@@ -209,6 +212,7 @@ export class Aggregate extends AggregateBase {
209
212
  if (currentMode === MODE.OFF && Object.keys(this.trace).length === 0) return
210
213
  if (currentMode === MODE.ERROR) return // Trace in this mode should never be harvesting, even on unload
211
214
  }
215
+
212
216
  return this.takeSTNs(options.retry)
213
217
  }
214
218
 
@@ -274,8 +278,7 @@ export class Aggregate extends AggregateBase {
274
278
  const origin = this.evtOrigin(event.target, target)
275
279
  if (event.type in ignoredEvents.global) return true
276
280
  if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true
277
- if (!!ignoredEvents[origin] && event.type in ignoredEvents[origin]) return true
278
- return false
281
+ return !!(!!ignoredEvents[origin] && event.type in ignoredEvents[origin])
279
282
  }
280
283
 
281
284
  evtName (type) {
@@ -394,7 +397,11 @@ export class Aggregate extends AggregateBase {
394
397
  if (this.nodeCount >= this.maxNodesPerHarvest) { // limit the amount of pending data awaiting next harvest
395
398
  if (this.isStandalone || this.agentRuntime.session.state.sessionTraceMode !== MODE.ERROR) return
396
399
  const openedSpace = this.trimSTNs(ERROR_MODE_SECONDS_WINDOW) // but maybe we could make some space by discarding irrelevant nodes if we're in sessioned Error mode
397
- if (openedSpace == 0) return
400
+ if (openedSpace === 0) return
401
+ }
402
+
403
+ if (this.isStandalone && now() >= MAX_TRACE_DURATION) {
404
+ return
398
405
  }
399
406
 
400
407
  if (this.trace[stn.n]) this.trace[stn.n].push(stn)
@@ -418,7 +425,7 @@ export class Aggregate extends AggregateBase {
418
425
  * ASSUMPTION: all 'end' timings stored are relative to timeOrigin (DOMHighResTimeStamp) and not Unix epoch based. */
419
426
  let cutoffIdx = nodeList.findIndex(node => cutoffHighResTime <= node.e)
420
427
 
421
- if (cutoffIdx == 0) return
428
+ if (cutoffIdx === 0) return
422
429
  else if (cutoffIdx < 0) { // whole list falls outside lookback window and is irrelevant
423
430
  cutoffIdx = nodeList.length
424
431
  delete this.trace[nameCategory]
@@ -484,8 +491,7 @@ export class Aggregate extends AggregateBase {
484
491
 
485
492
  function trivial (node) {
486
493
  const limit = 4
487
- if (node && typeof node.e === 'number' && typeof node.s === 'number' && (node.e - node.s) < limit) return true
488
- else return false
494
+ return !!(node && typeof node.e === 'number' && typeof node.s === 'number' && (node.e - node.s) < limit)
489
495
  }
490
496
  }
491
497
  }
@@ -17,7 +17,6 @@ import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
17
17
  import { Serializer } from './serializer'
18
18
  import { ee } from '../../../common/event-emitter/contextual-ee'
19
19
  import * as CONSTANTS from '../constants'
20
- import { drain } from '../../../common/drain/drain'
21
20
  import { FEATURE_NAMES } from '../../../loaders/features/features'
22
21
  import { AggregateBase } from '../../utils/aggregate-base'
23
22
 
@@ -122,8 +121,8 @@ export class Aggregate extends AggregateBase {
122
121
 
123
122
  // register plugins
124
123
  var pluginApi = {
125
- getCurrentNode: getCurrentNode,
126
- setCurrentNode: setCurrentNode
124
+ getCurrentNode,
125
+ setCurrentNode
127
126
  }
128
127
 
129
128
  register('spa-register', function (init) {
@@ -197,23 +196,21 @@ export class Aggregate extends AggregateBase {
197
196
  // If this event was emitted by an XHR, restore the node ID associated with
198
197
  // that XHR.
199
198
  setCurrentNode(baseEE.context(eventSource).spaNode)
200
- } else if (!state.currentNode) {
199
+ } else if (!state.currentNode && INTERACTION_EVENTS.indexOf(evName) !== -1) {
201
200
  // Otherwise, if no interaction is currently active, create a new node ID,
202
201
  // and let the aggregator know that we entered a new event handler callback
203
202
  // so that it has a chance to possibly start an interaction.
204
- if (INTERACTION_EVENTS.indexOf(evName) !== -1) {
205
- var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
203
+ var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
206
204
 
207
- // Store the interaction as prevInteraction in case it is prematurely discarded
208
- state.prevInteraction = ixn
205
+ // Store the interaction as prevInteraction in case it is prematurely discarded
206
+ state.prevInteraction = ixn
209
207
 
210
- setCurrentNode(ixn.root)
208
+ setCurrentNode(ixn.root)
211
209
 
212
- if (evName === 'click') {
213
- var value = getActionText(ev.target)
214
- if (value) {
215
- state.currentNode.attrs.custom.actionText = value
216
- }
210
+ if (evName === 'click') {
211
+ var value = getActionText(ev.target)
212
+ if (value) {
213
+ state.currentNode.attrs.custom.actionText = value
217
214
  }
218
215
  }
219
216
  }
@@ -530,7 +527,7 @@ export class Aggregate extends AggregateBase {
530
527
  register(INTERACTION_API + 'get', function (t) {
531
528
  var interaction
532
529
  if (state?.currentNode?.[INTERACTION]) interaction = this.ixn = state.currentNode[INTERACTION]
533
- else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName != 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION]
530
+ else if (state?.prevNode?.end === null && state?.prevNode?.[INTERACTION]?.root?.[INTERACTION]?.eventName !== 'initialPageLoad') interaction = this.ixn = state.prevNode[INTERACTION]
534
531
  else interaction = this.ixn = new Interaction('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier)
535
532
  if (!state.currentNode) {
536
533
  interaction.checkFinish()
@@ -727,12 +724,9 @@ export class Aggregate extends AggregateBase {
727
724
 
728
725
  function isEnabled () {
729
726
  var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled')
730
- if (enabled === false) {
731
- return false
732
- }
733
- return true
727
+ return enabled !== false
734
728
  }
735
729
 
736
- drain(this.agentIdentifier, this.featureName)
730
+ this.drain()
737
731
  }
738
732
  }
@@ -7,7 +7,6 @@ import { getInfo, getRuntime, originals } from '../../../common/config/config'
7
7
  import { mapOwn } from '../../../common/util/map-own'
8
8
  import { ee } from '../../../common/event-emitter/contextual-ee'
9
9
  import { InteractionNode } from './interaction-node'
10
- import { now } from '../../../common/timing/now'
11
10
 
12
11
  var originalSetTimeout = originals.ST
13
12
  var originalClearTimeout = originals.CT
@@ -95,7 +94,6 @@ InteractionPrototype.finish = function finishInteraction () {
95
94
  var root = interaction.root
96
95
  if (root.end !== null) return
97
96
  var endTimestamp = Math.max(interaction.lastCb, interaction.lastFinish)
98
- var delta = now() - endTimestamp
99
97
  var attrs = root.attrs
100
98
  var customAttrs = attrs.custom
101
99
 
@@ -176,7 +176,7 @@ export class Serializer extends SharedContext {
176
176
  // (since its the same as interaction.start)
177
177
  // and limit to just the first 20 values we know about
178
178
  mapOwn(navTiming.slice(1, 21), function (i, v) {
179
- if (v !== void 0) {
179
+ if (v !== undefined) {
180
180
  navTimingNode += seperator + numeric(v - prev)
181
181
  seperator = ','
182
182
  prev = v
@@ -3,6 +3,7 @@ import { FeatureBase } from './feature-base'
3
3
  import { getInfo, isConfigured, getRuntime } from '../../common/config/config'
4
4
  import { configure } from '../../loaders/configure/configure'
5
5
  import { gosCDN } from '../../common/window/nreum'
6
+ import { drain } from '../../common/drain/drain'
6
7
 
7
8
  export class AggregateBase extends FeatureBase {
8
9
  constructor (...args) {
@@ -25,6 +26,10 @@ export class AggregateBase extends FeatureBase {
25
26
  )
26
27
  }
27
28
 
29
+ drain () {
30
+ drain(this.agentIdentifier, this.featureName)
31
+ }
32
+
28
33
  /**
29
34
  * Checks for additional `jsAttributes` items to support backward compatibility with implementations of the agent where
30
35
  * loader configurations may appear after the loader code is executed.
@@ -31,7 +31,8 @@ jest.mock('../../loaders/configure/configure', () => ({
31
31
  }))
32
32
  jest.mock('../../common/window/nreum', () => ({
33
33
  __esModule: true,
34
- gosCDN: jest.fn().mockReturnValue({})
34
+ gosCDN: jest.fn().mockReturnValue({}),
35
+ gosNREUM: jest.fn().mockReturnValue({})
35
36
  }))
36
37
 
37
38
  let agentIdentifier
@@ -36,8 +36,9 @@ export class HandlerCache {
36
36
  * @returns {void}
37
37
  */
38
38
  settle (handler) {
39
- if (this.#decision === false) return
40
- else if (this.#decision === undefined) this.#cache.push(handler)
39
+ if (this.#decision === false) {
40
+ // Do nothing
41
+ } else if (this.#decision === undefined) this.#cache.push(handler)
41
42
  else handler()
42
43
  }
43
44
 
@@ -31,19 +31,24 @@ export class InstrumentBase extends FeatureBase {
31
31
  this.auto = auto
32
32
 
33
33
  /** @type {Function | undefined} This should be set by any derived Instrument class if it has things to do when feature fails or is killed. */
34
- this.abortHandler
34
+ this.abortHandler = undefined
35
+
35
36
  /**
36
37
  * @type {Class} Holds the reference to the feature's aggregate module counterpart, if and after it has been initialized. This may not be assigned until after page loads!
37
38
  * The only purpose of this for now is to expose it to the NREUM interface, as the feature's instrument instance is already exposed.
38
39
  */
39
- this.featAggregate
40
+ this.featAggregate = undefined
41
+
40
42
  /**
41
43
  * @type {Promise} Assigned immediately after @see importAggregator runs. Serves as a signal for when the inner async fn finishes execution. Useful for features to await
42
44
  * one another if there are inter-features dependencies.
43
45
  */
44
- this.onAggregateImported
46
+ this.onAggregateImported = undefined
45
47
 
46
- if (auto) registerDrain(agentIdentifier, featureName)
48
+ /** used in conjunction with newrelic.start() to defer harvesting in features */
49
+ if (getConfigurationValue(this.agentIdentifier, `${this.featureName}.autoStart`) === false) this.auto = false
50
+ /** if the feature requires opt-in (!auto-start), it will get registered once the api has been called */
51
+ if (this.auto) registerDrain(agentIdentifier, featureName)
47
52
  }
48
53
 
49
54
  /**
@@ -53,7 +58,21 @@ export class InstrumentBase extends FeatureBase {
53
58
  * @returns void
54
59
  */
55
60
  importAggregator (argsObjFromInstrument = {}) {
56
- if (this.featAggregate || !this.auto) return
61
+ if (this.featAggregate) return
62
+
63
+ if (!this.auto) {
64
+ // this feature requires an opt in...
65
+ // wait for API to be called
66
+ this.ee.on(`${this.featureName}-opt-in`, () => {
67
+ // register the feature to drain only once the API has been called, it will drain when importAggregator finishes for all the features
68
+ // called by the api in that cycle
69
+ registerDrain(this.agentIdentifier, this.featureName)
70
+ this.auto = true
71
+ this.importAggregator()
72
+ })
73
+ return
74
+ }
75
+
57
76
  const enableSessionTracking = isBrowserScope && getConfigurationValue(this.agentIdentifier, 'privacy.cookies_enabled') === true
58
77
  let loadedSuccessfully
59
78
  this.onAggregateImported = new Promise(resolve => {
@@ -72,7 +91,7 @@ export class InstrumentBase extends FeatureBase {
72
91
  }
73
92
 
74
93
  /**
75
- * Note this try-catch differs from the one in Agent.start() in that it's placed later in a page's lifecycle and
94
+ * Note this try-catch differs from the one in Agent.run() in that it's placed later in a page's lifecycle and
76
95
  * it's only responsible for aborting its one specific feature, rather than all.
77
96
  */
78
97
  try {
@@ -33,7 +33,7 @@ jest.mock('../../common/config/config', () => ({
33
33
  }))
34
34
  jest.mock('../../common/config/config', () => ({
35
35
  __esModule: true,
36
- getConfigurationValue: jest.fn(),
36
+ getConfigurationValue: jest.fn().mockReturnValue({}),
37
37
  originals: {
38
38
  MO: jest.fn()
39
39
  }
@@ -79,7 +79,7 @@ test('should construct a new instrument', () => {
79
79
  })
80
80
 
81
81
  test('should not immediately drain', () => {
82
- const instrument = new InstrumentBase(agentIdentifier, aggregator, featureName, false)
82
+ new InstrumentBase(agentIdentifier, aggregator, featureName, false)
83
83
 
84
84
  expect(registerDrain).not.toHaveBeenCalled()
85
85
  })