@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,31 +1,59 @@
1
1
  import { isBrowserScope } from '../../../common/constants/runtime';
2
2
  const FRAMEWORKS = {
3
3
  REACT: 'React',
4
+ NEXTJS: 'NextJS',
5
+ VUE: 'Vue',
6
+ NUXTJS: 'NuxtJS',
4
7
  ANGULAR: 'Angular',
8
+ ANGULARUNIVERSAL: 'AngularUniversal',
9
+ SVELTE: 'Svelte',
10
+ SVELTEKIT: 'SvelteKit',
11
+ PREACT: 'Preact',
12
+ PREACTSSR: 'PreactSSR',
5
13
  ANGULARJS: 'AngularJS',
6
14
  BACKBONE: 'Backbone',
7
15
  EMBER: 'Ember',
8
- VUE: 'Vue',
9
16
  METEOR: 'Meteor',
10
17
  ZEPTO: 'Zepto',
11
18
  JQUERY: 'Jquery',
12
- MOOTOOLS: 'MooTools'
19
+ MOOTOOLS: 'MooTools',
20
+ QWIK: 'Qwik',
21
+ ELECTRON: 'Electron'
13
22
  };
14
23
  export function getFrameworks() {
15
24
  if (!isBrowserScope) return []; // don't bother detecting frameworks if not in the main window context
16
25
 
17
26
  const frameworks = [];
18
27
  try {
19
- if (detectReact()) frameworks.push(FRAMEWORKS.REACT);
28
+ if (detectReact()) {
29
+ frameworks.push(FRAMEWORKS.REACT);
30
+ if (detectNextJS()) frameworks.push(FRAMEWORKS.NEXTJS);
31
+ }
32
+ if (detectVue()) {
33
+ frameworks.push(FRAMEWORKS.VUE);
34
+ if (detectNuxtJS()) frameworks.push(FRAMEWORKS.NUXTJS);
35
+ }
36
+ if (detectAngular()) {
37
+ frameworks.push(FRAMEWORKS.ANGULAR);
38
+ if (detectAngularUniversal()) frameworks.push(FRAMEWORKS.ANGULARUNIVERSAL);
39
+ }
40
+ if (detectSvelte()) {
41
+ frameworks.push(FRAMEWORKS.SVELTE);
42
+ if (detectSvelteKit()) frameworks.push(FRAMEWORKS.SVELTEKIT);
43
+ }
44
+ if (detectPreact()) {
45
+ frameworks.push(FRAMEWORKS.PREACT);
46
+ if (detectPreactSSR()) frameworks.push(FRAMEWORKS.PREACTSSR);
47
+ }
20
48
  if (detectAngularJs()) frameworks.push(FRAMEWORKS.ANGULARJS);
21
- if (detectAngular()) frameworks.push(FRAMEWORKS.ANGULAR);
22
49
  if (Object.prototype.hasOwnProperty.call(window, 'Backbone')) frameworks.push(FRAMEWORKS.BACKBONE);
23
50
  if (Object.prototype.hasOwnProperty.call(window, 'Ember')) frameworks.push(FRAMEWORKS.EMBER);
24
- if (Object.prototype.hasOwnProperty.call(window, 'Vue')) frameworks.push(FRAMEWORKS.VUE);
25
51
  if (Object.prototype.hasOwnProperty.call(window, 'Meteor')) frameworks.push(FRAMEWORKS.METEOR);
26
52
  if (Object.prototype.hasOwnProperty.call(window, 'Zepto')) frameworks.push(FRAMEWORKS.ZEPTO);
27
53
  if (Object.prototype.hasOwnProperty.call(window, 'jQuery')) frameworks.push(FRAMEWORKS.JQUERY);
28
54
  if (Object.prototype.hasOwnProperty.call(window, 'MooTools')) frameworks.push(FRAMEWORKS.MOOTOOLS);
55
+ if (Object.prototype.hasOwnProperty.call(window, 'qwikevents')) frameworks.push(FRAMEWORKS.QWIK);
56
+ if (detectElectron()) frameworks.push(FRAMEWORKS.ELECTRON);
29
57
  } catch (err) {
30
58
  // Possibly not supported
31
59
  }
@@ -45,9 +73,25 @@ function detectReact() {
45
73
  return false;
46
74
  }
47
75
  }
48
- function detectAngularJs() {
76
+ function detectNextJS() {
77
+ // React SSR
49
78
  try {
50
- return Object.prototype.hasOwnProperty.call(window, 'angular') || document.querySelector('.ng-binding, [ng-app], [data-ng-app], [ng-controller], [data-ng-controller], [ng-repeat], [data-ng-repeat]') || document.querySelector('script[src*="angular.js"], script[src*="angular.min.js"]');
79
+ return Object.prototype.hasOwnProperty.call(window, 'next') && Object.prototype.hasOwnProperty.call(window.next, 'version');
80
+ } catch (err) {
81
+ return false;
82
+ }
83
+ }
84
+ function detectVue() {
85
+ try {
86
+ return Object.prototype.hasOwnProperty.call(window, 'Vue');
87
+ } catch (err) {
88
+ return false;
89
+ }
90
+ }
91
+ function detectNuxtJS() {
92
+ // Vue SSR
93
+ try {
94
+ return Object.prototype.hasOwnProperty.call(window, '$nuxt') && Object.prototype.hasOwnProperty.call(window.$nuxt, 'nuxt');
51
95
  } catch (err) {
52
96
  return false;
53
97
  }
@@ -58,4 +102,56 @@ function detectAngular() {
58
102
  } catch (err) {
59
103
  return false;
60
104
  }
105
+ }
106
+ function detectAngularUniversal() {
107
+ // Anguler SSR
108
+ try {
109
+ return document.querySelector('[ng-server-context]');
110
+ } catch (err) {
111
+ return false;
112
+ }
113
+ }
114
+ function detectSvelte() {
115
+ try {
116
+ return Object.prototype.hasOwnProperty.call(window, '__svelte');
117
+ } catch (err) {
118
+ return false;
119
+ }
120
+ }
121
+ function detectSvelteKit() {
122
+ // Svelte SSR
123
+ try {
124
+ return !!Object.keys(window).find(prop => prop.startsWith('__sveltekit'));
125
+ } catch (err) {
126
+ return false;
127
+ }
128
+ }
129
+ function detectPreact() {
130
+ try {
131
+ return Object.prototype.hasOwnProperty.call(window, 'preact');
132
+ } catch (err) {
133
+ return false;
134
+ }
135
+ }
136
+ function detectPreactSSR() {
137
+ // Svelte SSR
138
+ try {
139
+ return document.querySelector('script[type="__PREACT_CLI_DATA__"]');
140
+ } catch (err) {
141
+ return false;
142
+ }
143
+ }
144
+ function detectAngularJs() {
145
+ try {
146
+ return Object.prototype.hasOwnProperty.call(window, 'angular') || document.querySelector('.ng-binding, [ng-app], [data-ng-app], [ng-controller], [data-ng-controller], [ng-repeat], [data-ng-repeat]') || document.querySelector('script[src*="angular.js"], script[src*="angular.min.js"]');
147
+ } catch (err) {
148
+ return false;
149
+ }
150
+ }
151
+ function detectElectron() {
152
+ try {
153
+ return typeof navigator === 'object' && typeof navigator.userAgent === 'string' && navigator.userAgent.indexOf('Electron') >= 0;
154
+ } catch (err) {
155
+ return false;
156
+ }
61
157
  }
@@ -1,19 +1,14 @@
1
- import { getRuntime, getInfo } from '../../../common/config/config';
1
+ import { getRuntime } from '../../../common/config/config';
2
2
  import { registerHandler } from '../../../common/event-emitter/register-handler';
3
3
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler';
4
4
  import { FEATURE_NAME, SUPPORTABILITY_METRIC, CUSTOM_METRIC, SUPPORTABILITY_METRIC_CHANNEL, CUSTOM_METRIC_CHANNEL } from '../constants';
5
- import { drain } from '../../../common/drain/drain';
6
5
  import { getFrameworks } from './framework-detection';
7
- import { getPolyfills } from './polyfill-detection';
8
6
  import { isFileProtocol } from '../../../common/url/protocol';
9
7
  import { getRules, validateRules } from '../../../common/util/obfuscate';
10
- import { VERSION } from "../../../common/constants/env.npm";
11
8
  import { onDOMContentLoaded } from '../../../common/window/load';
12
9
  import { windowAddEventListener } from '../../../common/event-listener/event-listener-opts';
13
- import { isBrowserScope } from '../../../common/constants/runtime';
10
+ import { isBrowserScope, isWorkerScope } from '../../../common/constants/runtime';
14
11
  import { AggregateBase } from '../../utils/aggregate-base';
15
- import { stringify } from '../../../common/util/stringify';
16
- import { endpointMap } from './endpoint-map';
17
12
  export class Aggregate extends AggregateBase {
18
13
  static featureName = FEATURE_NAME;
19
14
  constructor(agentIdentifier, aggregator) {
@@ -39,9 +34,8 @@ export class Aggregate extends AggregateBase {
39
34
  scheduler.harvest.on('jserrors', () => ({
40
35
  body: this.aggregator.take(['cm', 'sm'])
41
36
  }));
42
- drain(this.agentIdentifier, this.featureName); // regardless if this is blocked or not, drain is needed to unblock other features from harvesting (counteract registerDrain)
37
+ this.drain();
43
38
  }
44
-
45
39
  storeSupportabilityMetrics(name, value) {
46
40
  if (this.blocked) return;
47
41
  const type = SUPPORTABILITY_METRIC;
@@ -59,9 +53,6 @@ export class Aggregate extends AggregateBase {
59
53
  this.aggregator.store(type, name, params, metrics);
60
54
  }
61
55
  singleChecks() {
62
- // report generic info about the agent itself
63
- // note the browser agent version
64
- this.storeSupportabilityMetrics("Generic/Version/".concat(VERSION, "/Detected"));
65
56
  // report loaderType
66
57
  const {
67
58
  distMethod,
@@ -72,22 +63,27 @@ export class Aggregate extends AggregateBase {
72
63
 
73
64
  // frameworks on page
74
65
  if (isBrowserScope) {
66
+ this.storeSupportabilityMetrics('Generic/Runtime/Browser/Detected');
67
+
68
+ // These SMs are used by the AppExp team
75
69
  onDOMContentLoaded(() => {
76
70
  getFrameworks().forEach(framework => {
77
71
  this.storeSupportabilityMetrics('Framework/' + framework + '/Detected');
78
72
  });
79
73
  });
74
+ } else if (isWorkerScope) {
75
+ this.storeSupportabilityMetrics('Generic/Runtime/Worker/Detected');
76
+ } else {
77
+ this.storeSupportabilityMetrics('Generic/Runtime/Unknown/Detected');
80
78
  }
81
- getPolyfills().forEach(polyfill => {
82
- this.storeSupportabilityMetrics('Polyfill/' + polyfill + '/Detected');
83
- });
84
79
 
85
- // file protocol detection
80
+ // Track if the agent is being loaded using a file protocol such as is the case in some
81
+ // set-top box applications or Electron applications
86
82
  if (isFileProtocol()) {
87
83
  this.storeSupportabilityMetrics('Generic/FileProtocol/Detected');
88
84
  }
89
85
 
90
- // obfuscation rules detection
86
+ // Capture SMs to assess customer engagement with the obfuscation config
91
87
  const rules = getRules(this.agentIdentifier);
92
88
  if (rules.length > 0) this.storeSupportabilityMetrics('Generic/Obfuscate/Detected');
93
89
  if (rules.length > 0 && !validateRules(rules)) this.storeSupportabilityMetrics('Generic/Obfuscate/Invalid');
@@ -100,18 +96,17 @@ export class Aggregate extends AggregateBase {
100
96
  if (evt.persisted) {
101
97
  this.storeSupportabilityMetrics('Generic/BFCache/PageRestored');
102
98
  }
103
- return;
104
99
  });
105
100
  }
106
101
  unload() {
107
- // Page Resources detection for estimations with resources feature work
108
- // TODO - these SMs are to be removed when we implement the actual resources feature
109
102
  try {
110
103
  if (this.resourcesSent) return;
104
+ this.resourcesSent = true; // make sure this only gets sent once
105
+
111
106
  const agentRuntime = getRuntime(this.agentIdentifier);
112
- const info = getInfo(this.agentIdentifier);
113
- // make sure this only gets sent once
114
- this.resourcesSent = true;
107
+
108
+ // Capture SMs around network resources using the performance API to assess
109
+ // work to split this out from the ST nodes
115
110
  // differentiate between internal+external and ajax+non-ajax
116
111
  const ajaxResources = ['beacon', 'fetch', 'xmlhttprequest'];
117
112
  const internalUrls = ['nr-data.net', 'newrelic.com', 'nr-local.net', 'localhost'];
@@ -130,26 +125,14 @@ export class Aggregate extends AggregateBase {
130
125
  }
131
126
  });
132
127
 
133
- // Capture per-agent bytes sent for each endpoint (see harvest) and RUM call (see page_view_event aggregator).
134
- Object.keys(agentRuntime.bytesSent).forEach(endpoint => {
135
- this.storeSupportabilityMetrics("PageSession/Endpoint/".concat(endpointMap[endpoint], "/BytesSent"), agentRuntime.bytesSent[endpoint]);
136
- });
137
-
138
- // Capture per-agent query bytes sent for each endpoint (see harvest) and RUM call (see page_view_event aggregator).
139
- Object.keys(agentRuntime.bytesSent).forEach(endpoint => {
140
- this.storeSupportabilityMetrics("PageSession/Endpoint/".concat(endpointMap[endpoint], "/QueryBytesSent"), agentRuntime.queryBytesSent[endpoint]);
141
- });
142
-
143
- // Capture metrics for session trace if active (`ptid` is set when returned by replay ingest).
128
+ // Capture SMs for session trace if active (`ptid` is set when returned by replay ingest).
129
+ // Retain these SMs while we are working through the session_replay feature
144
130
  if (agentRuntime.ptid) {
145
131
  this.storeSupportabilityMetrics('PageSession/Feature/SessionTrace/DurationMs', Math.round(performance.now()));
146
132
  }
147
133
 
148
- // Capture metrics for size of custom attributes
149
- const jsAttributes = stringify(info.jsAttributes);
150
- this.storeSupportabilityMetrics('PageSession/Feature/CustomData/Bytes', jsAttributes === '{}' ? 0 : jsAttributes.length);
151
-
152
- // Capture metrics for performance markers and measures
134
+ // Capture SMs for performance markers and measures to assess the usage and possible inclusion of this
135
+ // data in the agent for use in NR
153
136
  if (typeof performance !== 'undefined') {
154
137
  const markers = performance.getEntriesByType('mark');
155
138
  const measures = performance.getEntriesByType('measure');
@@ -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
  export class Instrument extends InstrumentBase {
6
4
  static featureName = FEATURE_NAME;
7
5
  constructor(agentIdentifier, aggregator) {
@@ -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
  export class Aggregate extends AggregateBase {
@@ -22,8 +21,8 @@ export class Aggregate extends AggregateBase {
22
21
  this.eventsPerMinute = 240;
23
22
  this.harvestTimeSeconds = getConfigurationValue(this.agentIdentifier, 'page_action.harvestTimeSeconds') || getConfigurationValue(this.agentIdentifier, 'ins.harvestTimeSeconds') || 30;
24
23
  this.eventsPerHarvest = this.eventsPerMinute * this.harvestTimeSeconds / 60;
25
- this.referrerUrl;
26
- this.currentEvents;
24
+ this.referrerUrl = undefined;
25
+ this.currentEvents = undefined;
27
26
  this.events = [];
28
27
  this.att = getInfo(this.agentIdentifier).jsAttributes; // per-agent, aggregators-shared info context
29
28
 
@@ -31,24 +30,23 @@ export class Aggregate extends AggregateBase {
31
30
  register('api-addPageAction', function () {
32
31
  return _this.addPageAction(...arguments);
33
32
  }, this.featureName, this.ee);
34
- var scheduler = new HarvestScheduler('ins', {
35
- onFinished: function () {
36
- return _this.onHarvestFinished(...arguments);
33
+ this.waitForFlags(['ins']).then(_ref => {
34
+ let [enabled] = _ref;
35
+ if (enabled) {
36
+ const scheduler = new HarvestScheduler('ins', {
37
+ onFinished: function () {
38
+ return _this.onHarvestFinished(...arguments);
39
+ }
40
+ }, this);
41
+ scheduler.harvest.on('ins', function () {
42
+ return _this.onHarvestStarted(...arguments);
43
+ });
44
+ scheduler.startTimer(this.harvestTimeSeconds, 0);
45
+ } else {
46
+ this.blocked = true;
37
47
  }
38
- }, this);
39
- scheduler.harvest.on('ins', function () {
40
- return _this.onHarvestStarted(...arguments);
41
48
  });
42
- this.ee.on("drain-".concat(this.featureName), () => {
43
- if (!this.blocked) scheduler.startTimer(this.harvestTimeSeconds, 0);
44
- });
45
-
46
- // if rum response determines that customer lacks entitlements for ins endpoint, block it
47
- register('block-ins', () => {
48
- this.blocked = true;
49
- scheduler.stopTimer(true);
50
- }, this.featureName, this.ee);
51
- drain(this.agentIdentifier, this.featureName);
49
+ this.drain();
52
50
  }
53
51
  onHarvestStarted(options) {
54
52
  const {
@@ -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';
@@ -147,7 +146,7 @@ export class Aggregate extends AggregateBase {
147
146
  }
148
147
  try {
149
148
  activateFeatures(JSON.parse(responseText), this.agentIdentifier);
150
- drain(this.agentIdentifier, this.featureName);
149
+ this.drain();
151
150
  } catch (err) {
152
151
  this.ee.abort();
153
152
  warn('RUM call failed. Agent shutting down.');
@@ -13,10 +13,12 @@ export class Instrument extends InstrumentBase {
13
13
  super(agentIdentifier, aggregator, CONSTANTS.FEATURE_NAME, auto);
14
14
  if ((typeof PerformanceNavigationTiming === 'undefined' || isiOS) && typeof PerformanceTiming !== 'undefined') {
15
15
  // 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.
16
- // *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.
16
+ // *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.
17
17
  const agentRuntime = getRuntime(agentIdentifier);
18
18
  agentRuntime[CONSTANTS.TTFB] = Math.max(Date.now() - agentRuntime.offset, 0);
19
- onDOMContentLoaded(() => agentRuntime[CONSTANTS.FBTDC] = Math.max(now() - agentRuntime[CONSTANTS.TTFB], 0));
19
+ onDOMContentLoaded(() => {
20
+ agentRuntime[CONSTANTS.FBTDC] = Math.max(now() - agentRuntime[CONSTANTS.TTFB], 0);
21
+ });
20
22
  onWindowLoad(() => {
21
23
  const timeNow = now();
22
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
  export class Aggregate extends AggregateBase {
@@ -45,7 +44,7 @@ export class Aggregate extends AggregateBase {
45
44
  });
46
45
 
47
46
  /* 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. */
48
- if (iOS_below16) {
47
+ if (iOSBelow16) {
49
48
  try {
50
49
  if (!pageStartedHidden) {
51
50
  // see ios-version.js for detail on this following bug case; tldr: buffered flag doesn't work but getEntriesByType does
@@ -121,7 +120,7 @@ export class Aggregate extends AggregateBase {
121
120
  let {
122
121
  value
123
122
  } = _ref5;
124
- return this.cls = value;
123
+ this.cls = value;
125
124
  }, {
126
125
  reportAllChanges: true
127
126
  });
@@ -170,7 +169,7 @@ export class Aggregate extends AggregateBase {
170
169
  this.ee.on("drain-".concat(this.featureName), () => {
171
170
  this.scheduler.startTimer(harvestTimeSeconds, initialHarvestSeconds);
172
171
  });
173
- drain(this.agentIdentifier, this.featureName);
172
+ this.drain();
174
173
  }
175
174
 
176
175
  // takes an attributes object and appends connection attributes if available
@@ -224,9 +223,9 @@ export class Aggregate extends AggregateBase {
224
223
  attrs.cls = this.cls;
225
224
  }
226
225
  this.timings.push({
227
- name: name,
228
- value: value,
229
- attrs: attrs
226
+ name,
227
+ value,
228
+ attrs
230
229
  });
231
230
  handle('pvtAdded', [name, value, attrs], undefined, FEATURE_NAMES.sessionTrace, this.ee);
232
231
  }
@@ -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
  return this.initializeRecording(flagOn, Math.random() < getConfigurationValue(this.agentIdentifier, 'session_replay.errorSampleRate'), 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
 
@@ -174,11 +174,13 @@ export class Aggregate extends AggregateBase {
174
174
  this.scheduler.startTimer(this.harvestTimeSeconds);
175
175
  }
176
176
  try {
177
+ // Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
177
178
  recorder = (await import( /* webpackChunkName: "recorder" */'rrweb')).record;
178
179
  } catch (err) {
179
180
  return this.abort();
180
181
  }
181
182
  try {
183
+ // Do not change the webpackChunkName or it will break the webpack nrba-chunking plugin
182
184
  const {
183
185
  gzipSync,
184
186
  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';
@@ -57,9 +56,13 @@ export class Aggregate extends AggregateBase {
57
56
  this.sentTrace = null;
58
57
  this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10;
59
58
  this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000;
59
+ /**
60
+ * Standalone (mode) refers to the legacy version of ST before the idea of 'session' or the Replay feature existed.
61
+ * It has some different behavior vs when used in tandem with replay. */
60
62
  this.isStandalone = false;
61
63
  const operationalGate = new HandlerCache(); // acts as a controller-intermediary that can enable or disable this feature's collection dynamically
62
64
  const sessionEntity = this.agentRuntime.session;
65
+ this.operationalGate = operationalGate;
63
66
 
64
67
  /* --- The following section deals with user sessions concept & contains non-trivial control flow. --- */
65
68
  const controlTraceOp = traceMode => {
@@ -133,7 +136,9 @@ export class Aggregate extends AggregateBase {
133
136
  });
134
137
  mostRecentModeKnown = updatedTraceMode;
135
138
  });
136
- this.ee.on(SESSION_EVENTS.PAUSE, () => mostRecentModeKnown = sessionEntity.state.sessionTraceMode);
139
+ this.ee.on(SESSION_EVENTS.PAUSE, () => {
140
+ mostRecentModeKnown = sessionEntity.state.sessionTraceMode;
141
+ });
137
142
  if (!sessionEntity.isNew) {
138
143
  // inherit the same mode as existing session's Trace
139
144
  if (sessionEntity.state.sessionReplay === MODE.OFF) this.isStandalone = true;
@@ -205,7 +210,7 @@ export class Aggregate extends AggregateBase {
205
210
  }
206
211
  return operationalGate.settle(() => _this.processPVT(...args));
207
212
  }, this.featureName, this.ee);
208
- drain(this.agentIdentifier, this.featureName);
213
+ this.drain();
209
214
  }
210
215
  startTracing(startupBuffer) {
211
216
  let dontStartHarvestYet = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
@@ -243,17 +248,16 @@ export class Aggregate extends AggregateBase {
243
248
  }
244
249
  }
245
250
  #prepareHarvest(options) {
246
- /* Standalone refers to the legacy version of ST before the idea of 'session' or the Replay feature existed.
247
- It has a different behavior on returning a payload for harvest than when used in tandem with either of those concepts. */
248
251
  if (this.isStandalone) {
249
- if (now() > MAX_TRACE_DURATION) {
250
- // been collecting for over the longest duration we should run for, empty trace object so ST has nothing to send
251
- this.#scheduler.stopTimer();
252
- this.trace = {};
252
+ if (this.ptid && now() >= MAX_TRACE_DURATION) {
253
+ // Perform a final harvest once we hit or exceed the max session trace time
254
+ options.isFinalHarvest = true;
255
+ this.operationalGate.permanentlyDecide(false);
256
+ this.#scheduler.stopTimer(true);
257
+ } else if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND && !options.isFinalHarvest) {
258
+ // Only harvest when more than some threshold of nodes are pending, after the very first harvest, with the exception of the last outgoing harvest.
253
259
  return;
254
260
  }
255
- // Only harvest when more than some threshold of nodes are pending, after the very first harvest.
256
- if (this.ptid && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return;
257
261
  } else {
258
262
  // -- *cli May '26 - Update: Not rate limiting backgrounded pages either for now.
259
263
  // if (this.ptid && document.visibilityState === 'hidden' && this.nodeCount <= REQ_THRESHOLD_TO_SEND) return
@@ -330,8 +334,7 @@ export class Aggregate extends AggregateBase {
330
334
  const origin = this.evtOrigin(event.target, target);
331
335
  if (event.type in ignoredEvents.global) return true;
332
336
  if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true;
333
- if (!!ignoredEvents[origin] && event.type in ignoredEvents[origin]) return true;
334
- return false;
337
+ return !!(!!ignoredEvents[origin] && event.type in ignoredEvents[origin]);
335
338
  }
336
339
  evtName(type) {
337
340
  switch (type) {
@@ -441,7 +444,10 @@ export class Aggregate extends AggregateBase {
441
444
  // limit the amount of pending data awaiting next harvest
442
445
  if (this.isStandalone || this.agentRuntime.session.state.sessionTraceMode !== MODE.ERROR) return;
443
446
  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
444
- if (openedSpace == 0) return;
447
+ if (openedSpace === 0) return;
448
+ }
449
+ if (this.isStandalone && now() >= MAX_TRACE_DURATION) {
450
+ return;
445
451
  }
446
452
  if (this.trace[stn.n]) this.trace[stn.n].push(stn);else this.trace[stn.n] = [stn];
447
453
  this.nodeCount++;
@@ -461,7 +467,7 @@ export class Aggregate extends AggregateBase {
461
467
  * This isn't exact since nodes go through some processing & EE handlers chain, but it's close enough as we still capture nodes whose duration overlaps the lookback window.
462
468
  * ASSUMPTION: all 'end' timings stored are relative to timeOrigin (DOMHighResTimeStamp) and not Unix epoch based. */
463
469
  let cutoffIdx = nodeList.findIndex(node => cutoffHighResTime <= node.e);
464
- if (cutoffIdx == 0) return;else if (cutoffIdx < 0) {
470
+ if (cutoffIdx === 0) return;else if (cutoffIdx < 0) {
465
471
  // whole list falls outside lookback window and is irrelevant
466
472
  cutoffIdx = nodeList.length;
467
473
  delete this.trace[nameCategory];
@@ -525,7 +531,7 @@ export class Aggregate extends AggregateBase {
525
531
  };
526
532
  function trivial(node) {
527
533
  const limit = 4;
528
- if (node && typeof node.e === 'number' && typeof node.s === 'number' && node.e - node.s < limit) return true;else return false;
534
+ return !!(node && typeof node.e === 'number' && typeof node.s === 'number' && node.e - node.s < limit);
529
535
  }
530
536
  }
531
537
  }
@@ -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
  const {
@@ -135,8 +134,8 @@ export class Aggregate extends AggregateBase {
135
134
 
136
135
  // register plugins
137
136
  var pluginApi = {
138
- getCurrentNode: getCurrentNode,
139
- setCurrentNode: setCurrentNode
137
+ getCurrentNode,
138
+ setCurrentNode
140
139
  };
141
140
  register('spa-register', function (init) {
142
141
  if (typeof init === 'function') {
@@ -201,21 +200,19 @@ export class Aggregate extends AggregateBase {
201
200
  // If this event was emitted by an XHR, restore the node ID associated with
202
201
  // that XHR.
203
202
  setCurrentNode(baseEE.context(eventSource).spaNode);
204
- } else if (!state.currentNode) {
203
+ } else if (!state.currentNode && INTERACTION_EVENTS.indexOf(evName) !== -1) {
205
204
  // Otherwise, if no interaction is currently active, create a new node ID,
206
205
  // and let the aggregator know that we entered a new event handler callback
207
206
  // so that it has a chance to possibly start an interaction.
208
- if (INTERACTION_EVENTS.indexOf(evName) !== -1) {
209
- var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
207
+ var ixn = new Interaction(evName, this[FN_START], state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
210
208
 
211
- // Store the interaction as prevInteraction in case it is prematurely discarded
212
- state.prevInteraction = ixn;
213
- setCurrentNode(ixn.root);
214
- if (evName === 'click') {
215
- var value = getActionText(ev.target);
216
- if (value) {
217
- state.currentNode.attrs.custom.actionText = value;
218
- }
209
+ // Store the interaction as prevInteraction in case it is prematurely discarded
210
+ state.prevInteraction = ixn;
211
+ setCurrentNode(ixn.root);
212
+ if (evName === 'click') {
213
+ var value = getActionText(ev.target);
214
+ if (value) {
215
+ state.currentNode.attrs.custom.actionText = value;
219
216
  }
220
217
  }
221
218
  }
@@ -497,7 +494,7 @@ export class Aggregate extends AggregateBase {
497
494
  }, this.featureName, promiseEE);
498
495
  register(INTERACTION_API + 'get', function (t) {
499
496
  var interaction;
500
- 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('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
497
+ 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('api', t, state.lastSeenUrl, state.lastSeenRouteName, onInteractionFinished, agentIdentifier);
501
498
  if (!state.currentNode) {
502
499
  interaction.checkFinish();
503
500
  if (state.depth) setCurrentNode(interaction.root);
@@ -665,11 +662,8 @@ export class Aggregate extends AggregateBase {
665
662
  }
666
663
  function isEnabled() {
667
664
  var enabled = getConfigurationValue(agentIdentifier, 'spa.enabled');
668
- if (enabled === false) {
669
- return false;
670
- }
671
- return true;
665
+ return enabled !== false;
672
666
  }
673
- drain(this.agentIdentifier, this.featureName);
667
+ this.drain();
674
668
  }
675
669
  }