@newrelic/browser-agent 1.232.0 → 1.233.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 (273) hide show
  1. package/dist/cjs/cdn/polyfills.js +5 -2
  2. package/dist/cjs/common/config/state/configurable.js +15 -26
  3. package/dist/cjs/common/config/state/info.js +1 -1
  4. package/dist/cjs/common/config/state/init.js +101 -56
  5. package/dist/cjs/common/config/state/loader-config.js +1 -1
  6. package/dist/cjs/common/config/state/runtime.js +1 -5
  7. package/dist/cjs/common/constants/env.cdn.js +1 -1
  8. package/dist/cjs/common/constants/env.npm.js +1 -1
  9. package/dist/cjs/common/drain/drain.js +1 -1
  10. package/dist/cjs/common/harvest/harvest-scheduler.js +30 -10
  11. package/dist/cjs/common/harvest/harvest.js +119 -55
  12. package/dist/cjs/common/session/session-entity.js +35 -22
  13. package/dist/cjs/common/session/session-entity.test.js +73 -49
  14. package/dist/cjs/common/timer/interaction-timer.js +9 -12
  15. package/dist/cjs/common/url/canonicalize-url.js +32 -0
  16. package/dist/cjs/common/url/canonicalize-url.test.js +42 -0
  17. package/dist/cjs/common/url/clean-url.js +10 -3
  18. package/dist/cjs/common/url/protocol.test.js +0 -1
  19. package/dist/cjs/common/util/feature-flags.js +2 -1
  20. package/dist/cjs/common/util/global-scope.js +4 -2
  21. package/dist/cjs/common/util/submit-data.js +57 -18
  22. package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
  23. package/dist/cjs/common/wrap/wrap-function.js +1 -3
  24. package/dist/cjs/common/wrap/wrap-promise.js +1 -1
  25. package/dist/cjs/features/ajax/aggregate/index.js +2 -2
  26. package/dist/cjs/features/ajax/instrument/index.js +1 -1
  27. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +12 -4
  28. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +93 -10
  29. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +164 -38
  30. package/dist/cjs/features/jserrors/aggregate/index.js +29 -48
  31. package/dist/cjs/features/jserrors/instrument/index.js +0 -2
  32. package/dist/cjs/features/metrics/aggregate/framework-detection.js +67 -0
  33. package/dist/cjs/features/metrics/aggregate/framework-detection.test.js +137 -0
  34. package/dist/cjs/features/metrics/aggregate/index.js +7 -3
  35. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +14 -0
  36. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.test.js +17 -0
  37. package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +53 -0
  38. package/dist/cjs/features/metrics/aggregate/polyfill-detection.test.js +165 -0
  39. package/dist/cjs/features/page_action/aggregate/index.js +2 -2
  40. package/dist/cjs/features/page_view_event/aggregate/index.js +6 -3
  41. package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -2
  42. package/dist/cjs/features/session_replay/aggregate/index.js +333 -0
  43. package/dist/cjs/features/session_replay/constants.js +9 -0
  44. package/dist/cjs/features/session_replay/index.js +12 -0
  45. package/dist/cjs/features/session_replay/instrument/index.js +29 -0
  46. package/dist/cjs/features/session_trace/aggregate/index.js +163 -164
  47. package/dist/cjs/features/session_trace/constants.js +2 -9
  48. package/dist/cjs/features/session_trace/instrument/index.js +24 -66
  49. package/dist/cjs/features/spa/aggregate/index.js +2 -2
  50. package/dist/cjs/features/utils/agent-session.js +1 -2
  51. package/dist/cjs/features/utils/aggregate-base.js +64 -0
  52. package/dist/cjs/features/utils/feature-base.js +0 -31
  53. package/dist/cjs/features/utils/handler-cache.js +3 -4
  54. package/dist/cjs/features/utils/instrument-base.js +42 -10
  55. package/dist/cjs/features/utils/{lazy-loader.js → lazy-feature-loader.js} +4 -2
  56. package/dist/cjs/loaders/agent.js +1 -1
  57. package/dist/cjs/loaders/api/apiAsync.js +3 -1
  58. package/dist/cjs/loaders/configure/configure.js +3 -3
  59. package/dist/cjs/loaders/features/featureDependencies.js +0 -12
  60. package/dist/cjs/loaders/features/features.js +3 -1
  61. package/dist/cjs/loaders/micro-agent.js +6 -6
  62. package/dist/esm/cdn/polyfills.js +5 -2
  63. package/dist/esm/common/config/state/configurable.js +14 -24
  64. package/dist/esm/common/config/state/info.js +2 -2
  65. package/dist/esm/common/config/state/init.js +102 -57
  66. package/dist/esm/common/config/state/loader-config.js +2 -2
  67. package/dist/esm/common/config/state/runtime.js +2 -4
  68. package/dist/esm/common/constants/env.cdn.js +1 -1
  69. package/dist/esm/common/constants/env.npm.js +1 -1
  70. package/dist/esm/common/drain/drain.js +1 -1
  71. package/dist/esm/common/harvest/harvest-scheduler.js +30 -10
  72. package/dist/esm/common/harvest/harvest.js +121 -56
  73. package/dist/esm/common/session/session-entity.js +35 -22
  74. package/dist/esm/common/session/session-entity.test.js +73 -49
  75. package/dist/esm/common/timer/interaction-timer.js +9 -12
  76. package/dist/esm/common/url/canonicalize-url.js +27 -0
  77. package/dist/esm/common/url/canonicalize-url.test.js +38 -0
  78. package/dist/esm/common/url/clean-url.js +10 -3
  79. package/dist/esm/common/url/protocol.test.js +0 -1
  80. package/dist/esm/common/util/feature-flags.js +2 -1
  81. package/dist/esm/common/util/global-scope.js +1 -0
  82. package/dist/esm/common/util/submit-data.js +57 -18
  83. package/dist/esm/common/wrap/wrap-fetch.js +1 -2
  84. package/dist/esm/common/wrap/wrap-function.js +1 -2
  85. package/dist/esm/common/wrap/wrap-promise.js +1 -1
  86. package/dist/esm/features/ajax/aggregate/index.js +2 -2
  87. package/dist/esm/features/ajax/instrument/index.js +1 -1
  88. package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +12 -4
  89. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +93 -10
  90. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +149 -25
  91. package/dist/esm/features/jserrors/aggregate/index.js +30 -48
  92. package/dist/esm/features/jserrors/instrument/index.js +0 -1
  93. package/dist/esm/features/metrics/aggregate/framework-detection.js +61 -0
  94. package/dist/esm/features/metrics/aggregate/framework-detection.test.js +133 -0
  95. package/dist/esm/features/metrics/aggregate/index.js +7 -3
  96. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +8 -0
  97. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.test.js +15 -0
  98. package/dist/esm/features/metrics/aggregate/polyfill-detection.js +47 -0
  99. package/dist/esm/features/metrics/aggregate/polyfill-detection.test.js +163 -0
  100. package/dist/esm/features/page_action/aggregate/index.js +2 -2
  101. package/dist/esm/features/page_view_event/aggregate/index.js +6 -3
  102. package/dist/esm/features/page_view_timing/aggregate/index.js +2 -2
  103. package/dist/esm/features/session_replay/aggregate/index.js +327 -0
  104. package/dist/esm/features/session_replay/constants.js +2 -0
  105. package/dist/esm/features/session_replay/index.js +12 -0
  106. package/dist/esm/features/session_replay/instrument/index.js +21 -0
  107. package/dist/esm/features/session_trace/aggregate/index.js +163 -163
  108. package/dist/esm/features/session_trace/constants.js +1 -5
  109. package/dist/esm/features/session_trace/instrument/index.js +24 -66
  110. package/dist/esm/features/spa/aggregate/index.js +2 -2
  111. package/dist/esm/features/utils/agent-session.js +1 -2
  112. package/dist/esm/features/utils/aggregate-base.js +57 -0
  113. package/dist/esm/features/utils/feature-base.js +1 -32
  114. package/dist/esm/features/utils/handler-cache.js +3 -4
  115. package/dist/esm/features/utils/instrument-base.js +42 -10
  116. package/dist/esm/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
  117. package/dist/esm/loaders/agent.js +1 -1
  118. package/dist/esm/loaders/api/apiAsync.js +3 -1
  119. package/dist/esm/loaders/configure/configure.js +3 -3
  120. package/dist/esm/loaders/features/featureDependencies.js +0 -11
  121. package/dist/esm/loaders/features/features.js +3 -1
  122. package/dist/esm/loaders/micro-agent.js +6 -6
  123. package/dist/types/common/config/state/configurable.d.ts +1 -3
  124. package/dist/types/common/config/state/configurable.d.ts.map +1 -1
  125. package/dist/types/common/config/state/init.d.ts.map +1 -1
  126. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  127. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  128. package/dist/types/common/harvest/harvest.d.ts +37 -34
  129. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  130. package/dist/types/common/session/session-entity.d.ts +6 -3
  131. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  132. package/dist/types/common/timer/interaction-timer.d.ts +2 -1
  133. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
  134. package/dist/types/common/url/canonicalize-url.d.ts +9 -0
  135. package/dist/types/common/url/canonicalize-url.d.ts.map +1 -0
  136. package/dist/types/common/url/clean-url.d.ts +7 -1
  137. package/dist/types/common/url/clean-url.d.ts.map +1 -1
  138. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  139. package/dist/types/common/util/global-scope.d.ts +1 -0
  140. package/dist/types/common/util/global-scope.d.ts.map +1 -1
  141. package/dist/types/common/util/submit-data.d.ts +40 -14
  142. package/dist/types/common/util/submit-data.d.ts.map +1 -1
  143. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  144. package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
  145. package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
  146. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  147. package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts +8 -1
  148. package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts.map +1 -1
  149. package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts +48 -19
  150. package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts.map +1 -1
  151. package/dist/types/features/jserrors/aggregate/index.d.ts +14 -5
  152. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  153. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  154. package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -0
  155. package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
  156. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  157. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +6 -0
  158. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +1 -0
  159. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +7 -0
  160. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +1 -0
  161. package/dist/types/features/page_action/aggregate/index.d.ts +3 -3
  162. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  163. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
  164. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  165. package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -2
  166. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  167. package/dist/types/features/session_replay/aggregate/index.d.ts +96 -0
  168. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -0
  169. package/dist/types/features/session_replay/constants.d.ts +2 -0
  170. package/dist/types/features/session_replay/constants.d.ts.map +1 -0
  171. package/dist/types/features/session_replay/index.d.ts +2 -0
  172. package/dist/types/features/session_replay/index.d.ts.map +1 -0
  173. package/dist/types/features/session_replay/instrument/index.d.ts +6 -0
  174. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -0
  175. package/dist/types/features/session_trace/aggregate/index.d.ts +8 -57
  176. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  177. package/dist/types/features/session_trace/constants.d.ts +0 -3
  178. package/dist/types/features/session_trace/constants.d.ts.map +1 -1
  179. package/dist/types/features/session_trace/instrument/index.d.ts +1 -3
  180. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  181. package/dist/types/features/spa/aggregate/index.d.ts +2 -2
  182. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  183. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  184. package/dist/types/features/utils/aggregate-base.d.ts +11 -0
  185. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -0
  186. package/dist/types/features/utils/feature-base.d.ts +0 -5
  187. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  188. package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
  189. package/dist/types/features/utils/instrument-base.d.ts +3 -1
  190. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  191. package/dist/types/features/utils/{lazy-loader.d.ts → lazy-feature-loader.d.ts} +2 -2
  192. package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -0
  193. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  194. package/dist/types/loaders/features/featureDependencies.d.ts +0 -1
  195. package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
  196. package/dist/types/loaders/features/features.d.ts +1 -0
  197. package/dist/types/loaders/features/features.d.ts.map +1 -1
  198. package/package.json +31 -22
  199. package/src/cdn/polyfills.js +4 -1
  200. package/src/common/config/state/configurable.js +18 -24
  201. package/src/common/config/state/info.js +2 -2
  202. package/src/common/config/state/init.js +62 -28
  203. package/src/common/config/state/loader-config.js +2 -2
  204. package/src/common/config/state/runtime.js +2 -4
  205. package/src/common/drain/drain.js +1 -1
  206. package/src/common/harvest/harvest-scheduler.js +35 -10
  207. package/src/common/harvest/harvest.js +73 -50
  208. package/src/common/session/session-entity.js +34 -23
  209. package/src/common/session/session-entity.test.js +57 -51
  210. package/src/common/timer/interaction-timer.js +9 -12
  211. package/src/common/url/canonicalize-url.js +28 -0
  212. package/src/common/url/canonicalize-url.test.js +34 -0
  213. package/src/common/url/clean-url.js +10 -3
  214. package/src/common/url/protocol.test.js +0 -1
  215. package/src/common/util/feature-flags.js +2 -2
  216. package/src/common/util/global-scope.js +2 -0
  217. package/src/common/util/submit-data.js +28 -17
  218. package/src/common/wrap/wrap-fetch.js +1 -2
  219. package/src/common/wrap/wrap-function.js +1 -2
  220. package/src/common/wrap/wrap-promise.js +1 -1
  221. package/src/features/ajax/aggregate/index.js +2 -2
  222. package/src/features/ajax/instrument/index.js +1 -1
  223. package/src/features/jserrors/aggregate/canonical-function-name.js +12 -4
  224. package/src/features/jserrors/aggregate/compute-stack-trace.js +85 -11
  225. package/src/features/jserrors/aggregate/compute-stack-trace.test.js +141 -24
  226. package/src/features/jserrors/aggregate/index.js +28 -52
  227. package/src/features/jserrors/instrument/index.js +0 -1
  228. package/src/features/metrics/aggregate/framework-detection.js +73 -0
  229. package/src/features/metrics/aggregate/framework-detection.test.js +201 -0
  230. package/src/features/metrics/aggregate/index.js +8 -3
  231. package/src/features/metrics/aggregate/polyfill-detection.es5.js +9 -0
  232. package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +16 -0
  233. package/src/features/metrics/aggregate/polyfill-detection.js +48 -0
  234. package/src/features/metrics/aggregate/polyfill-detection.test.js +163 -0
  235. package/src/features/page_action/aggregate/index.js +2 -2
  236. package/src/features/page_view_event/aggregate/index.js +5 -5
  237. package/src/features/page_view_timing/aggregate/index.js +2 -2
  238. package/src/features/session_replay/aggregate/index.js +314 -0
  239. package/src/features/session_replay/constants.js +3 -0
  240. package/src/features/session_replay/index.js +12 -0
  241. package/src/features/session_replay/instrument/index.js +22 -0
  242. package/src/features/session_trace/aggregate/index.js +148 -188
  243. package/src/features/session_trace/constants.js +0 -4
  244. package/src/features/session_trace/instrument/index.js +17 -69
  245. package/src/features/spa/aggregate/index.js +2 -2
  246. package/src/features/utils/agent-session.js +1 -2
  247. package/src/features/utils/aggregate-base.js +51 -0
  248. package/src/features/utils/feature-base.js +1 -31
  249. package/src/features/utils/handler-cache.js +3 -4
  250. package/src/features/utils/instrument-base.js +40 -8
  251. package/src/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
  252. package/src/loaders/agent.js +1 -1
  253. package/src/loaders/api/apiAsync.js +1 -1
  254. package/src/loaders/configure/configure.js +4 -3
  255. package/src/loaders/features/featureDependencies.js +0 -12
  256. package/src/loaders/features/features.js +3 -1
  257. package/src/loaders/micro-agent.js +4 -4
  258. package/dist/cjs/common/metrics/framework-detection.js +0 -72
  259. package/dist/cjs/common/util/user-agent.js +0 -57
  260. package/dist/cjs/common/window/supports-performance-observer.js +0 -15
  261. package/dist/esm/common/metrics/framework-detection.js +0 -66
  262. package/dist/esm/common/util/user-agent.js +0 -48
  263. package/dist/esm/common/window/supports-performance-observer.js +0 -9
  264. package/dist/types/common/metrics/framework-detection.d.ts.map +0 -1
  265. package/dist/types/common/util/user-agent.d.ts +0 -5
  266. package/dist/types/common/util/user-agent.d.ts.map +0 -1
  267. package/dist/types/common/window/supports-performance-observer.d.ts +0 -2
  268. package/dist/types/common/window/supports-performance-observer.d.ts.map +0 -1
  269. package/dist/types/features/utils/lazy-loader.d.ts.map +0 -1
  270. package/src/common/metrics/framework-detection.js +0 -71
  271. package/src/common/util/user-agent.js +0 -56
  272. package/src/common/window/supports-performance-observer.js +0 -10
  273. /package/dist/types/{common/metrics → features/metrics/aggregate}/framework-detection.d.ts +0 -0
@@ -4,125 +4,95 @@
4
4
  */
5
5
  import { registerHandler } from '../../../common/event-emitter/register-handler'
6
6
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
7
- import { mapOwn } from '../../../common/util/map-own'
8
7
  import { stringify } from '../../../common/util/stringify'
9
8
  import { parseUrl } from '../../../common/url/parse-url'
10
- import { supportsPerformanceObserver } from '../../../common/window/supports-performance-observer'
11
- import slice from 'lodash._slice'
12
9
  import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config'
13
10
  import { now } from '../../../common/timing/now'
14
11
  import { FEATURE_NAME } from '../constants'
15
12
  import { drain } from '../../../common/drain/drain'
16
13
  import { HandlerCache } from '../../utils/handler-cache'
17
- import { FeatureBase } from '../../utils/feature-base'
14
+ import { AggregateBase } from '../../utils/aggregate-base'
15
+
16
+ const ignoredEvents = {
17
+ // we find that certain events make the data too noisy to be useful
18
+ global: { mouseup: true, mousedown: true },
19
+ // certain events are present both in the window and in PVT metrics. PVT metrics are prefered so the window events should be ignored
20
+ window: { load: true, pagehide: true },
21
+ // when ajax instrumentation is disabled, all XMLHttpRequest events will return with origin = xhrOriginMissing and should be ignored
22
+ xhrOriginMissing: { ignoreAll: true }
23
+ }
24
+ const toAggregate = {
25
+ typing: [1000, 2000],
26
+ scrolling: [100, 1000],
27
+ mousing: [1000, 2000],
28
+ touching: [1000, 2000]
29
+ }
30
+ const MAX_TRACE_DURATION = 15 * 60 * 1000 // 15 minutes
18
31
 
19
- export class Aggregate extends FeatureBase {
32
+ export class Aggregate extends AggregateBase {
20
33
  static featureName = FEATURE_NAME
21
- constructor (agentIdentifier, aggregator) {
34
+ constructor (agentIdentifier, aggregator, argsObj) {
22
35
  super(agentIdentifier, aggregator, FEATURE_NAME)
23
36
 
24
37
  // Very unlikely, but in case the existing XMLHttpRequest.prototype object on the page couldn't be wrapped.
25
38
  if (!getRuntime(agentIdentifier).xhrWrappable) return
26
39
 
27
- const handlerCache = new HandlerCache()
40
+ this.resourceObserver = argsObj?.resourceObserver // undefined if observer couldn't be created
28
41
  this.ptid = ''
29
- this.ignoredEvents = {
30
- // we find that certain events make the data too noisy to be useful
31
- global: { mouseup: true, mousedown: true },
32
- // certain events are present both in the window and in PVT metrics. PVT metrics are prefered so the window events should be ignored
33
- window: { load: true, pagehide: true },
34
- // when ajax instrumentation is disabled, all XMLHttpRequest events will return with origin = xhrOriginMissing and should be ignored
35
- xhrOriginMissing: { ignoreAll: true }
36
- }
37
- this.toAggregate = {
38
- typing: [1000, 2000],
39
- scrolling: [100, 1000],
40
- mousing: [1000, 2000],
41
- touching: [1000, 2000]
42
- }
43
- this.rename = {
44
- typing: {
45
- keydown: true,
46
- keyup: true,
47
- keypress: true
48
- },
49
- mousing: {
50
- mousemove: true,
51
- mouseenter: true,
52
- mouseleave: true,
53
- mouseover: true,
54
- mouseout: true
55
- },
56
- scrolling: {
57
- scroll: true
58
- },
59
- touching: {
60
- touchstart: true,
61
- touchmove: true,
62
- touchend: true,
63
- touchcancel: true,
64
- touchenter: true,
65
- touchleave: true
66
- }
67
- }
68
-
69
42
  this.trace = {}
70
43
  this.nodeCount = 0
71
44
  this.sentTrace = null
72
45
  this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10
73
46
  this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000
74
-
75
47
  this.laststart = 0
76
48
 
49
+ const handlerCache = new HandlerCache()
50
+
77
51
  registerHandler('feat-stn', () => {
78
52
  if (typeof PerformanceNavigationTiming !== 'undefined') {
79
- this.storeTiming(window.performance?.getEntriesByType('navigation')?.[0] || {})
53
+ this.storeTiming(window.performance.getEntriesByType('navigation')[0])
80
54
  } else {
81
- this.storeTiming(window.performance?.timing)
55
+ this.storeTiming(window.performance.timing)
82
56
  }
83
57
 
84
- var scheduler = new HarvestScheduler('resources', {
58
+ const scheduler = new HarvestScheduler('resources', {
85
59
  onFinished: onHarvestFinished.bind(this),
86
60
  retryDelay: this.harvestTimeSeconds
87
61
  }, this)
88
62
  scheduler.harvest.on('resources', prepareHarvest.bind(this))
89
63
  scheduler.runHarvest({ needResponse: true }) // sends first stn harvest immediately
64
+ handlerCache.decide(true)
90
65
 
91
66
  function onHarvestFinished (result) {
92
- // start timer only if ptid was returned by server
93
- if (result.sent && result.responseText && !this.ptid) {
94
- this.ptid = result.responseText
95
- getRuntime(this.agentIdentifier).ptid = this.ptid
67
+ if (result.sent && result.responseText && !this.ptid) { // continue interval harvest only if ptid was returned by server on the first
68
+ getRuntime(this.agentIdentifier).ptid = this.ptid = result.responseText
96
69
  scheduler.startTimer(this.harvestTimeSeconds)
97
70
  }
98
71
 
99
- if (result.sent && result.retry && this.sentTrace) {
100
- mapOwn(this.sentTrace, (name, nodes) => {
101
- this.mergeSTNs(name, nodes)
72
+ if (result.sent && result.retry && this.sentTrace) { // merge previous trace back into buffer to retry for next harvest
73
+ Object.entries(this.sentTrace).forEach(([name, listOfSTNodes]) => {
74
+ if (this.nodeCount >= this.maxNodesPerHarvest) return
75
+
76
+ this.nodeCount += listOfSTNodes.length
77
+ this.trace[name] = this.trace[name] ? listOfSTNodes.concat(this.trace[name]) : listOfSTNodes
102
78
  })
103
79
  this.sentTrace = null
104
80
  }
105
81
  }
106
-
107
82
  function prepareHarvest (options) {
108
- if ((now()) > (15 * 60 * 1000)) {
109
- // been collecting for over 15 min, empty trace object and bail
83
+ if (now() > MAX_TRACE_DURATION) { // been collecting for over 15 min, empty trace object and bail
110
84
  scheduler.stopTimer()
111
85
  this.trace = {}
112
86
  return
113
87
  }
114
-
115
- // only send when there are more than 30 nodes to send
88
+ // Only harvest when there are more than 30 nodes to send after the very first.
116
89
  if (this.ptid && this.nodeCount <= 30) return
117
90
 
118
91
  return this.takeSTNs(options.retry)
119
92
  }
120
- handlerCache.decide(true)
121
93
  }, this.featureName, this.ee)
122
94
 
123
- registerHandler('block-stn', () => {
124
- handlerCache.decide(false)
125
- }, this.featureName, this.ee)
95
+ registerHandler('block-stn', () => handlerCache.decide(false), this.featureName, this.ee)
126
96
 
127
97
  // register the handlers immediately... but let the handlerCache decide if the data should actually get stored...
128
98
  registerHandler('bst', (...args) => handlerCache.settle(() => this.storeEvent(...args)), this.featureName, this.ee)
@@ -136,17 +106,23 @@ export class Aggregate extends FeatureBase {
136
106
  drain(this.agentIdentifier, this.featureName)
137
107
  }
138
108
 
109
+ // PageViewTiming (FEATURE) events and metrics, such as 'load', 'lcp', etc. pipes into ST here.
139
110
  processPVT (name, value, attrs) {
140
- var t = {}
141
- t[name] = value
142
- this.storeTiming(t)
143
- if (this.hasFID(name, attrs)) this.storeEvent({ type: 'fid', target: 'document' }, 'document', value, value + attrs.fid)
111
+ this.storeTiming({ [name]: value })
112
+ if (hasFID(name, attrs)) this.storeEvent({ type: 'fid', target: 'document' }, 'document', value, value + attrs.fid)
113
+
114
+ function hasFID (name, attrs) {
115
+ return name === 'fi' && !!attrs && typeof attrs.fid === 'number'
116
+ }
144
117
  }
145
118
 
146
- storeTiming (_t) {
119
+ // This processes the aforementioned PVT and the first navigation entry of the page.
120
+ storeTiming (timingEntry) {
121
+ if (!timingEntry) return
122
+
147
123
  // loop iterates through prototype also (for FF)
148
- for (let key in _t) {
149
- const val = _t[key]
124
+ for (let key in timingEntry) {
125
+ let val = timingEntry[key]
150
126
 
151
127
  // ignore size and status type nodes that do not map to timestamp metrics
152
128
  const lck = key.toLowerCase()
@@ -154,39 +130,36 @@ export class Aggregate extends FeatureBase {
154
130
 
155
131
  // ignore inherited methods, meaningless 0 values, and bogus timestamps
156
132
  // that are in the future (Microsoft Edge seems to sometimes produce these)
157
- if (!(typeof (val) === 'number' && val >= 0)) continue
158
-
159
- const timeOffset = Math.round(_t[key])
133
+ if (!(typeof val === 'number' && val >= 0)) continue
160
134
 
135
+ val = Math.round(val)
161
136
  this.storeSTN({
162
137
  n: key,
163
- s: timeOffset,
164
- e: timeOffset,
138
+ s: val,
139
+ e: val,
165
140
  o: 'document',
166
141
  t: 'timing'
167
142
  })
168
143
  }
169
144
  }
170
145
 
146
+ // Tracks duration of native APIs wrapped by wrap-timer & wrap-raf.
171
147
  storeTimer (target, start, end, type) {
172
- var category = 'timer'
173
- if (type === 'requestAnimationFrame') category = type
174
-
175
- var evt = {
148
+ const evt = {
176
149
  n: type,
177
150
  s: start,
178
151
  e: end,
179
152
  o: 'window',
180
- t: category
153
+ t: (type === 'requestAnimationFrame') ? type : 'timer'
181
154
  }
182
-
183
155
  this.storeSTN(evt)
184
156
  }
185
157
 
158
+ // Tracks the events and their listener's duration on objects wrapped by wrap-events.
186
159
  storeEvent (currentEvent, target, start, end) {
187
- if (this.shouldIgnoreEvent(currentEvent, target)) return false
160
+ if (this.shouldIgnoreEvent(currentEvent, target)) return
188
161
 
189
- var evt = {
162
+ const evt = {
190
163
  n: this.evtName(currentEvent.type),
191
164
  s: start,
192
165
  e: end,
@@ -200,31 +173,56 @@ export class Aggregate extends FeatureBase {
200
173
  } catch (e) {
201
174
  evt.o = this.evtOrigin(null, target)
202
175
  }
203
-
204
176
  this.storeSTN(evt)
205
177
  }
206
178
 
207
- evtName (type) {
208
- var name = type
209
-
210
- mapOwn(this.rename, function (key, val) {
211
- if (type in val) name = key
212
- })
179
+ shouldIgnoreEvent (event, target) {
180
+ const origin = this.evtOrigin(event.target, target)
181
+ if (event.type in ignoredEvents.global) return true
182
+ if (!!ignoredEvents[origin] && ignoredEvents[origin].ignoreAll) return true
183
+ if (!!ignoredEvents[origin] && event.type in ignoredEvents[origin]) return true
184
+ return false
185
+ }
213
186
 
214
- return name
187
+ evtName (type) {
188
+ switch (type) {
189
+ case 'keydown':
190
+ case 'keyup':
191
+ case 'keypress':
192
+ return 'typing'
193
+ case 'mousemove':
194
+ case 'mouseenter':
195
+ case 'mouseleave':
196
+ case 'mouseover':
197
+ case 'mouseout':
198
+ return 'mousing'
199
+ case 'scroll':
200
+ return 'scrolling'
201
+ case 'touchstart':
202
+ case 'touchmove':
203
+ case 'touchend':
204
+ case 'touchcancel':
205
+ case 'touchenter':
206
+ case 'touchleave':
207
+ return 'touching'
208
+ default:
209
+ return type
210
+ }
215
211
  }
216
212
 
217
213
  evtOrigin (t, target) {
218
- var origin = 'unknown'
214
+ let origin = 'unknown'
219
215
 
220
216
  if (t && t instanceof XMLHttpRequest) {
221
- var params = this.ee.context(t).params
217
+ const params = this.ee.context(t).params
222
218
  if (!params || !params.status || !params.method || !params.host || !params.pathname) return 'xhrOriginMissing'
223
219
  origin = params.status + ' ' + params.method + ': ' + params.host + params.pathname
224
220
  } else if (t && typeof (t.tagName) === 'string') {
225
221
  origin = t.tagName.toLowerCase()
226
222
  if (t.id) origin += '#' + t.id
227
- if (t.className) origin += '.' + slice(t.classList).join('.')
223
+ if (t.className) {
224
+ for (let i = 0; i < t.classList.length; i++) origin += '.' + t.classList[i]
225
+ }
228
226
  }
229
227
 
230
228
  if (origin === 'unknown') {
@@ -237,43 +235,43 @@ export class Aggregate extends FeatureBase {
237
235
  return origin
238
236
  }
239
237
 
238
+ // Tracks when the window history API specified by wrap-history is used.
240
239
  storeHist (path, old, time) {
241
- var node = {
240
+ const node = {
242
241
  n: 'history.pushState',
243
242
  s: time,
244
243
  e: time,
245
244
  o: path,
246
245
  t: old
247
246
  }
248
-
249
247
  this.storeSTN(node)
250
248
  }
251
249
 
250
+ // Processes all the PerformanceResourceTiming entries captured (by observer).
252
251
  storeResources (resources) {
253
252
  if (!resources || resources.length === 0) return
254
253
 
255
254
  resources.forEach((currentResource) => {
256
- var parsed = parseUrl(currentResource.name)
257
- var res = {
255
+ if ((currentResource.fetchStart | 0) <= this.laststart) return // don't recollect already-seen resources
256
+
257
+ const parsed = parseUrl(currentResource.name)
258
+ const res = {
258
259
  n: currentResource.initiatorType,
259
260
  s: currentResource.fetchStart | 0,
260
261
  e: currentResource.responseEnd | 0,
261
262
  o: parsed.protocol + '://' + parsed.hostname + ':' + parsed.port + parsed.pathname, // resource.name is actually a URL so it's the source
262
263
  t: currentResource.entryType
263
264
  }
264
-
265
- // don't recollect old resources
266
- if (res.s <= this.laststart) return
267
-
268
265
  this.storeSTN(res)
269
266
  })
270
267
 
271
268
  this.laststart = resources[resources.length - 1].fetchStart | 0
272
269
  }
273
270
 
271
+ // JavascriptError (FEATURE) events pipes into ST here.
274
272
  storeErrorAgg (type, name, params, metrics) {
275
- if (type !== 'err') return
276
- var node = {
273
+ if (type !== 'err') return // internal errors are purposefully ignored
274
+ const node = {
277
275
  n: 'error',
278
276
  s: metrics.time,
279
277
  e: metrics.time,
@@ -283,9 +281,10 @@ export class Aggregate extends FeatureBase {
283
281
  this.storeSTN(node)
284
282
  }
285
283
 
284
+ // Ajax (FEATURE) events--XML & fetches--pipes into ST here.
286
285
  storeXhrAgg (type, name, params, metrics) {
287
286
  if (type !== 'xhr') return
288
- var node = {
287
+ const node = {
289
288
  n: 'Ajax',
290
289
  s: metrics.time,
291
290
  e: metrics.time + metrics.duration,
@@ -295,42 +294,29 @@ export class Aggregate extends FeatureBase {
295
294
  this.storeSTN(node)
296
295
  }
297
296
 
297
+ // Central function called by all the other store__ & addToTrace API to append a trace node.
298
298
  storeSTN (stn) {
299
- // limit the number of data that is stored
300
- if (this.nodeCount >= this.maxNodesPerHarvest) return
299
+ if (this.nodeCount >= this.maxNodesPerHarvest) return // limit the amount of data that is stored at once
301
300
 
302
- var traceArr = this.trace[stn.n]
303
- if (!traceArr) traceArr = this.trace[stn.n] = []
301
+ if (this.trace[stn.n]) this.trace[stn.n].push(stn)
302
+ else this.trace[stn.n] = [stn]
304
303
 
305
- traceArr.push(stn)
306
304
  this.nodeCount++
307
305
  }
308
306
 
309
- mergeSTNs (key, nodes) {
310
- // limit the number of data that is stored
311
- if (this.nodeCount >= this.maxNodesPerHarvest) return
312
-
313
- var traceArr = this.trace[key]
314
- if (!traceArr) traceArr = this.trace[key] = []
315
-
316
- this.trace[key] = nodes.concat(traceArr)
317
- this.nodeCount += nodes.length
318
- }
319
-
307
+ // Used by session trace's harvester to create the payload body.
320
308
  takeSTNs (retry) {
321
- // if the observer is not being used, this checks resourcetiming buffer every harvest
322
- if (!supportsPerformanceObserver()) {
309
+ if (!this.resourceObserver) { // if PO isn't supported, this checks resourcetiming buffer every harvest.
323
310
  this.storeResources(window.performance.getEntriesByType('resource'))
324
311
  }
325
312
 
326
- var stns = mapOwn(this.trace, (name, nodes) => {
327
- if (!(name in this.toAggregate)) return nodes
328
-
329
- return mapOwn(
330
- nodes.sort(this.byStart).reduce(this.smearEvtsByOrigin(name), {}), this.val
331
- ).reduce(this.flatten, [])
332
- }).reduce(this.flatten, [])
333
-
313
+ const stns = Object.entries(this.trace).flatMap(([name, listOfSTNodes]) => { // basically take the "this.trace" map-obj and concat all the list-type values
314
+ if (!(name in toAggregate)) return listOfSTNodes
315
+ // Special processing for event nodes dealing with user inputs:
316
+ const reindexByOriginFn = this.smearEvtsByOrigin(name)
317
+ const partitionListByOriginMap = listOfSTNodes.sort((a, b) => a.s - b.s).reduce(reindexByOriginFn, {})
318
+ return Object.values(partitionListByOriginMap).flat() // join the partitions back into 1-D, now ordered by origin then start time
319
+ }, this)
334
320
  if (stns.length === 0) return {}
335
321
 
336
322
  if (retry) {
@@ -339,75 +325,49 @@ export class Aggregate extends FeatureBase {
339
325
  this.trace = {}
340
326
  this.nodeCount = 0
341
327
 
342
- var stnInfo = {
343
- qs: { st: '' + getRuntime(this.agentIdentifier).offset },
328
+ const stnInfo = {
329
+ qs: { st: String(getRuntime(this.agentIdentifier).offset) },
344
330
  body: { res: stns }
345
331
  }
346
-
347
- if (!this.ptid) {
332
+ if (!this.ptid) { // send custom and user attributes on the very first ST harvest only
348
333
  const { userAttributes, atts, jsAttributes } = getInfo(this.agentIdentifier)
349
334
  stnInfo.qs.ua = userAttributes
350
335
  stnInfo.qs.at = atts
351
- var ja = stringify(jsAttributes)
336
+ const ja = stringify(jsAttributes)
352
337
  stnInfo.qs.ja = ja === '{}' ? null : ja
353
338
  }
354
339
  return stnInfo
355
340
  }
356
341
 
357
- byStart (a, b) {
358
- return a.s - b.s
359
- }
360
-
361
342
  smearEvtsByOrigin (name) {
362
- var maxGap = this.toAggregate[name][0]
363
- var maxLen = this.toAggregate[name][1]
364
- var lastO = {}
365
-
366
- return (byOrigin, evt) => {
367
- var lastArr = byOrigin[evt.o]
368
-
369
- lastArr || (lastArr = byOrigin[evt.o] = [])
370
-
371
- var last = lastO[evt.o]
372
-
373
- if (name === 'scrolling' && !this.trivial(evt)) {
374
- lastO[evt.o] = null
375
- evt.n = 'scroll'
376
- lastArr.push(evt)
377
- } else if (last && (evt.s - last.s) < maxLen && last.e > (evt.s - maxGap)) {
378
- last.e = evt.e
343
+ const maxGap = toAggregate[name][0]
344
+ const maxLen = toAggregate[name][1]
345
+ const lastO = {}
346
+
347
+ return (byOrigin, evtNode) => {
348
+ let lastArr = byOrigin[evtNode.o]
349
+ if (!lastArr) lastArr = byOrigin[evtNode.o] = []
350
+
351
+ const last = lastO[evtNode.o]
352
+
353
+ if (name === 'scrolling' && !trivial(evtNode)) {
354
+ lastO[evtNode.o] = null
355
+ evtNode.n = 'scroll'
356
+ lastArr.push(evtNode)
357
+ } else if (last && (evtNode.s - last.s) < maxLen && last.e > (evtNode.s - maxGap)) {
358
+ last.e = evtNode.e
379
359
  } else {
380
- lastO[evt.o] = evt
381
- lastArr.push(evt)
360
+ lastO[evtNode.o] = evtNode
361
+ lastArr.push(evtNode)
382
362
  }
383
363
 
384
364
  return byOrigin
385
365
  }
386
- }
387
-
388
- val (key, value) {
389
- return value
390
- }
391
-
392
- flatten (a, b) {
393
- return a.concat(b)
394
- }
395
366
 
396
- hasFID (name, attrs) {
397
- return name === 'fi' && !!attrs && typeof attrs.fid === 'number'
398
- }
399
-
400
- trivial (node) {
401
- var limit = 4
402
- if (node && typeof node.e === 'number' && typeof node.s === 'number' && (node.e - node.s) < limit) return true
403
- else return false
404
- }
405
-
406
- shouldIgnoreEvent (event, target) {
407
- var origin = this.evtOrigin(event.target, target)
408
- if (event.type in this.ignoredEvents.global) return true
409
- if (!!this.ignoredEvents[origin] && this.ignoredEvents[origin].ignoreAll) return true
410
- if (!!this.ignoredEvents[origin] && event.type in this.ignoredEvents[origin]) return true
411
- return false
367
+ function trivial (node) {
368
+ const limit = 4
369
+ if (node && typeof node.e === 'number' && typeof node.s === 'number' && (node.e - node.s) < limit) return true
370
+ else return false
371
+ }
412
372
  }
413
373
  }
@@ -1,8 +1,6 @@
1
- import { originals } from '../../common/config/config'
2
1
  import { FEATURE_NAMES } from '../../loaders/features/features'
3
2
 
4
3
  export const FEATURE_NAME = FEATURE_NAMES.sessionTrace
5
- export const RESOURCE_TIMING_BUFFER_FULL = 'resourcetimingbufferfull'
6
4
  export const BST_RESOURCE = 'bstResource'
7
5
  export const RESOURCE = 'resource'
8
6
  export const START = '-start'
@@ -11,5 +9,3 @@ export const FN_START = 'fn' + START
11
9
  export const FN_END = 'fn' + END
12
10
  export const BST_TIMER = 'bstTimer'
13
11
  export const PUSH_STATE = 'pushState'
14
- export const ORIG_EVENT = originals.EV
15
- export const ADD_EVENT_LISTENER = 'addEventListener'