@newrelic/browser-agent 0.0.9 → 0.1.229

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 (339) hide show
  1. package/README.md +84 -207
  2. package/dist/cjs/cdn/lite.js +14 -0
  3. package/dist/cjs/cdn/polyfills/lite.js +4 -0
  4. package/dist/cjs/cdn/polyfills/pro.js +4 -0
  5. package/dist/cjs/cdn/polyfills/spa.js +4 -0
  6. package/dist/cjs/cdn/polyfills.js +14 -0
  7. package/dist/cjs/cdn/pro.js +19 -0
  8. package/dist/cjs/cdn/spa.js +19 -0
  9. package/dist/cjs/cdn/worker.js +16 -0
  10. package/dist/cjs/common/aggregate/aggregator.js +168 -0
  11. package/dist/cjs/common/browser-version/firefox-version.js +17 -0
  12. package/dist/cjs/common/browser-version/ios-version.js +18 -0
  13. package/dist/cjs/common/config/config.js +76 -0
  14. package/dist/cjs/common/config/state/configurable.js +32 -0
  15. package/dist/cjs/common/config/state/info.js +50 -0
  16. package/dist/cjs/common/config/state/init.js +86 -0
  17. package/dist/cjs/common/config/state/loader-config.js +28 -0
  18. package/dist/cjs/common/config/state/originals.js +9 -0
  19. package/dist/cjs/common/config/state/runtime.js +50 -0
  20. package/dist/cjs/common/constants/environment-variables.js +20 -0
  21. package/dist/cjs/common/context/shared-context.js +25 -0
  22. package/dist/cjs/common/deny-list/deny-list.js +108 -0
  23. package/dist/cjs/common/drain/drain.js +126 -0
  24. package/dist/cjs/common/event-emitter/contextual-ee.js +149 -0
  25. package/dist/cjs/common/event-emitter/handle.js +24 -0
  26. package/dist/cjs/common/event-emitter/register-handler.js +24 -0
  27. package/dist/cjs/common/event-listener/event-listener-opts.js +46 -0
  28. package/dist/cjs/common/harvest/harvest-scheduler.js +111 -0
  29. package/dist/cjs/common/harvest/harvest.js +236 -0
  30. package/dist/cjs/common/ids/id.js +30 -0
  31. package/dist/cjs/common/ids/unique-id.js +84 -0
  32. package/dist/cjs/common/metrics/framework-detection.js +72 -0
  33. package/dist/cjs/common/metrics/paint-metrics.js +13 -0
  34. package/dist/cjs/common/serialize/bel-serializer.js +89 -0
  35. package/dist/cjs/common/timing/nav-timing.js +77 -0
  36. package/dist/cjs/common/timing/now.js +15 -0
  37. package/dist/cjs/common/unload/eol.js +69 -0
  38. package/dist/cjs/common/url/clean-url.js +16 -0
  39. package/dist/cjs/common/url/encode.js +79 -0
  40. package/dist/cjs/common/url/location.js +14 -0
  41. package/dist/cjs/common/url/parse-url.js +66 -0
  42. package/dist/cjs/common/url/protocol.js +25 -0
  43. package/dist/cjs/common/util/console.js +17 -0
  44. package/dist/cjs/common/util/data-size.js +25 -0
  45. package/dist/cjs/common/util/feature-flags.js +42 -0
  46. package/dist/cjs/common/util/get-or-set.js +39 -0
  47. package/dist/cjs/common/util/global-scope.js +56 -0
  48. package/dist/cjs/common/util/map-own.js +24 -0
  49. package/dist/cjs/common/util/obfuscate.js +76 -0
  50. package/dist/cjs/common/util/reduce.js +22 -0
  51. package/dist/cjs/common/util/s-hash.js +19 -0
  52. package/dist/cjs/common/util/single.js +23 -0
  53. package/dist/cjs/common/util/stringify.js +47 -0
  54. package/dist/cjs/common/util/submit-data.js +99 -0
  55. package/dist/cjs/common/util/traverse.js +41 -0
  56. package/dist/cjs/common/util/user-agent.js +57 -0
  57. package/dist/cjs/common/window/load.js +19 -0
  58. package/dist/cjs/common/window/nreum.js +107 -0
  59. package/dist/cjs/common/window/page-visibility.js +28 -0
  60. package/dist/cjs/common/window/session-storage.js +42 -0
  61. package/dist/cjs/common/window/supports-performance-observer.js +15 -0
  62. package/dist/cjs/common/window/top-level-callers.js +23 -0
  63. package/dist/cjs/common/wrap/index.js +68 -0
  64. package/dist/cjs/common/wrap/wrap-events.js +105 -0
  65. package/dist/cjs/common/wrap/wrap-fetch.js +114 -0
  66. package/dist/cjs/common/wrap/wrap-function.js +269 -0
  67. package/dist/cjs/common/wrap/wrap-history.js +56 -0
  68. package/dist/cjs/common/wrap/wrap-jsonp.js +129 -0
  69. package/dist/cjs/common/wrap/wrap-mutation.js +61 -0
  70. package/dist/cjs/common/wrap/wrap-promise.js +160 -0
  71. package/dist/cjs/common/wrap/wrap-raf.js +55 -0
  72. package/dist/cjs/common/wrap/wrap-timer.js +70 -0
  73. package/dist/cjs/common/wrap/wrap-xhr.js +206 -0
  74. package/dist/cjs/features/ajax/aggregate/index.js +226 -0
  75. package/dist/cjs/features/ajax/constants.js +9 -0
  76. package/dist/cjs/features/ajax/index.js +12 -0
  77. package/dist/cjs/features/ajax/instrument/distributed-tracing.js +145 -0
  78. package/dist/cjs/features/ajax/instrument/index.js +338 -0
  79. package/dist/cjs/features/ajax/instrument/response-size.js +26 -0
  80. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +18 -0
  81. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.test.js +30 -0
  82. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +216 -0
  83. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +257 -0
  84. package/dist/cjs/features/jserrors/aggregate/format-stack-trace.js +36 -0
  85. package/dist/cjs/features/jserrors/aggregate/format-stack-trace.test.js +39 -0
  86. package/dist/cjs/features/jserrors/aggregate/index.js +267 -0
  87. package/dist/cjs/features/jserrors/aggregate/string-hash-code.js +23 -0
  88. package/dist/cjs/features/jserrors/aggregate/string-hash-code.test.js +26 -0
  89. package/dist/cjs/features/jserrors/constants.js +11 -0
  90. package/dist/cjs/features/jserrors/index.js +12 -0
  91. package/dist/cjs/features/jserrors/instrument/debug.js +40 -0
  92. package/dist/cjs/features/jserrors/instrument/index.js +158 -0
  93. package/dist/cjs/features/metrics/aggregate/index.js +136 -0
  94. package/dist/cjs/features/metrics/constants.js +17 -0
  95. package/dist/cjs/features/metrics/index.js +12 -0
  96. package/dist/cjs/features/metrics/instrument/index.js +20 -0
  97. package/dist/cjs/features/metrics/instrument/workers-helper.js +121 -0
  98. package/dist/cjs/features/page_action/aggregate/index.js +112 -0
  99. package/dist/cjs/features/page_action/constants.js +9 -0
  100. package/dist/cjs/features/page_action/index.js +12 -0
  101. package/dist/cjs/features/page_action/instrument/index.js +21 -0
  102. package/dist/cjs/features/page_view_event/aggregate/index.js +133 -0
  103. package/dist/cjs/features/page_view_event/aggregate/initialized-features.js +39 -0
  104. package/dist/cjs/features/page_view_event/constants.js +15 -0
  105. package/dist/cjs/features/page_view_event/index.js +12 -0
  106. package/dist/cjs/features/page_view_event/instrument/index.js +38 -0
  107. package/dist/cjs/features/page_view_timing/aggregate/index.js +265 -0
  108. package/dist/cjs/features/page_view_timing/constants.js +9 -0
  109. package/dist/cjs/features/page_view_timing/first-paint.js +50 -0
  110. package/dist/cjs/features/page_view_timing/index.js +12 -0
  111. package/dist/cjs/features/page_view_timing/instrument/index.js +36 -0
  112. package/dist/cjs/features/page_view_timing/long-tasks.js +75 -0
  113. package/dist/cjs/features/session_trace/aggregate/index.js +375 -0
  114. package/dist/cjs/features/session_trace/constants.js +32 -0
  115. package/dist/cjs/features/session_trace/index.js +12 -0
  116. package/dist/cjs/features/session_trace/instrument/index.js +133 -0
  117. package/dist/cjs/features/spa/aggregate/index.js +684 -0
  118. package/dist/cjs/features/spa/aggregate/interaction-node.js +84 -0
  119. package/dist/cjs/features/spa/aggregate/interaction-node.test.js +16 -0
  120. package/dist/cjs/features/spa/aggregate/interaction.js +98 -0
  121. package/dist/cjs/features/spa/aggregate/serializer.js +147 -0
  122. package/dist/cjs/features/spa/constants.js +53 -0
  123. package/dist/cjs/features/spa/index.js +12 -0
  124. package/dist/cjs/features/spa/instrument/index.js +114 -0
  125. package/dist/cjs/features/utils/aggregate-base.js +13 -0
  126. package/dist/cjs/features/utils/feature-base.js +58 -0
  127. package/dist/cjs/features/utils/handler-cache.js +64 -0
  128. package/dist/cjs/features/utils/instrument-base.js +71 -0
  129. package/dist/cjs/features/utils/lazy-loader.js +44 -0
  130. package/dist/cjs/index.js +81 -58
  131. package/dist/cjs/loaders/agent.js +86 -0
  132. package/dist/cjs/loaders/api/api.js +109 -0
  133. package/dist/cjs/loaders/api/apiAsync.js +94 -0
  134. package/dist/cjs/loaders/browser-agent.js +29 -0
  135. package/dist/cjs/loaders/configure/configure.js +47 -0
  136. package/dist/cjs/loaders/features/enabled-features.js +19 -0
  137. package/dist/cjs/loaders/features/featureDependencies.js +32 -0
  138. package/dist/cjs/loaders/features/features.js +33 -0
  139. package/dist/cjs/loaders/micro-agent.js +93 -0
  140. package/dist/cjs/loaders/worker-agent.js +24 -0
  141. package/dist/esm/cdn/lite.js +12 -0
  142. package/dist/esm/cdn/polyfills/lite.js +7 -0
  143. package/dist/esm/cdn/polyfills/pro.js +7 -0
  144. package/dist/esm/cdn/polyfills/spa.js +7 -0
  145. package/dist/esm/cdn/polyfills.js +17 -0
  146. package/dist/esm/cdn/pro.js +17 -0
  147. package/dist/esm/cdn/spa.js +17 -0
  148. package/dist/esm/cdn/worker.js +14 -0
  149. package/dist/esm/common/aggregate/aggregator.js +161 -0
  150. package/dist/esm/common/browser-version/firefox-version.js +10 -0
  151. package/dist/esm/common/browser-version/ios-version.js +10 -0
  152. package/dist/esm/common/config/config.js +11 -0
  153. package/dist/esm/common/config/state/configurable.js +25 -0
  154. package/dist/esm/common/config/state/info.js +42 -0
  155. package/dist/esm/common/config/state/init.js +78 -0
  156. package/dist/esm/common/config/state/loader-config.js +21 -0
  157. package/dist/esm/common/config/state/originals.js +2 -0
  158. package/dist/esm/common/config/state/runtime.js +41 -0
  159. package/dist/esm/common/constants/environment-variables.js +11 -0
  160. package/dist/esm/common/context/shared-context.js +18 -0
  161. package/dist/esm/common/deny-list/deny-list.js +101 -0
  162. package/dist/esm/common/drain/drain.js +119 -0
  163. package/dist/esm/common/event-emitter/contextual-ee.js +142 -0
  164. package/dist/esm/common/event-emitter/handle.js +16 -0
  165. package/dist/esm/common/event-emitter/register-handler.js +19 -0
  166. package/dist/esm/common/event-listener/event-listener-opts.js +39 -0
  167. package/dist/esm/common/harvest/harvest-scheduler.js +105 -0
  168. package/dist/esm/common/harvest/harvest.js +228 -0
  169. package/dist/esm/common/ids/id.js +23 -0
  170. package/dist/esm/common/ids/unique-id.js +75 -0
  171. package/dist/esm/common/metrics/framework-detection.js +66 -0
  172. package/dist/esm/common/metrics/paint-metrics.js +6 -0
  173. package/dist/esm/common/serialize/bel-serializer.js +80 -0
  174. package/dist/esm/common/timing/nav-timing.js +67 -0
  175. package/dist/esm/common/timing/now.js +9 -0
  176. package/dist/esm/common/unload/eol.js +62 -0
  177. package/dist/esm/common/url/clean-url.js +10 -0
  178. package/dist/esm/common/url/encode.js +71 -0
  179. package/dist/esm/common/url/location.js +8 -0
  180. package/dist/esm/common/url/parse-url.js +60 -0
  181. package/dist/esm/common/url/protocol.js +17 -0
  182. package/dist/esm/common/util/console.js +11 -0
  183. package/dist/esm/common/util/data-size.js +19 -0
  184. package/dist/esm/common/util/feature-flags.js +33 -0
  185. package/dist/esm/common/util/get-or-set.js +33 -0
  186. package/dist/esm/common/util/global-scope.js +44 -0
  187. package/dist/esm/common/util/map-own.js +18 -0
  188. package/dist/esm/common/util/obfuscate.js +67 -0
  189. package/dist/esm/common/util/reduce.js +16 -0
  190. package/dist/esm/common/util/s-hash.js +13 -0
  191. package/dist/esm/common/util/single.js +16 -0
  192. package/dist/esm/common/util/stringify.js +42 -0
  193. package/dist/esm/common/util/submit-data.js +91 -0
  194. package/dist/esm/common/util/traverse.js +35 -0
  195. package/dist/esm/common/util/user-agent.js +48 -0
  196. package/dist/esm/common/window/load.js +12 -0
  197. package/dist/esm/common/window/nreum.js +91 -0
  198. package/dist/esm/common/window/page-visibility.js +23 -0
  199. package/dist/esm/common/window/session-storage.js +36 -0
  200. package/dist/esm/common/window/supports-performance-observer.js +9 -0
  201. package/dist/esm/common/window/top-level-callers.js +17 -0
  202. package/dist/esm/common/wrap/index.js +14 -0
  203. package/dist/esm/common/wrap/wrap-events.js +97 -0
  204. package/dist/esm/common/wrap/wrap-fetch.js +105 -0
  205. package/dist/esm/common/wrap/wrap-function.js +257 -0
  206. package/dist/esm/common/wrap/wrap-history.js +48 -0
  207. package/dist/esm/common/wrap/wrap-jsonp.js +122 -0
  208. package/dist/esm/common/wrap/wrap-mutation.js +54 -0
  209. package/dist/esm/common/wrap/wrap-promise.js +153 -0
  210. package/dist/esm/common/wrap/wrap-raf.js +48 -0
  211. package/dist/esm/common/wrap/wrap-timer.js +63 -0
  212. package/dist/esm/common/wrap/wrap-xhr.js +199 -0
  213. package/dist/esm/features/ajax/aggregate/index.js +218 -0
  214. package/dist/esm/features/ajax/constants.js +2 -0
  215. package/dist/esm/features/ajax/index.js +1 -0
  216. package/dist/esm/features/ajax/instrument/distributed-tracing.js +137 -0
  217. package/dist/esm/features/ajax/instrument/index.js +330 -0
  218. package/dist/esm/features/ajax/instrument/response-size.js +19 -0
  219. package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +12 -0
  220. package/dist/esm/features/jserrors/aggregate/canonical-function-name.test.js +28 -0
  221. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +209 -0
  222. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +255 -0
  223. package/dist/esm/features/jserrors/aggregate/format-stack-trace.js +29 -0
  224. package/dist/esm/features/jserrors/aggregate/format-stack-trace.test.js +37 -0
  225. package/dist/esm/features/jserrors/aggregate/index.js +260 -0
  226. package/dist/esm/features/jserrors/aggregate/string-hash-code.js +17 -0
  227. package/dist/esm/features/jserrors/aggregate/string-hash-code.test.js +24 -0
  228. package/dist/esm/features/jserrors/constants.js +3 -0
  229. package/dist/esm/features/jserrors/index.js +1 -0
  230. package/dist/esm/features/jserrors/instrument/debug.js +38 -0
  231. package/dist/esm/features/jserrors/instrument/index.js +150 -0
  232. package/dist/esm/features/metrics/aggregate/index.js +129 -0
  233. package/dist/esm/features/metrics/constants.js +6 -0
  234. package/dist/esm/features/metrics/index.js +1 -0
  235. package/dist/esm/features/metrics/instrument/index.js +13 -0
  236. package/dist/esm/features/metrics/instrument/workers-helper.js +116 -0
  237. package/dist/esm/features/page_action/aggregate/index.js +105 -0
  238. package/dist/esm/features/page_action/constants.js +2 -0
  239. package/dist/esm/features/page_action/index.js +1 -0
  240. package/dist/esm/features/page_action/instrument/index.js +14 -0
  241. package/dist/esm/features/page_view_event/aggregate/index.js +124 -0
  242. package/dist/esm/features/page_view_event/aggregate/initialized-features.js +34 -0
  243. package/dist/esm/features/page_view_event/constants.js +5 -0
  244. package/dist/esm/features/page_view_event/index.js +1 -0
  245. package/dist/esm/features/page_view_event/instrument/index.js +29 -0
  246. package/dist/esm/features/page_view_timing/aggregate/index.js +258 -0
  247. package/dist/esm/features/page_view_timing/constants.js +2 -0
  248. package/dist/esm/features/page_view_timing/first-paint.js +43 -0
  249. package/dist/esm/features/page_view_timing/index.js +1 -0
  250. package/dist/esm/features/page_view_timing/instrument/index.js +28 -0
  251. package/dist/esm/features/page_view_timing/long-tasks.js +69 -0
  252. package/dist/esm/features/session_trace/aggregate/index.js +366 -0
  253. package/dist/esm/features/session_trace/constants.js +14 -0
  254. package/dist/esm/features/session_trace/index.js +1 -0
  255. package/dist/esm/features/session_trace/instrument/index.js +123 -0
  256. package/dist/esm/features/spa/aggregate/index.js +674 -0
  257. package/dist/esm/features/spa/aggregate/interaction-node.js +78 -0
  258. package/dist/esm/features/spa/aggregate/interaction-node.test.js +14 -0
  259. package/dist/esm/features/spa/aggregate/interaction.js +92 -0
  260. package/dist/esm/features/spa/aggregate/serializer.js +139 -0
  261. package/dist/esm/features/spa/constants.js +25 -0
  262. package/dist/esm/features/spa/index.js +1 -0
  263. package/dist/esm/features/spa/instrument/index.js +104 -0
  264. package/dist/esm/features/utils/aggregate-base.js +6 -0
  265. package/dist/esm/features/utils/feature-base.js +51 -0
  266. package/dist/esm/features/utils/handler-cache.js +57 -0
  267. package/dist/esm/features/utils/instrument-base.js +69 -0
  268. package/dist/esm/features/utils/lazy-loader.js +37 -0
  269. package/dist/esm/index.js +15 -0
  270. package/dist/esm/loaders/agent.js +77 -0
  271. package/dist/esm/loaders/api/api.js +104 -0
  272. package/dist/esm/loaders/api/apiAsync.js +88 -0
  273. package/dist/esm/loaders/browser-agent.js +23 -0
  274. package/dist/esm/loaders/configure/configure.js +41 -0
  275. package/dist/esm/loaders/features/enabled-features.js +13 -0
  276. package/dist/esm/loaders/features/featureDependencies.js +25 -0
  277. package/dist/esm/loaders/features/features.js +25 -0
  278. package/dist/esm/loaders/micro-agent.js +86 -0
  279. package/dist/esm/loaders/worker-agent.js +18 -0
  280. package/package.json +204 -71
  281. package/types.ts +221 -0
  282. package/dist/bundled/es5/index.js +0 -2
  283. package/dist/bundled/es5/index.js.map +0 -1
  284. package/dist/bundled/es6/index.js +0 -2
  285. package/dist/bundled/es6/index.js.map +0 -1
  286. package/dist/cjs/index.d.ts +0 -19
  287. package/dist/cjs/index.js.map +0 -1
  288. package/dist/cjs/types.d.ts +0 -94
  289. package/dist/cjs/types.js +0 -28
  290. package/dist/cjs/types.js.map +0 -1
  291. package/dist/cjs/utils/api/api.d.ts +0 -10
  292. package/dist/cjs/utils/api/api.js +0 -40
  293. package/dist/cjs/utils/api/api.js.map +0 -1
  294. package/dist/cjs/utils/config/build-configs.d.ts +0 -6
  295. package/dist/cjs/utils/config/build-configs.js +0 -68
  296. package/dist/cjs/utils/config/build-configs.js.map +0 -1
  297. package/dist/cjs/utils/features/features.d.ts +0 -5
  298. package/dist/cjs/utils/features/features.js +0 -14
  299. package/dist/cjs/utils/features/features.js.map +0 -1
  300. package/dist/cjs/utils/features/initialize.d.ts +0 -5
  301. package/dist/cjs/utils/features/initialize.js +0 -51
  302. package/dist/cjs/utils/features/initialize.js.map +0 -1
  303. package/dist/es/index.d.ts +0 -19
  304. package/dist/es/index.js +0 -55
  305. package/dist/es/index.js.map +0 -1
  306. package/dist/es/types.d.ts +0 -94
  307. package/dist/es/types.js +0 -24
  308. package/dist/es/types.js.map +0 -1
  309. package/dist/es/utils/api/api.d.ts +0 -10
  310. package/dist/es/utils/api/api.js +0 -36
  311. package/dist/es/utils/api/api.js.map +0 -1
  312. package/dist/es/utils/config/build-configs.d.ts +0 -6
  313. package/dist/es/utils/config/build-configs.js +0 -64
  314. package/dist/es/utils/config/build-configs.js.map +0 -1
  315. package/dist/es/utils/features/features.d.ts +0 -5
  316. package/dist/es/utils/features/features.js +0 -10
  317. package/dist/es/utils/features/features.js.map +0 -1
  318. package/dist/es/utils/features/initialize.d.ts +0 -5
  319. package/dist/es/utils/features/initialize.js +0 -24
  320. package/dist/es/utils/features/initialize.js.map +0 -1
  321. package/dist/umd/index.d.ts +0 -19
  322. package/dist/umd/index.js +0 -69
  323. package/dist/umd/index.js.map +0 -1
  324. package/dist/umd/types.d.ts +0 -94
  325. package/dist/umd/types.js +0 -38
  326. package/dist/umd/types.js.map +0 -1
  327. package/dist/umd/utils/api/api.d.ts +0 -10
  328. package/dist/umd/utils/api/api.js +0 -50
  329. package/dist/umd/utils/api/api.js.map +0 -1
  330. package/dist/umd/utils/config/build-configs.d.ts +0 -6
  331. package/dist/umd/utils/config/build-configs.js +0 -78
  332. package/dist/umd/utils/config/build-configs.js.map +0 -1
  333. package/dist/umd/utils/features/features.d.ts +0 -5
  334. package/dist/umd/utils/features/features.js +0 -24
  335. package/dist/umd/utils/features/features.js.map +0 -1
  336. package/dist/umd/utils/features/initialize.d.ts +0 -5
  337. package/dist/umd/utils/features/initialize.js +0 -63
  338. package/dist/umd/utils/features/initialize.js.map +0 -1
  339. package/dist/webpack-analysis.html +0 -38
@@ -0,0 +1,366 @@
1
+ /*
2
+ * Copyright 2020 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { registerHandler } from '../../../common/event-emitter/register-handler';
6
+ import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler';
7
+ import { mapOwn } from '../../../common/util/map-own';
8
+ import { reduce } from '../../../common/util/reduce';
9
+ import { stringify } from '../../../common/util/stringify';
10
+ import { parseUrl } from '../../../common/url/parse-url';
11
+ import { supportsPerformanceObserver } from '../../../common/window/supports-performance-observer';
12
+ import slice from 'lodash._slice';
13
+ import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config';
14
+ import { now } from '../../../common/timing/now';
15
+ import { AggregateBase } from '../../utils/aggregate-base';
16
+ import { FEATURE_NAME } from '../constants';
17
+ import { drain } from '../../../common/drain/drain';
18
+ import { HandlerCache } from '../../utils/handler-cache';
19
+ export class Aggregate extends AggregateBase {
20
+ static featureName = FEATURE_NAME;
21
+ constructor(agentIdentifier, aggregator) {
22
+ super(agentIdentifier, aggregator, FEATURE_NAME);
23
+
24
+ // Very unlikely, but in case the existing XMLHttpRequest.prototype object on the page couldn't be wrapped.
25
+ if (!getRuntime(agentIdentifier).xhrWrappable) return;
26
+ const handlerCache = new HandlerCache();
27
+ this.ptid = '';
28
+ this.ignoredEvents = {
29
+ // we find that certain events make the data too noisy to be useful
30
+ global: {
31
+ mouseup: true,
32
+ mousedown: true
33
+ },
34
+ // certain events are present both in the window and in PVT metrics. PVT metrics are prefered so the window events should be ignored
35
+ window: {
36
+ load: true,
37
+ pagehide: true
38
+ },
39
+ // when ajax instrumentation is disabled, all XMLHttpRequest events will return with origin = xhrOriginMissing and should be ignored
40
+ xhrOriginMissing: {
41
+ ignoreAll: true
42
+ }
43
+ };
44
+ this.toAggregate = {
45
+ typing: [1000, 2000],
46
+ scrolling: [100, 1000],
47
+ mousing: [1000, 2000],
48
+ touching: [1000, 2000]
49
+ };
50
+ this.rename = {
51
+ typing: {
52
+ keydown: true,
53
+ keyup: true,
54
+ keypress: true
55
+ },
56
+ mousing: {
57
+ mousemove: true,
58
+ mouseenter: true,
59
+ mouseleave: true,
60
+ mouseover: true,
61
+ mouseout: true
62
+ },
63
+ scrolling: {
64
+ scroll: true
65
+ },
66
+ touching: {
67
+ touchstart: true,
68
+ touchmove: true,
69
+ touchend: true,
70
+ touchcancel: true,
71
+ touchenter: true,
72
+ touchleave: true
73
+ }
74
+ };
75
+ this.trace = {};
76
+ this.nodeCount = 0;
77
+ this.sentTrace = null;
78
+ this.harvestTimeSeconds = getConfigurationValue(agentIdentifier, 'session_trace.harvestTimeSeconds') || 10;
79
+ this.maxNodesPerHarvest = getConfigurationValue(agentIdentifier, 'session_trace.maxNodesPerHarvest') || 1000;
80
+ this.laststart = 0;
81
+ registerHandler('feat-stn', () => {
82
+ this.storeTiming(window.performance.timing);
83
+ var scheduler = new HarvestScheduler('resources', {
84
+ onFinished: onHarvestFinished.bind(this),
85
+ retryDelay: this.harvestTimeSeconds
86
+ }, this);
87
+ scheduler.harvest.on('resources', prepareHarvest.bind(this));
88
+ scheduler.runHarvest({
89
+ needResponse: true
90
+ }); // sends first stn harvest immediately
91
+
92
+ function onHarvestFinished(result) {
93
+ // start timer only if ptid was returned by server
94
+ if (result.sent && result.responseText && !this.ptid) {
95
+ this.ptid = result.responseText;
96
+ getRuntime(this.agentIdentifier).ptid = this.ptid;
97
+ scheduler.startTimer(this.harvestTimeSeconds);
98
+ }
99
+ if (result.sent && result.retry && this.sentTrace) {
100
+ mapOwn(this.sentTrace, (name, nodes) => {
101
+ this.mergeSTNs(name, nodes);
102
+ });
103
+ this.sentTrace = null;
104
+ }
105
+ }
106
+ function prepareHarvest(options) {
107
+ if (now() > 15 * 60 * 1000) {
108
+ // been collecting for over 15 min, empty trace object and bail
109
+ scheduler.stopTimer();
110
+ this.trace = {};
111
+ return;
112
+ }
113
+
114
+ // only send when there are more than 30 nodes to send
115
+ if (this.ptid && this.nodeCount <= 30) return;
116
+ return this.takeSTNs(options.retry);
117
+ }
118
+ handlerCache.decide(true);
119
+ }, this.featureName, this.ee);
120
+ registerHandler('block-stn', () => {
121
+ handlerCache.decide(false);
122
+ }, this.featureName, this.ee);
123
+
124
+ // register the handlers immediately... but let the handlerCache decide if the data should actually get stored...
125
+ registerHandler('bst', (...args) => handlerCache.settle(() => this.storeEvent(...args)), this.featureName, this.ee);
126
+ registerHandler('bstTimer', (...args) => handlerCache.settle(() => this.storeTimer(...args)), this.featureName, this.ee);
127
+ registerHandler('bstResource', (...args) => handlerCache.settle(() => this.storeResources(...args)), this.featureName, this.ee);
128
+ registerHandler('bstHist', (...args) => handlerCache.settle(() => this.storeHist(...args)), this.featureName, this.ee);
129
+ registerHandler('bstXhrAgg', (...args) => handlerCache.settle(() => this.storeXhrAgg(...args)), this.featureName, this.ee);
130
+ registerHandler('bstApi', (...args) => handlerCache.settle(() => this.storeSTN(...args)), this.featureName, this.ee);
131
+ registerHandler('errorAgg', (...args) => handlerCache.settle(() => this.storeErrorAgg(...args)), this.featureName, this.ee);
132
+ registerHandler('pvtAdded', (...args) => handlerCache.settle(() => this.processPVT(...args)), this.featureName, this.ee);
133
+ drain(this.agentIdentifier, this.featureName);
134
+ }
135
+ processPVT(name, value, attrs) {
136
+ var t = {};
137
+ t[name] = value;
138
+ this.storeTiming(t, true);
139
+ if (this.hasFID(name, attrs)) this.storeEvent({
140
+ type: 'fid',
141
+ target: 'document'
142
+ }, 'document', value, value + attrs.fid);
143
+ }
144
+ storeTiming(_t, ignoreOffset) {
145
+ var key;
146
+ var val;
147
+ var timeOffset;
148
+ var dateNow = Date.now();
149
+
150
+ // loop iterates through prototype also (for FF)
151
+ for (key in _t) {
152
+ val = _t[key];
153
+
154
+ // ignore inherited methods, meaningless 0 values, and bogus timestamps
155
+ // that are in the future (Microsoft Edge seems to sometimes produce these)
156
+ if (!(typeof val === 'number' && val > 0 && val < dateNow)) continue;
157
+ timeOffset = !ignoreOffset ? _t[key] - getRuntime(this.agentIdentifier).offset : _t[key];
158
+ this.storeSTN({
159
+ n: key,
160
+ s: timeOffset,
161
+ e: timeOffset,
162
+ o: 'document',
163
+ t: 'timing'
164
+ });
165
+ }
166
+ }
167
+ storeTimer(target, start, end, type) {
168
+ var category = 'timer';
169
+ if (type === 'requestAnimationFrame') category = type;
170
+ var evt = {
171
+ n: type,
172
+ s: start,
173
+ e: end,
174
+ o: 'window',
175
+ t: category
176
+ };
177
+ this.storeSTN(evt);
178
+ }
179
+ storeEvent(currentEvent, target, start, end) {
180
+ if (this.shouldIgnoreEvent(currentEvent, target)) return false;
181
+ var evt = {
182
+ n: this.evtName(currentEvent.type),
183
+ s: start,
184
+ e: end,
185
+ t: 'event'
186
+ };
187
+ try {
188
+ // webcomponents-lite.js can trigger an exception on currentEvent.target getter because
189
+ // it does not check currentEvent.currentTarget before calling getRootNode() on it
190
+ evt.o = this.evtOrigin(currentEvent.target, target);
191
+ } catch (e) {
192
+ evt.o = this.evtOrigin(null, target);
193
+ }
194
+ this.storeSTN(evt);
195
+ }
196
+ evtName(type) {
197
+ var name = type;
198
+ mapOwn(this.rename, function (key, val) {
199
+ if (type in val) name = key;
200
+ });
201
+ return name;
202
+ }
203
+ evtOrigin(t, target) {
204
+ var origin = 'unknown';
205
+ if (t && t instanceof XMLHttpRequest) {
206
+ var params = this.ee.context(t).params;
207
+ if (!params || !params.status || !params.method || !params.host || !params.pathname) return 'xhrOriginMissing';
208
+ origin = params.status + ' ' + params.method + ': ' + params.host + params.pathname;
209
+ } else if (t && typeof t.tagName === 'string') {
210
+ origin = t.tagName.toLowerCase();
211
+ if (t.id) origin += '#' + t.id;
212
+ if (t.className) origin += '.' + slice(t.classList).join('.');
213
+ }
214
+ if (origin === 'unknown') {
215
+ if (typeof target === 'string') origin = target;else if (target === document) origin = 'document';else if (target === window) origin = 'window';else if (target instanceof FileReader) origin = 'FileReader';
216
+ }
217
+ return origin;
218
+ }
219
+ storeHist(path, old, time) {
220
+ var node = {
221
+ n: 'history.pushState',
222
+ s: time,
223
+ e: time,
224
+ o: path,
225
+ t: old
226
+ };
227
+ this.storeSTN(node);
228
+ }
229
+ storeResources(resources) {
230
+ if (!resources || resources.length === 0) return;
231
+ resources.forEach(currentResource => {
232
+ var parsed = parseUrl(currentResource.name);
233
+ var res = {
234
+ n: currentResource.initiatorType,
235
+ s: currentResource.fetchStart | 0,
236
+ e: currentResource.responseEnd | 0,
237
+ o: parsed.protocol + '://' + parsed.hostname + ':' + parsed.port + parsed.pathname,
238
+ // resource.name is actually a URL so it's the source
239
+ t: currentResource.entryType
240
+ };
241
+
242
+ // don't recollect old resources
243
+ if (res.s <= this.laststart) return;
244
+ this.storeSTN(res);
245
+ });
246
+ this.laststart = resources[resources.length - 1].fetchStart | 0;
247
+ }
248
+ storeErrorAgg(type, name, params, metrics) {
249
+ if (type !== 'err') return;
250
+ var node = {
251
+ n: 'error',
252
+ s: metrics.time,
253
+ e: metrics.time,
254
+ o: params.message,
255
+ t: params.stackHash
256
+ };
257
+ this.storeSTN(node);
258
+ }
259
+ storeXhrAgg(type, name, params, metrics) {
260
+ if (type !== 'xhr') return;
261
+ var node = {
262
+ n: 'Ajax',
263
+ s: metrics.time,
264
+ e: metrics.time + metrics.duration,
265
+ o: params.status + ' ' + params.method + ': ' + params.host + params.pathname,
266
+ t: 'ajax'
267
+ };
268
+ this.storeSTN(node);
269
+ }
270
+ storeSTN(stn) {
271
+ // limit the number of data that is stored
272
+ if (this.nodeCount >= this.maxNodesPerHarvest) return;
273
+ var traceArr = this.trace[stn.n];
274
+ if (!traceArr) traceArr = this.trace[stn.n] = [];
275
+ traceArr.push(stn);
276
+ this.nodeCount++;
277
+ }
278
+ mergeSTNs(key, nodes) {
279
+ // limit the number of data that is stored
280
+ if (this.nodeCount >= this.maxNodesPerHarvest) return;
281
+ var traceArr = this.trace[key];
282
+ if (!traceArr) traceArr = this.trace[key] = [];
283
+ this.trace[key] = nodes.concat(traceArr);
284
+ this.nodeCount += nodes.length;
285
+ }
286
+ takeSTNs(retry) {
287
+ // if the observer is not being used, this checks resourcetiming buffer every harvest
288
+ if (!supportsPerformanceObserver()) {
289
+ this.storeResources(window.performance.getEntriesByType('resource'));
290
+ }
291
+ var stns = reduce(mapOwn(this.trace, (name, nodes) => {
292
+ if (!(name in this.toAggregate)) return nodes;
293
+ return reduce(mapOwn(reduce(nodes.sort(this.byStart), this.smearEvtsByOrigin(name), {}), this.val), this.flatten, []);
294
+ }), this.flatten, []);
295
+ if (stns.length === 0) return {};
296
+ if (retry) {
297
+ this.sentTrace = this.trace;
298
+ }
299
+ this.trace = {};
300
+ this.nodeCount = 0;
301
+ var stnInfo = {
302
+ qs: {
303
+ st: '' + getRuntime(this.agentIdentifier).offset
304
+ },
305
+ body: {
306
+ res: stns
307
+ }
308
+ };
309
+ if (!this.ptid) {
310
+ const {
311
+ userAttributes,
312
+ atts,
313
+ jsAttributes
314
+ } = getInfo(this.agentIdentifier);
315
+ stnInfo.qs.ua = userAttributes;
316
+ stnInfo.qs.at = atts;
317
+ var ja = stringify(jsAttributes);
318
+ stnInfo.qs.ja = ja === '{}' ? null : ja;
319
+ }
320
+ return stnInfo;
321
+ }
322
+ byStart(a, b) {
323
+ return a.s - b.s;
324
+ }
325
+ smearEvtsByOrigin(name) {
326
+ var maxGap = this.toAggregate[name][0];
327
+ var maxLen = this.toAggregate[name][1];
328
+ var lastO = {};
329
+ return (byOrigin, evt) => {
330
+ var lastArr = byOrigin[evt.o];
331
+ lastArr || (lastArr = byOrigin[evt.o] = []);
332
+ var last = lastO[evt.o];
333
+ if (name === 'scrolling' && !this.trivial(evt)) {
334
+ lastO[evt.o] = null;
335
+ evt.n = 'scroll';
336
+ lastArr.push(evt);
337
+ } else if (last && evt.s - last.s < maxLen && last.e > evt.s - maxGap) {
338
+ last.e = evt.e;
339
+ } else {
340
+ lastO[evt.o] = evt;
341
+ lastArr.push(evt);
342
+ }
343
+ return byOrigin;
344
+ };
345
+ }
346
+ val(key, value) {
347
+ return value;
348
+ }
349
+ flatten(a, b) {
350
+ return a.concat(b);
351
+ }
352
+ hasFID(name, attrs) {
353
+ return name === 'fi' && !!attrs && typeof attrs.fid === 'number';
354
+ }
355
+ trivial(node) {
356
+ var limit = 4;
357
+ if (node && typeof node.e === 'number' && typeof node.s === 'number' && node.e - node.s < limit) return true;else return false;
358
+ }
359
+ shouldIgnoreEvent(event, target) {
360
+ var origin = this.evtOrigin(event.target, target);
361
+ if (event.type in this.ignoredEvents.global) return true;
362
+ if (!!this.ignoredEvents[origin] && this.ignoredEvents[origin].ignoreAll) return true;
363
+ if (!!this.ignoredEvents[origin] && event.type in this.ignoredEvents[origin]) return true;
364
+ return false;
365
+ }
366
+ }
@@ -0,0 +1,14 @@
1
+ import { originals } from '../../common/config/config';
2
+ import { FEATURE_NAMES } from '../../loaders/features/features';
3
+ export const FEATURE_NAME = FEATURE_NAMES.sessionTrace;
4
+ export const RESOURCE_TIMING_BUFFER_FULL = 'resourcetimingbufferfull';
5
+ export const BST_RESOURCE = 'bstResource';
6
+ export const RESOURCE = 'resource';
7
+ export const START = '-start';
8
+ export const END = '-end';
9
+ export const FN_START = 'fn' + START;
10
+ export const FN_END = 'fn' + END;
11
+ export const BST_TIMER = 'bstTimer';
12
+ export const PUSH_STATE = 'pushState';
13
+ export const ORIG_EVENT = originals.EV;
14
+ export const ADD_EVENT_LISTENER = 'addEventListener';
@@ -0,0 +1 @@
1
+ export { Instrument as SessionTrace } from './instrument/index';
@@ -0,0 +1,123 @@
1
+ /*
2
+ * Copyright 2020 New Relic Corporation. All rights reserved.
3
+ * SPDX-License-Identifier: Apache-2.0
4
+ */
5
+ import { handle } from '../../../common/event-emitter/handle';
6
+ import { wrapHistory, wrapEvents, wrapTimer, wrapRaf } from '../../../common/wrap';
7
+ import { supportsPerformanceObserver } from '../../../common/window/supports-performance-observer';
8
+ import { eventListenerOpts } from '../../../common/event-listener/event-listener-opts';
9
+ import { now } from '../../../common/timing/now';
10
+ import { InstrumentBase } from '../../utils/instrument-base';
11
+ import * as CONSTANTS from '../constants';
12
+ import { FEATURE_NAMES } from '../../../loaders/features/features';
13
+ import { isBrowserScope } from '../../../common/util/global-scope';
14
+ const {
15
+ BST_RESOURCE,
16
+ BST_TIMER,
17
+ END,
18
+ FEATURE_NAME,
19
+ FN_END,
20
+ FN_START,
21
+ ADD_EVENT_LISTENER,
22
+ PUSH_STATE,
23
+ RESOURCE,
24
+ RESOURCE_TIMING_BUFFER_FULL,
25
+ START,
26
+ ORIG_EVENT: origEvent
27
+ } = CONSTANTS;
28
+ const CRT = 'clearResourceTimings';
29
+ export class Instrument extends InstrumentBase {
30
+ static featureName = FEATURE_NAME;
31
+ constructor(agentIdentifier, aggregator, auto = true) {
32
+ super(agentIdentifier, aggregator, FEATURE_NAME, auto);
33
+ if (!isBrowserScope) return; // session traces not supported outside web env
34
+
35
+ const thisInstrumentEE = this.ee;
36
+ this.timerEE = wrapTimer(thisInstrumentEE);
37
+ this.rafEE = wrapRaf(thisInstrumentEE);
38
+ wrapHistory(thisInstrumentEE);
39
+ wrapEvents(thisInstrumentEE);
40
+ thisInstrumentEE.on(FN_START, function (args, target) {
41
+ var evt = args[0];
42
+ if (evt instanceof origEvent) {
43
+ this.bstStart = now();
44
+ }
45
+ });
46
+ thisInstrumentEE.on(FN_END, function (args, target) {
47
+ var evt = args[0];
48
+ if (evt instanceof origEvent) {
49
+ // ISSUE: when target is XMLHttpRequest, nr@context should have params so we can calculate event origin
50
+ // When ajax is disabled, this may fail without making ajax a dependency of session_trace
51
+ handle('bst', [evt, target, this.bstStart, now()], undefined, FEATURE_NAMES.sessionTrace, thisInstrumentEE);
52
+ }
53
+ });
54
+ this.timerEE.on(FN_START, function (args, obj, type) {
55
+ this.bstStart = now();
56
+ this.bstType = type;
57
+ });
58
+ this.timerEE.on(FN_END, function (args, target) {
59
+ handle(BST_TIMER, [target, this.bstStart, now(), this.bstType], undefined, FEATURE_NAMES.sessionTrace, thisInstrumentEE);
60
+ });
61
+ this.rafEE.on(FN_START, function () {
62
+ this.bstStart = now();
63
+ });
64
+ this.rafEE.on(FN_END, function (args, target) {
65
+ handle(BST_TIMER, [target, this.bstStart, now(), 'requestAnimationFrame'], undefined, FEATURE_NAMES.sessionTrace, thisInstrumentEE);
66
+ });
67
+ thisInstrumentEE.on(PUSH_STATE + START, function (args) {
68
+ this.time = now();
69
+ this.startPath = location.pathname + location.hash;
70
+ });
71
+ thisInstrumentEE.on(PUSH_STATE + END, function (args) {
72
+ handle('bstHist', [location.pathname + location.hash, this.startPath, this.time], undefined, FEATURE_NAMES.sessionTrace, thisInstrumentEE);
73
+ });
74
+ if (supportsPerformanceObserver()) {
75
+ // capture initial resources, in case our observer missed anything
76
+ handle(BST_RESOURCE, [window.performance.getEntriesByType('resource')], undefined, FEATURE_NAMES.sessionTrace, thisInstrumentEE);
77
+ observeResourceTimings();
78
+ } else {
79
+ // collect resource timings once when buffer is full
80
+ if (window.performance[CRT] && window.performance[ADD_EVENT_LISTENER]) {
81
+ window.performance.addEventListener(RESOURCE_TIMING_BUFFER_FULL, this.onResourceTimingBufferFull, eventListenerOpts(false));
82
+ }
83
+ }
84
+ function observeResourceTimings() {
85
+ var observer = new PerformanceObserver((list, observer) => {
86
+ // eslint-disable-line no-undef
87
+ var entries = list.getEntries();
88
+ handle(BST_RESOURCE, [entries], undefined, FEATURE_NAMES.sessionTrace, thisInstrumentEE);
89
+ });
90
+ try {
91
+ observer.observe({
92
+ entryTypes: ['resource']
93
+ });
94
+ } catch (e) {
95
+ // do nothing
96
+ }
97
+ }
98
+ document.addEventListener('scroll', this.noOp, eventListenerOpts(false));
99
+ document.addEventListener('keypress', this.noOp, eventListenerOpts(false));
100
+ document.addEventListener('click', this.noOp, eventListenerOpts(false));
101
+ this.abortHandler = this.#abort;
102
+ this.importAggregator();
103
+ }
104
+
105
+ /** Restoration and resource release tasks to be done if Session trace loader is being aborted. Unwind changes to globals. */
106
+ #abort() {
107
+ window.performance.removeEventListener(RESOURCE_TIMING_BUFFER_FULL, this.onResourceTimingBufferFull, false);
108
+ // The doc interaction noOp listeners are harmless--cannot buffer data into EE.
109
+ this.abortHandler = undefined; // weakly allow this abort op to run only once
110
+ }
111
+
112
+ noOp(e) {/* no-op */}
113
+ onResourceTimingBufferFull(evt) {
114
+ handle(BST_RESOURCE, [window.performance.getEntriesByType(RESOURCE)], undefined, FEATURE_NAMES.sessionTrace, this.ee);
115
+
116
+ // stop recording once buffer is full
117
+ if (window.performance[CRT]) {
118
+ try {
119
+ window.performance.removeEventListener(RESOURCE_TIMING_BUFFER_FULL, this.onResourceTimingBufferFull, false);
120
+ } catch (e) {}
121
+ }
122
+ }
123
+ }