@newrelic/browser-agent 0.1.230 → 1.232.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 (365) hide show
  1. package/README.md +27 -3
  2. package/dist/cjs/common/browser-version/ios-version.js +4 -3
  3. package/dist/cjs/common/config/state/configurable.js +27 -21
  4. package/dist/cjs/common/config/state/info.js +1 -1
  5. package/dist/cjs/common/config/state/init.js +9 -1
  6. package/dist/cjs/common/config/state/loader-config.js +1 -1
  7. package/dist/cjs/common/config/state/runtime.js +26 -28
  8. package/dist/cjs/common/constants/env.cdn.js +29 -0
  9. package/dist/cjs/common/constants/env.js +32 -0
  10. package/dist/cjs/common/constants/env.npm.js +30 -0
  11. package/dist/cjs/common/context/shared-context.js +2 -1
  12. package/dist/cjs/common/event-emitter/contextual-ee.test.js +282 -0
  13. package/dist/cjs/common/event-emitter/handle.test.js +58 -0
  14. package/dist/cjs/common/event-emitter/register-handler.test.js +55 -0
  15. package/dist/cjs/common/event-listener/event-listener-opts.js +4 -2
  16. package/dist/cjs/common/harvest/harvest-scheduler.js +14 -11
  17. package/dist/cjs/common/harvest/harvest.js +5 -3
  18. package/dist/cjs/common/ids/id.js +14 -6
  19. package/dist/cjs/common/ids/id.test.js +85 -0
  20. package/dist/cjs/common/ids/unique-id.js +75 -51
  21. package/dist/cjs/common/ids/unique-id.test.js +49 -0
  22. package/dist/cjs/common/session/constants.js +12 -0
  23. package/dist/cjs/common/session/session-entity.js +278 -0
  24. package/dist/cjs/common/session/session-entity.test.js +436 -0
  25. package/dist/cjs/common/storage/first-party-cookies.js +35 -0
  26. package/dist/cjs/common/storage/local-memory.js +35 -0
  27. package/dist/cjs/common/storage/local-memory.test.js +20 -0
  28. package/dist/cjs/common/storage/local-storage.js +33 -0
  29. package/dist/cjs/common/storage/local-storage.test.js +14 -0
  30. package/dist/cjs/common/timer/interaction-timer.js +78 -0
  31. package/dist/cjs/common/timer/interaction-timer.test.js +216 -0
  32. package/dist/cjs/common/timer/timer.js +32 -0
  33. package/dist/cjs/common/timer/timer.test.js +105 -0
  34. package/dist/cjs/common/timing/nav-timing.js +51 -30
  35. package/dist/cjs/common/timing/nav-timing.test.js +192 -0
  36. package/dist/cjs/common/unload/eol.js +2 -2
  37. package/dist/cjs/common/url/clean-url.test.js +9 -0
  38. package/dist/cjs/common/url/encode.test.js +74 -0
  39. package/dist/cjs/common/url/location.js +4 -0
  40. package/dist/cjs/common/url/location.test.js +13 -0
  41. package/dist/cjs/common/url/parse-url.test.js +111 -0
  42. package/dist/cjs/common/url/protocol.js +2 -12
  43. package/dist/cjs/common/url/protocol.test.js +16 -0
  44. package/dist/cjs/common/util/console.js +1 -1
  45. package/dist/cjs/common/util/data-size.js +6 -0
  46. package/dist/cjs/common/util/data-size.test.js +47 -0
  47. package/dist/cjs/common/util/invoke.js +73 -0
  48. package/dist/cjs/common/util/invoke.test.js +49 -0
  49. package/dist/cjs/common/util/map-own.test.js +3 -3
  50. package/dist/cjs/common/util/obfuscate.js +1 -5
  51. package/dist/cjs/common/window/page-visibility.js +5 -2
  52. package/dist/cjs/common/wrap/index.js +0 -7
  53. package/dist/cjs/common/wrap/wrap-events.js +6 -9
  54. package/dist/cjs/common/wrap/wrap-fetch.js +6 -6
  55. package/dist/cjs/common/wrap/wrap-history.js +7 -6
  56. package/dist/cjs/common/wrap/wrap-jsonp.js +7 -6
  57. package/dist/cjs/common/wrap/wrap-mutation.js +7 -6
  58. package/dist/cjs/common/wrap/wrap-promise.js +7 -6
  59. package/dist/cjs/common/wrap/wrap-promise.test.js +119 -0
  60. package/dist/cjs/common/wrap/wrap-raf.js +6 -6
  61. package/dist/cjs/common/wrap/wrap-timer.js +7 -7
  62. package/dist/cjs/common/wrap/wrap-xhr.js +5 -6
  63. package/dist/cjs/features/ajax/aggregate/index.js +3 -3
  64. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +5 -5
  65. package/dist/cjs/features/jserrors/aggregate/format-stack-trace.test.js +1 -1
  66. package/dist/cjs/features/jserrors/aggregate/index.js +6 -6
  67. package/dist/cjs/features/jserrors/instrument/index.js +2 -2
  68. package/dist/cjs/features/metrics/aggregate/index.js +19 -9
  69. package/dist/cjs/features/metrics/instrument/index.js +0 -25
  70. package/dist/cjs/features/metrics/instrument/workers-helper.js +5 -5
  71. package/dist/cjs/features/page_action/aggregate/index.js +3 -3
  72. package/dist/cjs/features/page_view_event/aggregate/index.js +23 -9
  73. package/dist/cjs/features/page_view_timing/aggregate/index.js +40 -30
  74. package/dist/cjs/features/session_trace/aggregate/index.js +18 -15
  75. package/dist/cjs/features/spa/aggregate/index.js +6 -5
  76. package/dist/cjs/features/utils/agent-session.js +73 -0
  77. package/dist/cjs/features/utils/feature-base.js +1 -1
  78. package/dist/cjs/features/utils/instrument-base.js +12 -3
  79. package/dist/cjs/features/utils/lazy-loader.js +2 -2
  80. package/dist/cjs/loaders/agent.js +2 -2
  81. package/dist/cjs/loaders/api/api.js +9 -9
  82. package/dist/cjs/loaders/api/apiAsync.js +3 -2
  83. package/dist/cjs/loaders/configure/configure.js +0 -6
  84. package/dist/cjs/loaders/features/enabled-features.js +1 -1
  85. package/dist/cjs/loaders/micro-agent.js +2 -1
  86. package/dist/esm/common/browser-version/ios-version.js +4 -3
  87. package/dist/esm/common/config/state/configurable.js +26 -20
  88. package/dist/esm/common/config/state/info.js +1 -1
  89. package/dist/esm/common/config/state/init.js +9 -1
  90. package/dist/esm/common/config/state/loader-config.js +1 -1
  91. package/dist/esm/common/config/state/runtime.js +26 -28
  92. package/dist/esm/common/constants/env.cdn.js +20 -0
  93. package/dist/esm/common/constants/env.js +23 -0
  94. package/dist/esm/common/constants/env.npm.js +21 -0
  95. package/dist/esm/common/context/shared-context.js +2 -1
  96. package/dist/esm/common/event-emitter/contextual-ee.test.js +278 -0
  97. package/dist/esm/common/event-emitter/handle.test.js +54 -0
  98. package/dist/esm/common/event-emitter/register-handler.test.js +51 -0
  99. package/dist/esm/common/event-listener/event-listener-opts.js +4 -2
  100. package/dist/esm/common/harvest/harvest-scheduler.js +14 -11
  101. package/dist/esm/common/harvest/harvest.js +4 -2
  102. package/dist/esm/common/ids/id.js +16 -6
  103. package/dist/esm/common/ids/id.test.js +81 -0
  104. package/dist/esm/common/ids/unique-id.js +75 -51
  105. package/dist/esm/common/ids/unique-id.test.js +44 -0
  106. package/dist/esm/common/session/constants.js +3 -0
  107. package/dist/esm/common/session/session-entity.js +271 -0
  108. package/dist/esm/common/session/session-entity.test.js +434 -0
  109. package/dist/esm/common/storage/first-party-cookies.js +28 -0
  110. package/dist/esm/common/storage/local-memory.js +28 -0
  111. package/dist/esm/common/storage/local-memory.test.js +18 -0
  112. package/dist/esm/common/storage/local-storage.js +26 -0
  113. package/dist/esm/common/storage/local-storage.test.js +12 -0
  114. package/dist/esm/common/timer/interaction-timer.js +71 -0
  115. package/dist/esm/common/timer/interaction-timer.test.js +214 -0
  116. package/dist/esm/common/timer/timer.js +25 -0
  117. package/dist/esm/common/timer/timer.test.js +103 -0
  118. package/dist/esm/common/timing/nav-timing.js +51 -29
  119. package/dist/esm/common/timing/nav-timing.test.js +190 -0
  120. package/dist/esm/common/unload/eol.js +1 -1
  121. package/dist/esm/common/url/clean-url.test.js +7 -0
  122. package/dist/esm/common/url/encode.test.js +70 -0
  123. package/dist/esm/common/url/location.js +4 -0
  124. package/dist/esm/common/url/location.test.js +11 -0
  125. package/dist/esm/common/url/parse-url.test.js +107 -0
  126. package/dist/esm/common/url/protocol.js +3 -12
  127. package/dist/esm/common/url/protocol.test.js +14 -0
  128. package/dist/esm/common/util/console.js +1 -1
  129. package/dist/esm/common/util/data-size.js +7 -0
  130. package/dist/esm/common/util/data-size.test.js +45 -0
  131. package/dist/esm/common/util/invoke.js +66 -0
  132. package/dist/esm/common/util/invoke.test.js +47 -0
  133. package/dist/esm/common/util/map-own.test.js +3 -3
  134. package/dist/esm/common/util/obfuscate.js +2 -6
  135. package/dist/esm/common/window/page-visibility.js +5 -2
  136. package/dist/esm/common/wrap/index.js +1 -2
  137. package/dist/esm/common/wrap/wrap-events.js +6 -9
  138. package/dist/esm/common/wrap/wrap-fetch.js +6 -6
  139. package/dist/esm/common/wrap/wrap-history.js +7 -6
  140. package/dist/esm/common/wrap/wrap-jsonp.js +7 -6
  141. package/dist/esm/common/wrap/wrap-mutation.js +7 -6
  142. package/dist/esm/common/wrap/wrap-promise.js +7 -6
  143. package/dist/esm/common/wrap/wrap-promise.test.js +115 -0
  144. package/dist/esm/common/wrap/wrap-raf.js +6 -6
  145. package/dist/esm/common/wrap/wrap-timer.js +7 -7
  146. package/dist/esm/common/wrap/wrap-xhr.js +5 -6
  147. package/dist/esm/features/ajax/aggregate/index.js +3 -3
  148. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +5 -5
  149. package/dist/esm/features/jserrors/aggregate/format-stack-trace.test.js +1 -1
  150. package/dist/esm/features/jserrors/aggregate/index.js +6 -6
  151. package/dist/esm/features/jserrors/instrument/index.js +2 -2
  152. package/dist/esm/features/metrics/aggregate/index.js +21 -11
  153. package/dist/esm/features/metrics/instrument/index.js +0 -25
  154. package/dist/esm/features/metrics/instrument/workers-helper.js +5 -5
  155. package/dist/esm/features/page_action/aggregate/index.js +3 -3
  156. package/dist/esm/features/page_view_event/aggregate/index.js +23 -9
  157. package/dist/esm/features/page_view_timing/aggregate/index.js +40 -30
  158. package/dist/esm/features/session_trace/aggregate/index.js +18 -15
  159. package/dist/esm/features/spa/aggregate/index.js +6 -5
  160. package/dist/esm/features/utils/agent-session.js +67 -0
  161. package/dist/esm/features/utils/feature-base.js +1 -1
  162. package/dist/esm/features/utils/instrument-base.js +7 -2
  163. package/dist/esm/features/utils/lazy-loader.js +2 -2
  164. package/dist/esm/loaders/agent.js +2 -2
  165. package/dist/esm/loaders/api/api.js +6 -9
  166. package/dist/esm/loaders/api/apiAsync.js +2 -1
  167. package/dist/esm/loaders/configure/configure.js +2 -8
  168. package/dist/esm/loaders/features/enabled-features.js +1 -1
  169. package/dist/types/common/config/state/configurable.d.ts.map +1 -1
  170. package/dist/types/common/config/state/init.d.ts.map +1 -1
  171. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  172. package/dist/types/common/constants/env.cdn.d.ts +18 -0
  173. package/dist/types/common/constants/env.cdn.d.ts.map +1 -0
  174. package/dist/types/common/constants/env.d.ts +13 -0
  175. package/dist/types/common/constants/env.d.ts.map +1 -0
  176. package/dist/types/common/constants/env.npm.d.ts +19 -0
  177. package/dist/types/common/constants/env.npm.d.ts.map +1 -0
  178. package/dist/types/common/context/shared-context.d.ts.map +1 -1
  179. package/dist/types/common/event-listener/event-listener-opts.d.ts +2 -2
  180. package/dist/types/common/event-listener/event-listener-opts.d.ts.map +1 -1
  181. package/dist/types/common/harvest/harvest-scheduler.d.ts +1 -0
  182. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  183. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  184. package/dist/types/common/ids/id.d.ts +11 -1
  185. package/dist/types/common/ids/id.d.ts.map +1 -1
  186. package/dist/types/common/ids/unique-id.d.ts +24 -1
  187. package/dist/types/common/ids/unique-id.d.ts.map +1 -1
  188. package/dist/types/common/session/constants.d.ts +4 -0
  189. package/dist/types/common/session/constants.d.ts.map +1 -0
  190. package/dist/types/common/session/session-entity.d.ts +72 -0
  191. package/dist/types/common/session/session-entity.d.ts.map +1 -0
  192. package/dist/types/common/storage/first-party-cookies.d.ts +8 -0
  193. package/dist/types/common/storage/first-party-cookies.d.ts.map +1 -0
  194. package/dist/types/common/storage/local-memory.d.ts +8 -0
  195. package/dist/types/common/storage/local-memory.d.ts.map +1 -0
  196. package/dist/types/common/storage/local-storage.d.ts +6 -0
  197. package/dist/types/common/storage/local-storage.d.ts.map +1 -0
  198. package/dist/types/common/timer/interaction-timer.d.ts +11 -0
  199. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -0
  200. package/dist/types/common/timer/timer.d.ts +12 -0
  201. package/dist/types/common/timer/timer.d.ts.map +1 -0
  202. package/dist/types/common/timing/nav-timing.d.ts +1 -2
  203. package/dist/types/common/timing/nav-timing.d.ts.map +1 -1
  204. package/dist/types/common/unload/eol.d.ts.map +1 -1
  205. package/dist/types/common/url/location.d.ts +4 -0
  206. package/dist/types/common/url/location.d.ts.map +1 -1
  207. package/dist/types/common/url/parse-url.d.ts.map +1 -1
  208. package/dist/types/common/url/protocol.d.ts +1 -6
  209. package/dist/types/common/url/protocol.d.ts.map +1 -1
  210. package/dist/types/common/util/data-size.d.ts +7 -1
  211. package/dist/types/common/util/data-size.d.ts.map +1 -1
  212. package/dist/types/common/util/global-scope.d.ts.map +1 -1
  213. package/dist/types/common/util/invoke.d.ts +35 -0
  214. package/dist/types/common/util/invoke.d.ts.map +1 -0
  215. package/dist/types/common/util/obfuscate.d.ts.map +1 -1
  216. package/dist/types/common/window/page-visibility.d.ts +1 -1
  217. package/dist/types/common/window/page-visibility.d.ts.map +1 -1
  218. package/dist/types/common/wrap/index.d.ts +1 -2
  219. package/dist/types/common/wrap/index.d.ts.map +1 -1
  220. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  221. package/dist/types/common/wrap/wrap-history.d.ts.map +1 -1
  222. package/dist/types/common/wrap/wrap-jsonp.d.ts.map +1 -1
  223. package/dist/types/common/wrap/wrap-mutation.d.ts.map +1 -1
  224. package/dist/types/common/wrap/wrap-promise.d.ts.map +1 -1
  225. package/dist/types/common/wrap/wrap-raf.d.ts.map +1 -1
  226. package/dist/types/common/wrap/wrap-timer.d.ts.map +1 -1
  227. package/dist/types/common/wrap/wrap-xhr.d.ts.map +1 -1
  228. package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
  229. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  230. package/dist/types/features/jserrors/aggregate/index.d.ts +2 -2
  231. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  232. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  233. package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
  234. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  235. package/dist/types/features/metrics/instrument/index.d.ts +0 -1
  236. package/dist/types/features/metrics/instrument/index.d.ts.map +1 -1
  237. package/dist/types/features/metrics/instrument/workers-helper.d.ts.map +1 -1
  238. package/dist/types/features/page_action/aggregate/index.d.ts +2 -2
  239. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  240. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
  241. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  242. package/dist/types/features/page_view_timing/aggregate/index.d.ts +3 -4
  243. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  244. package/dist/types/features/session_trace/aggregate/index.d.ts +3 -3
  245. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  246. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  247. package/dist/types/features/spa/aggregate/index.d.ts +2 -2
  248. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  249. package/dist/types/features/spa/instrument/index.d.ts.map +1 -1
  250. package/dist/types/features/utils/agent-session.d.ts +2 -0
  251. package/dist/types/features/utils/agent-session.d.ts.map +1 -0
  252. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  253. package/dist/types/features/utils/lazy-loader.d.ts +2 -2
  254. package/dist/types/features/utils/lazy-loader.d.ts.map +1 -1
  255. package/dist/types/loaders/api/api.d.ts.map +1 -1
  256. package/dist/types/loaders/api/apiAsync.d.ts.map +1 -1
  257. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  258. package/package.json +12 -32
  259. package/src/common/browser-version/ios-version.js +4 -3
  260. package/src/common/config/state/configurable.js +26 -19
  261. package/src/common/config/state/init.js +7 -0
  262. package/src/common/config/state/runtime.js +7 -10
  263. package/src/common/constants/env.cdn.js +20 -0
  264. package/src/common/constants/env.js +23 -0
  265. package/src/common/constants/env.npm.js +21 -0
  266. package/src/common/context/shared-context.js +2 -1
  267. package/src/common/event-emitter/contextual-ee.test.js +310 -0
  268. package/src/common/event-emitter/handle.test.js +56 -0
  269. package/src/common/event-emitter/register-handler.test.js +61 -0
  270. package/src/common/event-listener/event-listener-opts.js +4 -4
  271. package/src/common/harvest/harvest-scheduler.js +12 -8
  272. package/src/common/harvest/harvest.js +5 -3
  273. package/src/common/ids/id.js +15 -6
  274. package/src/common/ids/id.test.js +92 -0
  275. package/src/common/ids/unique-id.js +77 -54
  276. package/src/common/ids/unique-id.test.js +58 -0
  277. package/src/common/session/constants.js +3 -0
  278. package/src/common/session/session-entity.js +271 -0
  279. package/src/common/session/session-entity.test.js +317 -0
  280. package/src/common/storage/first-party-cookies.js +31 -0
  281. package/src/common/storage/local-memory.js +30 -0
  282. package/src/common/storage/local-memory.test.js +19 -0
  283. package/src/common/storage/local-storage.js +28 -0
  284. package/src/common/storage/local-storage.test.js +17 -0
  285. package/src/common/timer/interaction-timer.js +75 -0
  286. package/src/common/timer/interaction-timer.test.js +167 -0
  287. package/src/common/timer/timer.js +31 -0
  288. package/src/common/timer/timer.test.js +100 -0
  289. package/src/common/timing/nav-timing.js +50 -30
  290. package/src/common/timing/nav-timing.test.js +161 -0
  291. package/src/common/unload/eol.js +2 -3
  292. package/src/common/url/clean-url.test.js +25 -0
  293. package/src/common/url/encode.test.js +80 -0
  294. package/src/common/url/location.js +4 -0
  295. package/src/common/url/location.test.js +15 -0
  296. package/src/common/url/parse-url.js +1 -2
  297. package/src/common/url/parse-url.test.js +110 -0
  298. package/src/common/url/protocol.js +3 -13
  299. package/src/common/url/protocol.test.js +18 -0
  300. package/src/common/util/data-size.js +6 -0
  301. package/src/common/util/data-size.test.js +50 -0
  302. package/src/common/util/global-scope.js +1 -2
  303. package/src/common/util/invoke.js +55 -0
  304. package/src/common/util/invoke.test.js +65 -0
  305. package/src/common/util/obfuscate.js +2 -6
  306. package/src/common/window/page-visibility.js +3 -3
  307. package/src/common/wrap/index.js +1 -2
  308. package/src/common/wrap/wrap-events.js +5 -5
  309. package/src/common/wrap/wrap-fetch.js +4 -3
  310. package/src/common/wrap/wrap-history.js +6 -3
  311. package/src/common/wrap/wrap-jsonp.js +5 -3
  312. package/src/common/wrap/wrap-mutation.js +6 -3
  313. package/src/common/wrap/wrap-promise.js +7 -6
  314. package/src/common/wrap/wrap-promise.test.js +140 -0
  315. package/src/common/wrap/wrap-raf.js +5 -3
  316. package/src/common/wrap/wrap-timer.js +6 -4
  317. package/src/common/wrap/wrap-xhr.js +4 -3
  318. package/src/features/ajax/aggregate/index.js +2 -2
  319. package/src/features/ajax/instrument/index.js +1 -1
  320. package/src/features/jserrors/aggregate/index.js +3 -3
  321. package/src/features/jserrors/instrument/index.js +4 -2
  322. package/src/features/metrics/aggregate/index.js +21 -7
  323. package/src/features/metrics/instrument/index.js +0 -30
  324. package/src/features/metrics/instrument/workers-helper.js +9 -6
  325. package/src/features/page_action/aggregate/index.js +2 -2
  326. package/src/features/page_view_event/aggregate/index.js +21 -9
  327. package/src/features/page_view_timing/aggregate/index.js +40 -29
  328. package/src/features/page_view_timing/long-tasks.js +10 -10
  329. package/src/features/session_trace/aggregate/index.js +17 -14
  330. package/src/features/session_trace/instrument/index.js +3 -2
  331. package/src/features/spa/aggregate/index.js +5 -5
  332. package/src/features/spa/instrument/index.js +4 -2
  333. package/src/features/utils/agent-session.js +68 -0
  334. package/src/features/utils/feature-base.js +1 -1
  335. package/src/features/utils/instrument-base.js +5 -2
  336. package/src/features/utils/lazy-loader.js +1 -1
  337. package/src/loaders/agent.js +1 -1
  338. package/src/loaders/api/api.js +3 -6
  339. package/src/loaders/api/apiAsync.js +2 -1
  340. package/src/loaders/configure/configure.js +2 -7
  341. package/dist/cjs/common/constants/environment-variables.js +0 -20
  342. package/dist/cjs/common/util/single.js +0 -23
  343. package/dist/cjs/common/window/session-storage.js +0 -87
  344. package/dist/cjs/common/wrap/wrap-console.js +0 -54
  345. package/dist/cjs/features/utils/aggregate-base.js +0 -13
  346. package/dist/esm/common/constants/environment-variables.js +0 -11
  347. package/dist/esm/common/util/single.js +0 -16
  348. package/dist/esm/common/window/session-storage.js +0 -77
  349. package/dist/esm/common/wrap/wrap-console.js +0 -46
  350. package/dist/esm/features/utils/aggregate-base.js +0 -6
  351. package/dist/types/common/constants/environment-variables.d.ts +0 -4
  352. package/dist/types/common/constants/environment-variables.d.ts.map +0 -1
  353. package/dist/types/common/util/single.d.ts +0 -2
  354. package/dist/types/common/util/single.d.ts.map +0 -1
  355. package/dist/types/common/window/session-storage.d.ts +0 -18
  356. package/dist/types/common/window/session-storage.d.ts.map +0 -1
  357. package/dist/types/common/wrap/wrap-console.d.ts +0 -16
  358. package/dist/types/common/wrap/wrap-console.d.ts.map +0 -1
  359. package/dist/types/features/utils/aggregate-base.d.ts +0 -4
  360. package/dist/types/features/utils/aggregate-base.d.ts.map +0 -1
  361. package/src/common/constants/environment-variables.js +0 -11
  362. package/src/common/util/single.js +0 -18
  363. package/src/common/window/session-storage.js +0 -75
  364. package/src/common/wrap/wrap-console.js +0 -47
  365. package/src/features/utils/aggregate-base.js +0 -7
@@ -1,17 +1,19 @@
1
- import { getRuntime } from '../../../common/config/config'
1
+ import { getRuntime, getInfo } from '../../../common/config/config'
2
2
  import { registerHandler } from '../../../common/event-emitter/register-handler'
3
3
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
4
- import { AggregateBase } from '../../utils/aggregate-base'
5
4
  import { FEATURE_NAME, SUPPORTABILITY_METRIC, CUSTOM_METRIC, SUPPORTABILITY_METRIC_CHANNEL, CUSTOM_METRIC_CHANNEL } from '../constants'
6
5
  import { drain } from '../../../common/drain/drain'
7
6
  import { getFrameworks } from '../../../common/metrics/framework-detection'
8
- import { protocol } from '../../../common/url/protocol'
7
+ import { isFileProtocol } from '../../../common/url/protocol'
9
8
  import { getRules, validateRules } from '../../../common/util/obfuscate'
10
- import { VERSION } from '../../../common/constants/environment-variables'
9
+ import { VERSION } from '../../../common/constants/env'
11
10
  import { onDOMContentLoaded } from '../../../common/window/load'
12
11
  import { windowAddEventListener } from '../../../common/event-listener/event-listener-opts'
13
12
  import { isBrowserScope } from '../../../common/util/global-scope'
14
- export class Aggregate extends AggregateBase {
13
+ import { FeatureBase } from '../../utils/feature-base'
14
+ import { stringify } from '../../../common/util/stringify'
15
+
16
+ export class Aggregate extends FeatureBase {
15
17
  static featureName = FEATURE_NAME
16
18
  constructor (agentIdentifier, aggregator) {
17
19
  super(agentIdentifier, aggregator, FEATURE_NAME)
@@ -70,9 +72,8 @@ export class Aggregate extends AggregateBase {
70
72
  }
71
73
 
72
74
  // file protocol detection
73
- if (protocol.isFileProtocol()) {
75
+ if (isFileProtocol()) {
74
76
  this.storeSupportabilityMetrics('Generic/FileProtocol/Detected')
75
- protocol.supportabilityMetricSent = true
76
77
  }
77
78
 
78
79
  // obfuscation rules detection
@@ -97,6 +98,7 @@ export class Aggregate extends AggregateBase {
97
98
  try {
98
99
  if (this.resourcesSent) return
99
100
  const agentRuntime = getRuntime(this.agentIdentifier)
101
+ const info = getInfo(this.agentIdentifier)
100
102
  // make sure this only gets sent once
101
103
  this.resourcesSent = true
102
104
  // differentiate between internal+external and ajax+non-ajax
@@ -123,10 +125,22 @@ export class Aggregate extends AggregateBase {
123
125
  )
124
126
  })
125
127
 
128
+ // Capture per-agent query bytes sent for each endpoint (see harvest) and RUM call (see page_view_event aggregator).
129
+ Object.keys(agentRuntime.bytesSent).forEach(endpoint => {
130
+ this.storeSupportabilityMetrics(
131
+ `PageSession/Endpoint/${endpoint.charAt(0).toUpperCase() + endpoint.slice(1)}/QueryBytesSent`,
132
+ agentRuntime.queryBytesSent[endpoint]
133
+ )
134
+ })
135
+
126
136
  // Capture metrics for session trace if active (`ptid` is set when returned by replay ingest).
127
137
  if (agentRuntime.ptid) {
128
138
  this.storeSupportabilityMetrics('PageSession/Feature/SessionTrace/DurationMs', Math.round(performance.now()))
129
139
  }
140
+
141
+ // Capture metrics for size of custom attributes
142
+ const jsAttributes = stringify(info.jsAttributes)
143
+ this.storeSupportabilityMetrics('PageSession/Feature/CustomData/Bytes', jsAttributes === '{}' ? 0 : jsAttributes.length)
130
144
  } catch (e) {
131
145
  // do nothing
132
146
  }
@@ -3,42 +3,12 @@ import { insertSupportMetrics } from './workers-helper'
3
3
  import { FEATURE_NAME, SUPPORTABILITY_METRIC_CHANNEL } from '../constants'
4
4
  import { handle } from '../../../common/event-emitter/handle'
5
5
  import { FEATURE_NAMES } from '../../../loaders/features/features'
6
- import { wrapConsole } from '../../../common/wrap'
7
- import { stringify } from '../../../common/util/stringify'
8
6
 
9
7
  export class Instrument extends InstrumentBase {
10
8
  static featureName = FEATURE_NAME
11
9
  constructor (agentIdentifier, aggregator, auto = true) {
12
10
  super(agentIdentifier, aggregator, FEATURE_NAME, auto)
13
11
  insertSupportMetrics(tag => handle(SUPPORTABILITY_METRIC_CHANNEL, [tag], undefined, FEATURE_NAMES.metrics, this.ee))
14
-
15
- this.addConsoleSupportabilityMetrics()
16
-
17
12
  this.importAggregator()
18
13
  }
19
-
20
- addConsoleSupportabilityMetrics () {
21
- // For now we are just capturing supportability metrics on `console` usage to assess log forwarding feature.
22
- const consoleEE = wrapConsole(this.ee)
23
-
24
- for (const method of ['Debug', 'Error', 'Info', 'Log', 'Trace', 'Warn']) {
25
- consoleEE.on(`${method.toLowerCase()}-console-start`, function (args, target) {
26
- // Parsing the args individually into a new array ensures that functions and Error objects are represented with
27
- // useful string values. By default, functions stringify to null and Error objects stringify to empty objects.
28
- // Note that stack traces printed by the console.trace method are not captured.
29
- let parsedArgs = []
30
- for (const arg of args) {
31
- if (typeof arg === 'function' ||
32
- (arg && arg.message && arg.stack) // Duck typing for Error objects
33
- ) {
34
- parsedArgs.push(arg.toString())
35
- } else {
36
- parsedArgs.push(arg)
37
- }
38
- }
39
- const parsedArgsJSON = stringify(parsedArgs)
40
- handle(SUPPORTABILITY_METRIC_CHANNEL, [`Console/${method}/Seen`, parsedArgsJSON.length], undefined, FEATURE_NAMES.metrics, consoleEE)
41
- })
42
- }
43
- }
44
14
  }
@@ -37,23 +37,26 @@ export function insertSupportMetrics (report) {
37
37
  return // similarly, if dedicated is n/a, none of them are supported so quit
38
38
  } else {
39
39
  origWorker = Worker
40
- try { globalScope.Worker = extendWorkerConstructor(origWorker, 'Dedicated') }
41
- catch (e) { handleInsertionError(e, 'Dedicated') }
40
+ try {
41
+ globalScope.Worker = extendWorkerConstructor(origWorker, 'Dedicated')
42
+ } catch (e) { handleInsertionError(e, 'Dedicated') }
42
43
  }
43
44
 
44
45
  if (!workersApiIsSupported.shared) {
45
46
  reportUnavailable('Shared')
46
47
  } else {
47
48
  origSharedWorker = SharedWorker
48
- try { globalScope.SharedWorker = extendWorkerConstructor(origSharedWorker, 'Shared') }
49
- catch (e) { handleInsertionError(e, 'Shared') }
49
+ try {
50
+ globalScope.SharedWorker = extendWorkerConstructor(origSharedWorker, 'Shared')
51
+ } catch (e) { handleInsertionError(e, 'Shared') }
50
52
  }
51
53
  if (!workersApiIsSupported.service) {
52
54
  reportUnavailable('Service')
53
55
  } else {
54
56
  origServiceWorkerCreate = navigator.serviceWorker.register
55
- try { globalScope.navigator.serviceWorker.register = extendServiceCreation(origServiceWorkerCreate) }
56
- catch (e) { handleInsertionError(e, 'Service') }
57
+ try {
58
+ globalScope.navigator.serviceWorker.register = extendServiceCreation(origServiceWorkerCreate)
59
+ } catch (e) { handleInsertionError(e, 'Service') }
57
60
  }
58
61
  return
59
62
 
@@ -9,12 +9,12 @@ import { registerHandler as register } from '../../../common/event-emitter/regis
9
9
  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
- import { AggregateBase } from '../../utils/aggregate-base'
13
12
  import { FEATURE_NAME } from '../constants'
14
13
  import { drain } from '../../../common/drain/drain'
15
14
  import { isBrowserScope } from '../../../common/util/global-scope'
15
+ import { FeatureBase } from '../../utils/feature-base'
16
16
 
17
- export class Aggregate extends AggregateBase {
17
+ export class Aggregate extends FeatureBase {
18
18
  static featureName = FEATURE_NAME
19
19
  constructor (agentIdentifier, aggregator) {
20
20
  super(agentIdentifier, aggregator, FEATURE_NAME)
@@ -10,15 +10,15 @@ import { paintMetrics } from '../../../common/metrics/paint-metrics'
10
10
  import { submitData } from '../../../common/util/submit-data'
11
11
  import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config'
12
12
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
13
- import { AggregateBase } from '../../utils/aggregate-base'
14
13
  import * as CONSTANTS from '../constants'
15
14
  import { getActivatedFeaturesFlags } from './initialized-features'
16
15
  import { globalScope, isBrowserScope } from '../../../common/util/global-scope'
17
16
  import { drain } from '../../../common/drain/drain'
17
+ import { FeatureBase } from '../../utils/feature-base'
18
18
 
19
19
  const jsonp = 'NREUM.setToken'
20
20
 
21
- export class Aggregate extends AggregateBase {
21
+ export class Aggregate extends FeatureBase {
22
22
  static featureName = CONSTANTS.FEATURE_NAME
23
23
  constructor (agentIdentifier, aggregator) {
24
24
  super(agentIdentifier, aggregator, CONSTANTS.FEATURE_NAME)
@@ -89,12 +89,21 @@ export class Aggregate extends AggregateBase {
89
89
  chunksForQueryString.push(param('pr', info.product))
90
90
  chunksForQueryString.push(param('af', getActivatedFeaturesFlags(this.agentIdentifier).join(',')))
91
91
 
92
- if (globalScope.performance && typeof (globalScope.performance.timing) !== 'undefined') {
93
- var navTimingApiData = ({
94
- timing: addPT(agentRuntime.offset, globalScope.performance.timing, {}),
95
- navigation: addPN(globalScope.performance.navigation, {})
96
- })
97
- chunksForQueryString.push(param('perf', stringify(navTimingApiData)))
92
+ if (globalScope.performance) {
93
+ if (typeof PerformanceNavigationTiming !== 'undefined') { // Navigation Timing level 2 API that replaced PerformanceTiming & PerformanceNavigation
94
+ const navTimingEntry = globalScope?.performance?.getEntriesByType('navigation')?.[0]
95
+ const perf = ({
96
+ timing: addPT(agentRuntime.offset, navTimingEntry, {}),
97
+ navigation: addPN(navTimingEntry, {})
98
+ })
99
+ chunksForQueryString.push(param('perf', stringify(perf)))
100
+ } else if (typeof PerformanceTiming !== 'undefined') { // Safari pre-15 did not support level 2 timing
101
+ const perf = ({
102
+ timing: addPT(agentRuntime.offset, globalScope.performance.timing, {}, true),
103
+ navigation: addPN(globalScope.performance.navigation, {})
104
+ })
105
+ chunksForQueryString.push(param('perf', stringify(perf)))
106
+ }
98
107
  }
99
108
 
100
109
  try { // PVTiming sends these too, albeit using web-vitals and slightly different; it's unknown why they're duplicated, but PVT should be the truth
@@ -121,7 +130,10 @@ export class Aggregate extends AggregateBase {
121
130
  var queryString = fromArray(chunksForQueryString, agentRuntime.maxBytes)
122
131
 
123
132
  // Capture bytes sent to RUM call endpoint (currently `1`) as a supportability metric. See metrics aggregator (on unload).
124
- agentRuntime.bytesSent[protocol] = (agentRuntime.bytesSent[protocol] || 0) + queryString?.length || 0
133
+ agentRuntime.bytesSent[protocol] = 0 // Set to zero for now until RUM is moved to POST
134
+
135
+ // Capture query bytes sent to RUM call endpoint (currently `1`) as a supportability metric. See metrics aggregator (on unload).
136
+ agentRuntime.queryBytesSent[protocol] = (agentRuntime.queryBytesSent[protocol] || 0) + queryString?.length || 0
125
137
 
126
138
  const isValidJsonp = submitData.jsonp(
127
139
  this.getScheme() + '://' + info.beacon + '/' + protocol + '/' + info.licenseKey + queryString,
@@ -14,12 +14,12 @@ import { registerHandler } from '../../../common/event-emitter/register-handler'
14
14
  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
- import { AggregateBase } from '../../utils/aggregate-base'
18
17
  import { FEATURE_NAME } from '../constants'
19
18
  import { drain } from '../../../common/drain/drain'
20
19
  import { FEATURE_NAMES } from '../../../loaders/features/features'
20
+ import { FeatureBase } from '../../utils/feature-base'
21
21
 
22
- export class Aggregate extends AggregateBase {
22
+ export class Aggregate extends FeatureBase {
23
23
  static featureName = FEATURE_NAME
24
24
  constructor (agentIdentifier, aggregator) {
25
25
  super(agentIdentifier, aggregator, FEATURE_NAME)
@@ -27,13 +27,9 @@ export class Aggregate extends AggregateBase {
27
27
  this.timings = []
28
28
  this.timingsSent = []
29
29
  this.curSessEndRecorded = false
30
+ this.cls = null // this should be null unless set to a numeric value by web-vitals so that we differentiate if CLS is supported
30
31
 
31
- try { // we (only) need to track cls state because it's attached to other timing events rather than reported on change...
32
- this.clsSupported = PerformanceObserver.supportedEntryTypes.includes('layout-shift')
33
- this.cls = 0
34
- } catch (e) {}
35
-
36
- /*! This is the section that used to be in the loader portion: !*/
32
+ /* ! This is the section that used to be in the loader portion: ! */
37
33
  /* ------------------------------------------------------------ */
38
34
  const pageStartedHidden = getRuntime(agentIdentifier).initHidden // our attempt at recapturing initial vis state since this code runs post-load time
39
35
  this.alreadySent = new Set() // since we don't support timings on BFCache restores, this tracks and helps cap metrics that web-vitals report more than once
@@ -66,7 +62,7 @@ export class Aggregate extends AggregateBase {
66
62
 
67
63
  /* First Input Delay (+"First Interaction") - As of WV v3, it still imperfectly tries to detect document vis state asap and isn't supposed to report if page starts hidden. */
68
64
  onFID(({ name, value, entries }) => {
69
- if (pageStartedHidden || this.alreadySent.has(name)) return
65
+ if (pageStartedHidden || this.alreadySent.has(name) || entries.length === 0) return
70
66
  this.alreadySent.add(name)
71
67
 
72
68
  // CWV will only report one (THE) first-input entry to us; fid isn't reported if there are no user interactions occurs before the *first* page hiding.
@@ -84,24 +80,28 @@ export class Aggregate extends AggregateBase {
84
80
  if (pageStartedHidden || this.alreadySent.has(name)) return
85
81
  this.alreadySent.add(name)
86
82
 
87
- // CWV will only ever report one (THE) lcp entry to us; lcp is also only reported *once* on earlier(user interaction, page hidden).
88
- const lcpEntry = entries[entries.length - 1] // this looks weird if we only expect one, but this is how cwv-attribution gets it so to be sure...
89
- const attrs = {
90
- size: lcpEntry.size,
91
- eid: lcpEntry.id
92
- }
93
- this.addConnectionAttributes(attrs)
94
- if (lcpEntry.url) {
95
- attrs['elUrl'] = cleanURL(lcpEntry.url)
96
- }
97
- if (lcpEntry.element && lcpEntry.element.tagName) {
98
- attrs['elTag'] = lcpEntry.element.tagName
83
+ const attributes = {}
84
+ if (entries.length > 0) {
85
+ // CWV will only ever report one (THE) lcp entry to us; lcp is also only reported *once* on earlier(user interaction, page hidden).
86
+ const lcpEntry = entries[entries.length - 1] // this looks weird if we only expect one, but this is how cwv-attribution gets it so to be sure...
87
+ attributes.size = lcpEntry.size
88
+ attributes.eid = lcpEntry.id
89
+
90
+ if (lcpEntry.url) {
91
+ attributes.elUrl = cleanURL(lcpEntry.url)
92
+ }
93
+ if (lcpEntry.element?.tagName) {
94
+ attributes.elTag = lcpEntry.element.tagName
95
+ }
99
96
  }
100
- this.addTiming(name.toLowerCase(), value, attrs)
97
+
98
+ this.addConnectionAttributes(attributes)
99
+ this.addTiming(name.toLowerCase(), value, attributes)
101
100
  })
102
101
 
103
- /* Cumulative Layout Shift - We don't have to limit this callback since cls is stored as a state and only sent as attribute on other timings. */
104
- onCLS(({ value }) => this.cls = value)
102
+ /* Cumulative Layout Shift - We don't have to limit this callback since cls is stored as a state and only sent as attribute on other timings.
103
+ reportAllChanges ensures our tracked cls has the most recent rolling value to attach to 'unload' and 'pagehide'. */
104
+ onCLS(({ value }) => this.cls = value, { reportAllChanges: true })
105
105
 
106
106
  /* Interaction-to-Next-Paint */
107
107
  onINP(({ name, value, id }) => this.addTiming(name.toLowerCase(), value, { metricId: id }))
@@ -160,17 +160,28 @@ export class Aggregate extends AggregateBase {
160
160
  */
161
161
  recordPageUnload (timestamp) {
162
162
  this.addTiming('unload', timestamp, null)
163
- // Because window's pageHide commonly fires before vis change and the final harvest occurs on the earlier of the two, we also have to add that now or it won't make it into the last payload out.
163
+ /*
164
+ Issue: Because window's pageHide commonly fires BEFORE vis change and "final" harvest would happen at the former in this case, we also have to add our vis-change event now or it may not be sent.
165
+ Affected: Safari < v14.1/.5 ; versions that don't support 'visiilitychange' event
166
+ Impact: For affected w/o this, NR 'pageHide' attribute may not be sent. For other browsers w/o this, NR 'pageHide' gets fragmented into its own harvest call on page unloading because of dual EoL logic.
167
+ Mitigation: NR 'unload' and 'pageHide' are both recorded when window pageHide fires, rather than only recording 'unload'.
168
+ Future: When EoL can become the singular subscribeToVisibilityChange, it's likely endCurrentSession isn't needed here as 'unload'-'pageHide' can be untangled.
169
+ */
164
170
  this.endCurrentSession(timestamp)
165
171
  }
166
172
 
167
173
  addTiming (name, value, attrs) {
168
174
  attrs = attrs || {}
169
175
 
170
- // If CLS is supported, a cls value should exist and be reported, even at 0.
171
- // *cli Mar'23 - At this time, it remains attached to all timings. See NEWRELIC-6143.
172
- if (this.clsSupported) {
173
- attrs['cls'] = this.cls
176
+ // If cls was set to another value by `onCLS`, then it's supported and is attached onto any timing but is omitted until such time.
177
+ /*
178
+ *cli Apr'23 - Convert attach-to-all -> attach-if-not-null. See NEWRELIC-6143.
179
+ Issue: Because NR 'pageHide' was only sent once with what is considered the "final" CLS value, in the case that 'pageHide' fires before 'load' happens, we incorrectly a final CLS of 0 for that page.
180
+ Mitigation: We've set initial CLS to null so that it's omitted from timings like 'pageHide' in that edge case. It should only be included if onCLS callback was executed at least once.
181
+ Future: onCLS value changes should be reported directly & CLS separated into its own timing node so it's not beholden to 'pageHide' firing. It'd also be possible to report the real final CLS.
182
+ */
183
+ if (this.cls !== null) {
184
+ attrs.cls = this.cls
174
185
  }
175
186
 
176
187
  this.timings.push({
@@ -15,21 +15,21 @@ export const onLongTask = (onReport) => {
15
15
  const metric = {
16
16
  name: 'LT',
17
17
  value: entry.duration,
18
- info: { // this property deviates from CWV std interface but will hold the custom context to send to NRDB
19
- ltFrame: entry.name, // MDN: the browsing context or frame that can be attributed to the long task
20
- ltStart: entry.startTime, // MDN: a double representing the time (millisec) when the task started
21
- ltCtr: entry.attribution[0].containerType // MDN: type of frame container: 'iframe', 'embed', or 'object' ... but this can also be 'window'
18
+ info: { // this property deviates from CWV std interface but will hold the custom context to send to NRDB
19
+ ltFrame: entry.name, // MDN: the browsing context or frame that can be attributed to the long task
20
+ ltStart: entry.startTime, // MDN: a double representing the time (millisec) when the task started
21
+ ltCtr: entry.attribution[0].containerType // MDN: type of frame container: 'iframe', 'embed', or 'object' ... but this can also be 'window'
22
22
  }
23
23
  }
24
- if (metric.info.ltCtr !== 'window') { // the following properties are only of relevance & appended for html elements
24
+ if (metric.info.ltCtr !== 'window') { // the following properties are only of relevance & appended for html elements
25
25
  Object.assign(metric.info, {
26
- ltCtrSrc: entry.attribution[0].containerSrc, // MDN: container's 'src' attribute
27
- ltCtrId: entry.attribution[0].containerId, // MDN: container's 'id' attribute
28
- ltCtrName: entry.attribution[0].containerName // MDN: container's 'name' attribute
26
+ ltCtrSrc: entry.attribution[0].containerSrc, // MDN: container's 'src' attribute
27
+ ltCtrId: entry.attribution[0].containerId, // MDN: container's 'id' attribute
28
+ ltCtrName: entry.attribution[0].containerName // MDN: container's 'name' attribute
29
29
  })
30
30
  }
31
31
 
32
- onReport(metric) // report every long task observed unconditionally
32
+ onReport(metric) // report every long task observed unconditionally
33
33
  })
34
34
  }
35
35
 
@@ -53,7 +53,7 @@ export const onLongTask = (onReport) => {
53
53
  if (observer) {
54
54
  subscribeToEOL(() => {
55
55
  handleEntries(observer.takeRecords())
56
- }, true) // this bool is a temp arg under staged BFCache work that runs the func under the new page session logic -- tb removed w/ the feature flag later
56
+ }, true) // this bool is a temp arg under staged BFCache work that runs the func under the new page session logic -- tb removed w/ the feature flag later
57
57
 
58
58
  /* No work needed on BFCache restore for long task. */
59
59
  }
@@ -11,12 +11,12 @@ import { supportsPerformanceObserver } from '../../../common/window/supports-per
11
11
  import slice from 'lodash._slice'
12
12
  import { getConfigurationValue, getInfo, getRuntime } from '../../../common/config/config'
13
13
  import { now } from '../../../common/timing/now'
14
- import { AggregateBase } from '../../utils/aggregate-base'
15
14
  import { FEATURE_NAME } from '../constants'
16
15
  import { drain } from '../../../common/drain/drain'
17
16
  import { HandlerCache } from '../../utils/handler-cache'
17
+ import { FeatureBase } from '../../utils/feature-base'
18
18
 
19
- export class Aggregate extends AggregateBase {
19
+ export class Aggregate extends FeatureBase {
20
20
  static featureName = FEATURE_NAME
21
21
  constructor (agentIdentifier, aggregator) {
22
22
  super(agentIdentifier, aggregator, FEATURE_NAME)
@@ -75,7 +75,11 @@ export class Aggregate extends AggregateBase {
75
75
  this.laststart = 0
76
76
 
77
77
  registerHandler('feat-stn', () => {
78
- this.storeTiming(window.performance.timing)
78
+ if (typeof PerformanceNavigationTiming !== 'undefined') {
79
+ this.storeTiming(window.performance?.getEntriesByType('navigation')?.[0] || {})
80
+ } else {
81
+ this.storeTiming(window.performance?.timing)
82
+ }
79
83
 
80
84
  var scheduler = new HarvestScheduler('resources', {
81
85
  onFinished: onHarvestFinished.bind(this),
@@ -135,25 +139,24 @@ export class Aggregate extends AggregateBase {
135
139
  processPVT (name, value, attrs) {
136
140
  var t = {}
137
141
  t[name] = value
138
- this.storeTiming(t, true)
142
+ this.storeTiming(t)
139
143
  if (this.hasFID(name, attrs)) this.storeEvent({ type: 'fid', target: 'document' }, 'document', value, value + attrs.fid)
140
144
  }
141
145
 
142
- storeTiming (_t, ignoreOffset) {
143
- var key
144
- var val
145
- var timeOffset
146
- var dateNow = Date.now()
147
-
146
+ storeTiming (_t) {
148
147
  // loop iterates through prototype also (for FF)
149
- for (key in _t) {
150
- val = _t[key]
148
+ for (let key in _t) {
149
+ const val = _t[key]
150
+
151
+ // ignore size and status type nodes that do not map to timestamp metrics
152
+ const lck = key.toLowerCase()
153
+ if (lck.indexOf('size') >= 0 || lck.indexOf('status') >= 0) continue
151
154
 
152
155
  // ignore inherited methods, meaningless 0 values, and bogus timestamps
153
156
  // that are in the future (Microsoft Edge seems to sometimes produce these)
154
- if (!(typeof (val) === 'number' && val > 0 && val < dateNow)) continue
157
+ if (!(typeof (val) === 'number' && val >= 0)) continue
155
158
 
156
- timeOffset = !ignoreOffset ? _t[key] - getRuntime(this.agentIdentifier).offset : _t[key]
159
+ const timeOffset = Math.round(_t[key])
157
160
 
158
161
  this.storeSTN({
159
162
  n: key,
@@ -78,8 +78,9 @@ export class Instrument extends InstrumentBase {
78
78
  observeResourceTimings()
79
79
  } else {
80
80
  // collect resource timings once when buffer is full
81
- if (window.performance[CRT] && window.performance[ADD_EVENT_LISTENER])
82
- { window.performance.addEventListener(RESOURCE_TIMING_BUFFER_FULL, this.onResourceTimingBufferFull, eventListenerOpts(false)) }
81
+ if (window.performance[CRT] && window.performance[ADD_EVENT_LISTENER]) {
82
+ window.performance.addEventListener(RESOURCE_TIMING_BUFFER_FULL, this.onResourceTimingBufferFull, eventListenerOpts(false))
83
+ }
83
84
  }
84
85
 
85
86
  function observeResourceTimings () {
@@ -2,7 +2,7 @@
2
2
  * Copyright 2020 New Relic Corporation. All rights reserved.
3
3
  * SPDX-License-Identifier: Apache-2.0
4
4
  */
5
- /*eslint no-undef: "error"*/
5
+ /* eslint no-undef: "error" */
6
6
  import { registerHandler as register } from '../../../common/event-emitter/register-handler'
7
7
  import { parseUrl } from '../../../common/url/parse-url'
8
8
  import { shouldCollectEvent } from '../../../common/deny-list/deny-list'
@@ -13,19 +13,19 @@ import { paintMetrics } from '../../../common/metrics/paint-metrics'
13
13
  import { Interaction } from './interaction'
14
14
  import { getConfigurationValue, getRuntime } from '../../../common/config/config'
15
15
  import { eventListenerOpts } from '../../../common/event-listener/event-listener-opts'
16
- import { AggregateBase } from '../../utils/aggregate-base'
17
16
  import { HarvestScheduler } from '../../../common/harvest/harvest-scheduler'
18
17
  import { Serializer } from './serializer'
19
18
  import { ee } from '../../../common/event-emitter/contextual-ee'
20
19
  import * as CONSTANTS from '../constants'
21
20
  import { drain } from '../../../common/drain/drain'
22
21
  import { FEATURE_NAMES } from '../../../loaders/features/features'
22
+ import { FeatureBase } from '../../utils/feature-base'
23
23
 
24
24
  const {
25
25
  FEATURE_NAME, INTERACTION_EVENTS, MAX_TIMER_BUDGET, FN_START, FN_END, CB_START, INTERACTION_API, REMAINING,
26
26
  INTERACTION, SPA_NODE, JSONP_NODE, FETCH_START, FETCH_DONE, FETCH_BODY, JSONP_END, originalSetTimeout
27
27
  } = CONSTANTS
28
- export class Aggregate extends AggregateBase {
28
+ export class Aggregate extends FeatureBase {
29
29
  static featureName = FEATURE_NAME
30
30
  constructor (agentIdentifier, aggregator) {
31
31
  super(agentIdentifier, aggregator, FEATURE_NAME)
@@ -67,7 +67,7 @@ export class Aggregate extends AggregateBase {
67
67
  const scheduler = new HarvestScheduler('events', {
68
68
  onFinished: onHarvestFinished,
69
69
  retryDelay: state.harvestTimeSeconds
70
- }, { agentIdentifier })
70
+ }, { agentIdentifier, ee: baseEE })
71
71
  scheduler.harvest.on('events', onHarvestStarted)
72
72
 
73
73
  // childTime is used when calculating exclusive time for a cb duration.
@@ -212,7 +212,7 @@ export class Aggregate extends AggregateBase {
212
212
  if (evName === 'click') {
213
213
  var value = getActionText(ev.target)
214
214
  if (value) {
215
- state.currentNode.attrs.custom['actionText'] = value
215
+ state.currentNode.attrs.custom.actionText = value
216
216
  }
217
217
  }
218
218
  }
@@ -24,8 +24,10 @@ export class Instrument extends InstrumentBase {
24
24
 
25
25
  if (!getRuntime(agentIdentifier).xhrWrappable) return
26
26
 
27
- try { this.removeOnAbort = new AbortController() }
28
- catch (e) {}
27
+ try {
28
+ this.removeOnAbort = new AbortController()
29
+ } catch (e) {}
30
+
29
31
  let depth = 0
30
32
  let startHash
31
33
 
@@ -0,0 +1,68 @@
1
+ import { getConfigurationValue, getInfo, getRuntime, setInfo } from '../../common/config/config'
2
+ import { drain } from '../../common/drain/drain'
3
+ import { ee } from '../../common/event-emitter/contextual-ee'
4
+ import { registerHandler } from '../../common/event-emitter/register-handler'
5
+ import { isBrowserScope } from '../../common/util/global-scope'
6
+ import { SessionEntity } from '../../common/session/session-entity'
7
+ import { LocalStorage } from '../../common/storage/local-storage.js'
8
+ import { FirstPartyCookies } from '../../common/storage/first-party-cookies'
9
+ import { LocalMemory } from '../../common/storage/local-memory'
10
+
11
+ let ranOnce = 0
12
+ export function setupAgentSession (agentIdentifier) {
13
+ const agentRuntime = getRuntime(agentIdentifier)
14
+ if (ranOnce++) return agentRuntime.session
15
+
16
+ const sharedEE = ee.get(agentIdentifier)
17
+
18
+ // domain is a string that can be specified by customer.
19
+ // only way to keep the session object across subdomains is using first party cookies
20
+ // This determines which storage wrapper the session manager will use to keep state
21
+ let storageAPI
22
+ const cookiesEnabled = getConfigurationValue(agentIdentifier, 'privacy.cookies_enabled') === true
23
+ if (cookiesEnabled && isBrowserScope) {
24
+ storageAPI = getConfigurationValue(agentIdentifier, 'session.domain')
25
+ ? new FirstPartyCookies(getConfigurationValue(agentIdentifier, 'session.domain'))
26
+ : new LocalStorage()
27
+ }
28
+
29
+ if (cookiesEnabled) {
30
+ // defaults to "LocalMemory" if storageAPI is undefined, such as in Worker build
31
+ agentRuntime.session = new SessionEntity({
32
+ agentIdentifier,
33
+ key: 'SESSION',
34
+ storageAPI,
35
+ expiresMs: getConfigurationValue(agentIdentifier, 'session.expiresMs'),
36
+ inactiveMs: getConfigurationValue(agentIdentifier, 'session.inactiveMs')
37
+ })
38
+ }
39
+
40
+ // The first time the agent runs on a page, it should put everything
41
+ // that's currently stored in the storage API into the local info.jsAttributes object
42
+ if (isBrowserScope) {
43
+ // retrieve & re-add all of the persisted setCustomAttribute|setUserId k-v from previous page load(s)
44
+ const customSessionData = agentRuntime.session?.read?.()?.custom
45
+ const agentInfo = getInfo(agentIdentifier)
46
+ if (customSessionData) {
47
+ setInfo(agentIdentifier, { ...agentInfo, jsAttributes: { ...agentInfo.jsAttributes, ...customSessionData } })
48
+ }
49
+ }
50
+
51
+ // any calls to newrelic.setCustomAttribute(<persisted>) will need to be added to:
52
+ // local info.jsAttributes {}
53
+ // the session's storage API
54
+ registerHandler('api-setCustomAttribute', (time, key, value) => {
55
+ agentRuntime.session.syncCustomAttribute(key, value)
56
+ }, 'session', sharedEE)
57
+
58
+ // any calls to newrelic.setUserId(...) will need to be added to:
59
+ // local info.jsAttributes {}
60
+ // the session's storage API
61
+ registerHandler('api-setUserId', (time, key, value) => {
62
+ agentRuntime.session.syncCustomAttribute(key, value)
63
+ }, 'session', sharedEE)
64
+
65
+ drain(agentIdentifier, 'session')
66
+
67
+ return agentRuntime.session
68
+ }
@@ -28,7 +28,7 @@ export class FeatureBase {
28
28
  * loader configurations may appear after the loader code is executed.
29
29
  */
30
30
  checkConfiguration () {
31
- // NOTE: This check has to happen at aggregator load time, but could be moved to `AggregateBase`.
31
+ // NOTE: This check has to happen at aggregator load time
32
32
  if (!isConfigured(this.agentIdentifier)) {
33
33
  let jsAttributes = { ...gosCDN().info?.jsAttributes }
34
34
  try {
@@ -49,13 +49,16 @@ export class InstrumentBase extends FeatureBase {
49
49
  * it's only responsible for aborting its one specific feature, rather than all.
50
50
  */
51
51
  try {
52
+ // The session entity needs to be attached to the config internals before the aggregator chunk runs
53
+ const { setupAgentSession } = await import(/* webpackChunkName: "session-manager" */ './agent-session')
54
+ setupAgentSession(this.agentIdentifier)
55
+ // import and instantiate the aggregator chunk
52
56
  const { lazyLoader } = await import(/* webpackChunkName: "lazy-loader" */ './lazy-loader')
53
57
  const { Aggregate } = await lazyLoader(this.featureName, 'aggregate')
54
58
  new Aggregate(this.agentIdentifier, this.aggregator)
55
59
  } catch (e) {
56
- warn(`Downloading ${this.featureName} failed...`)
60
+ warn(`Downloading ${this.featureName} failed...`, e)
57
61
  this.abortHandler?.() // undo any important alterations made to the page
58
-
59
62
  // not supported yet but nice to do: "abort" this agent's EE for this feature specifically
60
63
  }
61
64
  }
@@ -9,7 +9,7 @@ import { FEATURE_NAMES } from '../../loaders/features/features'
9
9
  * should be.
10
10
  * @param featureName Name of the feature to import such as ajax or session_trace
11
11
  * @param featurePart Name of the feature part to load; should be either instrument or aggregate
12
- * @returns {Promise<InstrumentBase|AggregateBase|null>}
12
+ * @returns {Promise<InstrumentBase|FeatureBase|null>}
13
13
  */
14
14
  export function lazyLoader (featureName, featurePart) {
15
15
  if (featurePart === 'aggregate') {
@@ -68,7 +68,7 @@ export class Agent {
68
68
  }
69
69
 
70
70
  const newrelic = gosNREUM()
71
- delete newrelic.initializedAgents[this.agentIdentifier]?.['api'] // prevent further calls to agent-specific APIs (see "configure.js")
71
+ delete newrelic.initializedAgents[this.agentIdentifier]?.api // prevent further calls to agent-specific APIs (see "configure.js")
72
72
  delete newrelic.initializedAgents[this.agentIdentifier]?.[NR_FEATURES_REF_NAME] // GC mem used internally by features
73
73
  delete this.sharedAggregator
74
74
  // Keep the initialized agent object with its configs for troubleshooting purposes.