@newrelic/browser-agent 1.232.0 → 1.233.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (273) hide show
  1. package/dist/cjs/cdn/polyfills.js +5 -2
  2. package/dist/cjs/common/config/state/configurable.js +15 -26
  3. package/dist/cjs/common/config/state/info.js +1 -1
  4. package/dist/cjs/common/config/state/init.js +101 -56
  5. package/dist/cjs/common/config/state/loader-config.js +1 -1
  6. package/dist/cjs/common/config/state/runtime.js +1 -5
  7. package/dist/cjs/common/constants/env.cdn.js +1 -1
  8. package/dist/cjs/common/constants/env.npm.js +1 -1
  9. package/dist/cjs/common/drain/drain.js +1 -1
  10. package/dist/cjs/common/harvest/harvest-scheduler.js +30 -10
  11. package/dist/cjs/common/harvest/harvest.js +119 -55
  12. package/dist/cjs/common/session/session-entity.js +35 -22
  13. package/dist/cjs/common/session/session-entity.test.js +73 -49
  14. package/dist/cjs/common/timer/interaction-timer.js +9 -12
  15. package/dist/cjs/common/url/canonicalize-url.js +32 -0
  16. package/dist/cjs/common/url/canonicalize-url.test.js +42 -0
  17. package/dist/cjs/common/url/clean-url.js +10 -3
  18. package/dist/cjs/common/url/protocol.test.js +0 -1
  19. package/dist/cjs/common/util/feature-flags.js +2 -1
  20. package/dist/cjs/common/util/global-scope.js +4 -2
  21. package/dist/cjs/common/util/submit-data.js +57 -18
  22. package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
  23. package/dist/cjs/common/wrap/wrap-function.js +1 -3
  24. package/dist/cjs/common/wrap/wrap-promise.js +1 -1
  25. package/dist/cjs/features/ajax/aggregate/index.js +2 -2
  26. package/dist/cjs/features/ajax/instrument/index.js +1 -1
  27. package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +12 -4
  28. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +93 -10
  29. package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +164 -38
  30. package/dist/cjs/features/jserrors/aggregate/index.js +29 -48
  31. package/dist/cjs/features/jserrors/instrument/index.js +0 -2
  32. package/dist/cjs/features/metrics/aggregate/framework-detection.js +67 -0
  33. package/dist/cjs/features/metrics/aggregate/framework-detection.test.js +137 -0
  34. package/dist/cjs/features/metrics/aggregate/index.js +7 -3
  35. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +14 -0
  36. package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.test.js +17 -0
  37. package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +53 -0
  38. package/dist/cjs/features/metrics/aggregate/polyfill-detection.test.js +165 -0
  39. package/dist/cjs/features/page_action/aggregate/index.js +2 -2
  40. package/dist/cjs/features/page_view_event/aggregate/index.js +6 -3
  41. package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -2
  42. package/dist/cjs/features/session_replay/aggregate/index.js +333 -0
  43. package/dist/cjs/features/session_replay/constants.js +9 -0
  44. package/dist/cjs/features/session_replay/index.js +12 -0
  45. package/dist/cjs/features/session_replay/instrument/index.js +29 -0
  46. package/dist/cjs/features/session_trace/aggregate/index.js +163 -164
  47. package/dist/cjs/features/session_trace/constants.js +2 -9
  48. package/dist/cjs/features/session_trace/instrument/index.js +24 -66
  49. package/dist/cjs/features/spa/aggregate/index.js +2 -2
  50. package/dist/cjs/features/utils/agent-session.js +1 -2
  51. package/dist/cjs/features/utils/aggregate-base.js +64 -0
  52. package/dist/cjs/features/utils/feature-base.js +0 -31
  53. package/dist/cjs/features/utils/handler-cache.js +3 -4
  54. package/dist/cjs/features/utils/instrument-base.js +42 -10
  55. package/dist/cjs/features/utils/{lazy-loader.js → lazy-feature-loader.js} +4 -2
  56. package/dist/cjs/loaders/agent.js +1 -1
  57. package/dist/cjs/loaders/api/apiAsync.js +3 -1
  58. package/dist/cjs/loaders/configure/configure.js +3 -3
  59. package/dist/cjs/loaders/features/featureDependencies.js +0 -12
  60. package/dist/cjs/loaders/features/features.js +3 -1
  61. package/dist/cjs/loaders/micro-agent.js +6 -6
  62. package/dist/esm/cdn/polyfills.js +5 -2
  63. package/dist/esm/common/config/state/configurable.js +14 -24
  64. package/dist/esm/common/config/state/info.js +2 -2
  65. package/dist/esm/common/config/state/init.js +102 -57
  66. package/dist/esm/common/config/state/loader-config.js +2 -2
  67. package/dist/esm/common/config/state/runtime.js +2 -4
  68. package/dist/esm/common/constants/env.cdn.js +1 -1
  69. package/dist/esm/common/constants/env.npm.js +1 -1
  70. package/dist/esm/common/drain/drain.js +1 -1
  71. package/dist/esm/common/harvest/harvest-scheduler.js +30 -10
  72. package/dist/esm/common/harvest/harvest.js +121 -56
  73. package/dist/esm/common/session/session-entity.js +35 -22
  74. package/dist/esm/common/session/session-entity.test.js +73 -49
  75. package/dist/esm/common/timer/interaction-timer.js +9 -12
  76. package/dist/esm/common/url/canonicalize-url.js +27 -0
  77. package/dist/esm/common/url/canonicalize-url.test.js +38 -0
  78. package/dist/esm/common/url/clean-url.js +10 -3
  79. package/dist/esm/common/url/protocol.test.js +0 -1
  80. package/dist/esm/common/util/feature-flags.js +2 -1
  81. package/dist/esm/common/util/global-scope.js +1 -0
  82. package/dist/esm/common/util/submit-data.js +57 -18
  83. package/dist/esm/common/wrap/wrap-fetch.js +1 -2
  84. package/dist/esm/common/wrap/wrap-function.js +1 -2
  85. package/dist/esm/common/wrap/wrap-promise.js +1 -1
  86. package/dist/esm/features/ajax/aggregate/index.js +2 -2
  87. package/dist/esm/features/ajax/instrument/index.js +1 -1
  88. package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +12 -4
  89. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +93 -10
  90. package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +149 -25
  91. package/dist/esm/features/jserrors/aggregate/index.js +30 -48
  92. package/dist/esm/features/jserrors/instrument/index.js +0 -1
  93. package/dist/esm/features/metrics/aggregate/framework-detection.js +61 -0
  94. package/dist/esm/features/metrics/aggregate/framework-detection.test.js +133 -0
  95. package/dist/esm/features/metrics/aggregate/index.js +7 -3
  96. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +8 -0
  97. package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.test.js +15 -0
  98. package/dist/esm/features/metrics/aggregate/polyfill-detection.js +47 -0
  99. package/dist/esm/features/metrics/aggregate/polyfill-detection.test.js +163 -0
  100. package/dist/esm/features/page_action/aggregate/index.js +2 -2
  101. package/dist/esm/features/page_view_event/aggregate/index.js +6 -3
  102. package/dist/esm/features/page_view_timing/aggregate/index.js +2 -2
  103. package/dist/esm/features/session_replay/aggregate/index.js +327 -0
  104. package/dist/esm/features/session_replay/constants.js +2 -0
  105. package/dist/esm/features/session_replay/index.js +12 -0
  106. package/dist/esm/features/session_replay/instrument/index.js +21 -0
  107. package/dist/esm/features/session_trace/aggregate/index.js +163 -163
  108. package/dist/esm/features/session_trace/constants.js +1 -5
  109. package/dist/esm/features/session_trace/instrument/index.js +24 -66
  110. package/dist/esm/features/spa/aggregate/index.js +2 -2
  111. package/dist/esm/features/utils/agent-session.js +1 -2
  112. package/dist/esm/features/utils/aggregate-base.js +57 -0
  113. package/dist/esm/features/utils/feature-base.js +1 -32
  114. package/dist/esm/features/utils/handler-cache.js +3 -4
  115. package/dist/esm/features/utils/instrument-base.js +42 -10
  116. package/dist/esm/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
  117. package/dist/esm/loaders/agent.js +1 -1
  118. package/dist/esm/loaders/api/apiAsync.js +3 -1
  119. package/dist/esm/loaders/configure/configure.js +3 -3
  120. package/dist/esm/loaders/features/featureDependencies.js +0 -11
  121. package/dist/esm/loaders/features/features.js +3 -1
  122. package/dist/esm/loaders/micro-agent.js +6 -6
  123. package/dist/types/common/config/state/configurable.d.ts +1 -3
  124. package/dist/types/common/config/state/configurable.d.ts.map +1 -1
  125. package/dist/types/common/config/state/init.d.ts.map +1 -1
  126. package/dist/types/common/config/state/runtime.d.ts.map +1 -1
  127. package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
  128. package/dist/types/common/harvest/harvest.d.ts +37 -34
  129. package/dist/types/common/harvest/harvest.d.ts.map +1 -1
  130. package/dist/types/common/session/session-entity.d.ts +6 -3
  131. package/dist/types/common/session/session-entity.d.ts.map +1 -1
  132. package/dist/types/common/timer/interaction-timer.d.ts +2 -1
  133. package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
  134. package/dist/types/common/url/canonicalize-url.d.ts +9 -0
  135. package/dist/types/common/url/canonicalize-url.d.ts.map +1 -0
  136. package/dist/types/common/url/clean-url.d.ts +7 -1
  137. package/dist/types/common/url/clean-url.d.ts.map +1 -1
  138. package/dist/types/common/util/feature-flags.d.ts.map +1 -1
  139. package/dist/types/common/util/global-scope.d.ts +1 -0
  140. package/dist/types/common/util/global-scope.d.ts.map +1 -1
  141. package/dist/types/common/util/submit-data.d.ts +40 -14
  142. package/dist/types/common/util/submit-data.d.ts.map +1 -1
  143. package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
  144. package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
  145. package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
  146. package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
  147. package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts +8 -1
  148. package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts.map +1 -1
  149. package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts +48 -19
  150. package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts.map +1 -1
  151. package/dist/types/features/jserrors/aggregate/index.d.ts +14 -5
  152. package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
  153. package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
  154. package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -0
  155. package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
  156. package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
  157. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +6 -0
  158. package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +1 -0
  159. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +7 -0
  160. package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +1 -0
  161. package/dist/types/features/page_action/aggregate/index.d.ts +3 -3
  162. package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
  163. package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
  164. package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
  165. package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -2
  166. package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
  167. package/dist/types/features/session_replay/aggregate/index.d.ts +96 -0
  168. package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -0
  169. package/dist/types/features/session_replay/constants.d.ts +2 -0
  170. package/dist/types/features/session_replay/constants.d.ts.map +1 -0
  171. package/dist/types/features/session_replay/index.d.ts +2 -0
  172. package/dist/types/features/session_replay/index.d.ts.map +1 -0
  173. package/dist/types/features/session_replay/instrument/index.d.ts +6 -0
  174. package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -0
  175. package/dist/types/features/session_trace/aggregate/index.d.ts +8 -57
  176. package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
  177. package/dist/types/features/session_trace/constants.d.ts +0 -3
  178. package/dist/types/features/session_trace/constants.d.ts.map +1 -1
  179. package/dist/types/features/session_trace/instrument/index.d.ts +1 -3
  180. package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
  181. package/dist/types/features/spa/aggregate/index.d.ts +2 -2
  182. package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
  183. package/dist/types/features/utils/agent-session.d.ts.map +1 -1
  184. package/dist/types/features/utils/aggregate-base.d.ts +11 -0
  185. package/dist/types/features/utils/aggregate-base.d.ts.map +1 -0
  186. package/dist/types/features/utils/feature-base.d.ts +0 -5
  187. package/dist/types/features/utils/feature-base.d.ts.map +1 -1
  188. package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
  189. package/dist/types/features/utils/instrument-base.d.ts +3 -1
  190. package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
  191. package/dist/types/features/utils/{lazy-loader.d.ts → lazy-feature-loader.d.ts} +2 -2
  192. package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -0
  193. package/dist/types/loaders/configure/configure.d.ts.map +1 -1
  194. package/dist/types/loaders/features/featureDependencies.d.ts +0 -1
  195. package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
  196. package/dist/types/loaders/features/features.d.ts +1 -0
  197. package/dist/types/loaders/features/features.d.ts.map +1 -1
  198. package/package.json +31 -22
  199. package/src/cdn/polyfills.js +4 -1
  200. package/src/common/config/state/configurable.js +18 -24
  201. package/src/common/config/state/info.js +2 -2
  202. package/src/common/config/state/init.js +62 -28
  203. package/src/common/config/state/loader-config.js +2 -2
  204. package/src/common/config/state/runtime.js +2 -4
  205. package/src/common/drain/drain.js +1 -1
  206. package/src/common/harvest/harvest-scheduler.js +35 -10
  207. package/src/common/harvest/harvest.js +73 -50
  208. package/src/common/session/session-entity.js +34 -23
  209. package/src/common/session/session-entity.test.js +57 -51
  210. package/src/common/timer/interaction-timer.js +9 -12
  211. package/src/common/url/canonicalize-url.js +28 -0
  212. package/src/common/url/canonicalize-url.test.js +34 -0
  213. package/src/common/url/clean-url.js +10 -3
  214. package/src/common/url/protocol.test.js +0 -1
  215. package/src/common/util/feature-flags.js +2 -2
  216. package/src/common/util/global-scope.js +2 -0
  217. package/src/common/util/submit-data.js +28 -17
  218. package/src/common/wrap/wrap-fetch.js +1 -2
  219. package/src/common/wrap/wrap-function.js +1 -2
  220. package/src/common/wrap/wrap-promise.js +1 -1
  221. package/src/features/ajax/aggregate/index.js +2 -2
  222. package/src/features/ajax/instrument/index.js +1 -1
  223. package/src/features/jserrors/aggregate/canonical-function-name.js +12 -4
  224. package/src/features/jserrors/aggregate/compute-stack-trace.js +85 -11
  225. package/src/features/jserrors/aggregate/compute-stack-trace.test.js +141 -24
  226. package/src/features/jserrors/aggregate/index.js +28 -52
  227. package/src/features/jserrors/instrument/index.js +0 -1
  228. package/src/features/metrics/aggregate/framework-detection.js +73 -0
  229. package/src/features/metrics/aggregate/framework-detection.test.js +201 -0
  230. package/src/features/metrics/aggregate/index.js +8 -3
  231. package/src/features/metrics/aggregate/polyfill-detection.es5.js +9 -0
  232. package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +16 -0
  233. package/src/features/metrics/aggregate/polyfill-detection.js +48 -0
  234. package/src/features/metrics/aggregate/polyfill-detection.test.js +163 -0
  235. package/src/features/page_action/aggregate/index.js +2 -2
  236. package/src/features/page_view_event/aggregate/index.js +5 -5
  237. package/src/features/page_view_timing/aggregate/index.js +2 -2
  238. package/src/features/session_replay/aggregate/index.js +314 -0
  239. package/src/features/session_replay/constants.js +3 -0
  240. package/src/features/session_replay/index.js +12 -0
  241. package/src/features/session_replay/instrument/index.js +22 -0
  242. package/src/features/session_trace/aggregate/index.js +148 -188
  243. package/src/features/session_trace/constants.js +0 -4
  244. package/src/features/session_trace/instrument/index.js +17 -69
  245. package/src/features/spa/aggregate/index.js +2 -2
  246. package/src/features/utils/agent-session.js +1 -2
  247. package/src/features/utils/aggregate-base.js +51 -0
  248. package/src/features/utils/feature-base.js +1 -31
  249. package/src/features/utils/handler-cache.js +3 -4
  250. package/src/features/utils/instrument-base.js +40 -8
  251. package/src/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
  252. package/src/loaders/agent.js +1 -1
  253. package/src/loaders/api/apiAsync.js +1 -1
  254. package/src/loaders/configure/configure.js +4 -3
  255. package/src/loaders/features/featureDependencies.js +0 -12
  256. package/src/loaders/features/features.js +3 -1
  257. package/src/loaders/micro-agent.js +4 -4
  258. package/dist/cjs/common/metrics/framework-detection.js +0 -72
  259. package/dist/cjs/common/util/user-agent.js +0 -57
  260. package/dist/cjs/common/window/supports-performance-observer.js +0 -15
  261. package/dist/esm/common/metrics/framework-detection.js +0 -66
  262. package/dist/esm/common/util/user-agent.js +0 -48
  263. package/dist/esm/common/window/supports-performance-observer.js +0 -9
  264. package/dist/types/common/metrics/framework-detection.d.ts.map +0 -1
  265. package/dist/types/common/util/user-agent.d.ts +0 -5
  266. package/dist/types/common/util/user-agent.d.ts.map +0 -1
  267. package/dist/types/common/window/supports-performance-observer.d.ts +0 -2
  268. package/dist/types/common/window/supports-performance-observer.d.ts.map +0 -1
  269. package/dist/types/features/utils/lazy-loader.d.ts.map +0 -1
  270. package/src/common/metrics/framework-detection.js +0 -71
  271. package/src/common/util/user-agent.js +0 -56
  272. package/src/common/window/supports-performance-observer.js +0 -10
  273. /package/dist/types/{common/metrics → features/metrics/aggregate}/framework-detection.d.ts +0 -0
@@ -57,6 +57,7 @@
57
57
  // ex.message = ...
58
58
  // ex.name = ReferenceError
59
59
  import { formatStackTrace } from './format-stack-trace'
60
+ import { canonicalizeUrl } from '../../../common/url/canonicalize-url'
60
61
 
61
62
  var debug = false
62
63
 
@@ -66,6 +67,23 @@ var gecko = /^\s*(?:(\S*|global code)(?:\(.*?\))?@)?((?:file|http|https|chrome|s
66
67
  var chrome_eval = /^\s*at .+ \(eval at \S+ \((?:(?:file|http|https):[^)]+)?\)(?:, [^:]*:\d+:\d+)?\)$/i
67
68
  var ie_eval = /^\s*at Function code \(Function code:\d+:\d+\)\s*/i
68
69
 
70
+ /**
71
+ * Represents an error with a stack trace.
72
+ * @typedef {Object} StackInfo
73
+ * @property {string} name - The name of the error (e.g. 'TypeError').
74
+ * @property {string} message - The error message.
75
+ * @property {string} stackString - The stack trace as a string.
76
+ * @property {Array<Object>} frames - An array of frames in the stack trace.
77
+ * @property {string} frames.url - The URL of the file containing the code for the frame.
78
+ * @property {string} frames.func - The name of the function associated with the frame.
79
+ * @property {number} frames.line - The line number of the code in the frame.
80
+ */
81
+
82
+ /**
83
+ * Attempts to compute a stack trace for the given exception.
84
+ * @param {Error} ex - The exception for which to compute the stack trace.
85
+ * @returns {StackInfo} A stack trace object containing information about the frames on the stack.
86
+ */
69
87
  export function computeStackTrace (ex) {
70
88
  var stack = null
71
89
 
@@ -110,9 +128,9 @@ export function computeStackTrace (ex) {
110
128
  }
111
129
 
112
130
  /**
113
- * Computes stack trace information from the stack property.
114
- * Chrome and Gecko use this property.
115
- * @param {Error} ex
131
+ * Computes stack trace information from the stack property. Chrome and Gecko use this property.
132
+ *
133
+ * @param {Error} ex - The error object to compute the stack trace for.
116
134
  * @return {?Object.<string, *>} Stack trace information.
117
135
  */
118
136
  function computeStackTraceFromStackProp (ex) {
@@ -136,22 +154,49 @@ function computeStackTraceFromStackProp (ex) {
136
154
  }
137
155
  }
138
156
 
157
+ /**
158
+ * Parses a line from a JavaScript error stack trace and adds it to the given `info` object.
159
+ * Ignores all stack entries thrown from one of our wrapper functions.
160
+ *
161
+ * @param {object} info - The `info` object to add the parsed line to.
162
+ * @param {string} line - The line to parse.
163
+ * @returns {object} The `info` object with the parsed line added.
164
+ */
139
165
  function parseStackProp (info, line) {
140
- var element = getElement(line)
166
+ let element = getStackElement(line)
141
167
 
168
+ // This catches lines that aren't frames (like the first line stating the error).
142
169
  if (!element) {
143
170
  info.stackLines.push(line)
144
171
  return info
145
172
  }
146
173
 
147
- if (isWrapper(element.func)) info.wrapperSeen = true
148
- else info.stackLines.push(line)
174
+ // Once we've seen a wrapper, ignore all subsequent stack entries.
175
+ if (isNrWrapper(element.func)) info.wrapperSeen = true
176
+ if (!info.wrapperSeen) {
177
+ // Query strings and fragments should be removed, and URLs matching the loader's origin should be "<inline>".
178
+ let canonicalUrl = canonicalizeUrl(element.url)
179
+ if (canonicalUrl !== element.url) {
180
+ line = line.replace(element.url, canonicalUrl)
181
+ element.url = canonicalUrl
182
+ }
183
+
184
+ info.stackLines.push(line)
185
+ info.frames.push(element)
186
+ }
149
187
 
150
- if (!info.wrapperSeen) info.frames.push(element)
151
188
  return info
152
189
  }
153
190
 
154
- function getElement (line) {
191
+ /**
192
+ * Parses a line from a JavaScript error stack trace to extract information about a stack trace element, such as the
193
+ * URL, function name, line number, and column number.
194
+ *
195
+ * @param {string} line - A single line from a JavaScript error stack trace.
196
+ * @returns {object} An object containing information about the stack trace element, including the URL, function
197
+ * name, line number, and column number (if available).
198
+ */
199
+ function getStackElement (line) {
155
200
  var parts = line.match(gecko)
156
201
  if (!parts) parts = line.match(chrome)
157
202
 
@@ -169,6 +214,14 @@ function getElement (line) {
169
214
  }
170
215
  }
171
216
 
217
+ /**
218
+ * Computes a stack trace object from an error object, by extracting the source and line number from the error object,
219
+ * and using them to create a single stack frame.
220
+ *
221
+ * @param {Error} ex - The error object to compute the stack trace for.
222
+ * @returns {Object|null} - An object representing the computed stack trace, or null if the
223
+ * input error object does not contain a line number.
224
+ */
172
225
  function computeStackTraceBySourceAndLine (ex) {
173
226
  if (!('line' in ex)) return null
174
227
 
@@ -187,7 +240,10 @@ function computeStackTraceBySourceAndLine (ex) {
187
240
  })
188
241
  }
189
242
 
190
- var stackString = className + ': ' + ex.message + '\n at ' + ex.sourceURL
243
+ // Remove any query string and fragment
244
+ var canonicalUrl = canonicalizeUrl(ex.sourceURL)
245
+
246
+ var stackString = className + ': ' + ex.message + '\n at ' + canonicalUrl
191
247
  if (ex.line) {
192
248
  stackString += ':' + ex.line
193
249
  if (ex.column) {
@@ -201,13 +257,19 @@ function computeStackTraceBySourceAndLine (ex) {
201
257
  message: ex.message,
202
258
  stackString: stackString,
203
259
  frames: [{
204
- url: ex.sourceURL,
260
+ url: canonicalUrl,
205
261
  line: ex.line,
206
262
  column: ex.column
207
263
  }]
208
264
  })
209
265
  }
210
266
 
267
+ /**
268
+ * For exceptions with no stack and only a message, derives a stack trace by extracting the class name and message.
269
+ *
270
+ * @param {Error} ex - The exception for which to compute the stack trace.
271
+ * @returns {StackTrace} A stack trace object containing the name and message of the exception.
272
+ */
211
273
  function computeStackTraceWithMessageOnly (ex) {
212
274
  var className = ex.name || getClassName(ex)
213
275
  if (!className) return null
@@ -221,11 +283,23 @@ function computeStackTraceWithMessageOnly (ex) {
221
283
  })
222
284
  }
223
285
 
286
+ /**
287
+ * Attempts to extract the name of the constructor function (the class) of the given object.
288
+ *
289
+ * @param {Object} obj - The object for which to extract the constructor function name.
290
+ * @returns {string} The name of the constructor function, or 'unknown' if the name cannot be determined.
291
+ */
224
292
  function getClassName (obj) {
225
293
  var results = classNameRegex.exec(String(obj.constructor))
226
294
  return (results && results.length > 1) ? results[1] : 'unknown'
227
295
  }
228
296
 
229
- function isWrapper (functionName) {
297
+ /**
298
+ * Checks whether the given function name is a New Relic wrapper function.
299
+ *
300
+ * @param {string} functionName - The name of the function to check.
301
+ * @returns {boolean} True if the function name includes the string 'nrWrapper', false otherwise.
302
+ */
303
+ function isNrWrapper (functionName) {
230
304
  return (functionName && functionName.indexOf('nrWrapper') >= 0)
231
305
  }
@@ -1,16 +1,34 @@
1
1
  import { faker } from '@faker-js/faker'
2
2
  import { browserErrorUtils } from '../../../../tools/testing-utils'
3
- import { computeStackTrace } from './compute-stack-trace'
3
+
4
+ const globalScopeLocation = 'https://example.com/'
5
+
6
+ const mockGlobalScopeLocation = (url) => {
7
+ jest.doMock('../../../common/util/global-scope', () => ({
8
+ initialLocation: url || globalScopeLocation
9
+ }))
10
+ }
11
+
12
+ afterEach(() => {
13
+ jest.resetModules()
14
+ jest.clearAllMocks()
15
+ })
4
16
 
5
17
  const baseMockError = {
6
18
  toString: 'RangeError: Invalid array length',
7
19
  name: 'RangeError',
8
20
  constructor: 'function RangeError() { [native code] }',
9
21
  message: 'Invalid array length',
10
- stack: 'RangeError: Invalid array length\n at errorTest (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:74:16)\n at captureError (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:17:9)\n at onload (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:70:5)'
22
+ stack:
23
+ 'RangeError: Invalid array length\n' +
24
+ ' at errorTest (' + globalScopeLocation + '?loader=spa#hello:74:16)\n' +
25
+ ' at captureError (' + globalScopeLocation + 'js/script.js?loader=spa:17:9)\n' +
26
+ ' at onload (' + globalScopeLocation + 'js/script.js?loader=spa:70:5)'
11
27
  }
12
28
 
13
- test('parsing should return a failure for a null error object', () => {
29
+ test('parsing should return a failure for a null error object', async () => {
30
+ mockGlobalScopeLocation()
31
+ const { computeStackTrace } = await import('./compute-stack-trace')
14
32
  const result = computeStackTrace(null)
15
33
 
16
34
  expect(result).toEqual(expect.objectContaining({
@@ -21,29 +39,49 @@ test('parsing should return a failure for a null error object', () => {
21
39
  })
22
40
 
23
41
  describe('errors with stack property', () => {
24
- test('parsed name should be unknown when name and constructor are missing', () => {
42
+ test('should show <inline> for same-page stack string URLs but not sub-paths', async () => {
43
+ const mockError = browserErrorUtils.constructError({
44
+ ...baseMockError
45
+ })
46
+
47
+ mockGlobalScopeLocation()
48
+ const { computeStackTrace } = await import('./compute-stack-trace')
49
+ const result = computeStackTrace(mockError)
50
+
51
+ expect(result).toEqual(expect.objectContaining({
52
+ stackString: // canonicalized
53
+ 'RangeError: Invalid array length\n' +
54
+ ' at errorTest (<inline>:74:16)\n' +
55
+ ' at captureError (' + globalScopeLocation + 'js/script.js:17:9)\n' +
56
+ ' at onload (' + globalScopeLocation + 'js/script.js:70:5)'
57
+ }))
58
+ })
59
+
60
+ test('parsed name should be unknown when name and constructor are missing', async () => {
25
61
  const mockError = browserErrorUtils.constructError({
26
62
  ...baseMockError,
27
63
  name: null,
28
64
  constructor: null
29
65
  })
30
66
 
67
+ mockGlobalScopeLocation()
68
+ const { computeStackTrace } = await import('./compute-stack-trace')
31
69
  const result = computeStackTrace(mockError)
32
70
 
33
71
  expect(result).toEqual(expect.objectContaining({
34
72
  mode: 'stack',
35
- name: 'unknown',
36
- message: mockError.message,
37
- stackString: mockError.stack
73
+ name: 'unknown'
38
74
  }))
39
75
  })
40
76
 
41
- test('parsed stack should not contain nrWrapper', () => {
77
+ test('parsed stack should not contain nrWrapper', async () => {
42
78
  const alteredError = baseMockError
43
79
  alteredError.stack +=
44
- '\n at nrWrapper (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:60:17)'
80
+ '\n at nrWrapper (' + globalScopeLocation + '?loader=spa:60:17)'
45
81
  const mockError = browserErrorUtils.constructError(alteredError)
46
82
 
83
+ mockGlobalScopeLocation()
84
+ const { computeStackTrace } = await import('./compute-stack-trace')
47
85
  const result = computeStackTrace(mockError)
48
86
 
49
87
  expect(result).toEqual(expect.objectContaining({
@@ -57,20 +95,31 @@ describe('errors with stack property', () => {
57
95
  }))
58
96
  })
59
97
 
60
- test('stack should still parse when column numbers are missing', () => {
98
+ test('stack should still parse when column numbers are missing', async () => {
61
99
  const mockError = browserErrorUtils.constructError({
62
100
  ...baseMockError,
63
101
  stack:
64
- 'Error: Blocked a frame with origin "http://bam-test-1.nr-local.net:3334" from accessing a cross-origin frame.\n at errorTest (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:60)\n at captureError (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:17)\n at onload (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html?loader=spa:57)'
102
+ 'RangeError: Invalid array length\n' +
103
+ 'Error: Blocked a frame with origin "http://bam-test-1.nr-local.net:3334" from accessing a cross-origin frame.\n' +
104
+ ' at errorTest (' + globalScopeLocation + '?loader=spa:60)\n' +
105
+ ' at captureError (' + globalScopeLocation + '?loader=spa:17)\n' +
106
+ ' at onload (' + globalScopeLocation + '?loader=spa:57)'
65
107
  })
66
108
 
109
+ mockGlobalScopeLocation()
110
+ const { computeStackTrace } = await import('./compute-stack-trace')
67
111
  const result = computeStackTrace(mockError)
68
112
 
69
113
  expect(result).toEqual(expect.objectContaining({
70
114
  mode: 'stack',
71
115
  name: mockError.name,
72
116
  message: mockError.message,
73
- stackString: mockError.stack
117
+ stackString:
118
+ 'RangeError: Invalid array length\n' +
119
+ 'Error: Blocked a frame with origin "http://bam-test-1.nr-local.net:3334" from accessing a cross-origin frame.\n' +
120
+ ' at errorTest (<inline>:60)\n' +
121
+ ' at captureError (<inline>:17)\n' +
122
+ ' at onload (<inline>:57)'
74
123
  }))
75
124
  expect(result.frames.length).toEqual(3)
76
125
  expect(result.frames).toContainEqual(expect.objectContaining({
@@ -87,13 +136,15 @@ describe('errors with stack property', () => {
87
136
  }))
88
137
  })
89
138
 
90
- test('parser can handle chrome eval stack', () => {
139
+ test('parser can handle chrome eval stack', async () => {
91
140
  const mockError = browserErrorUtils.constructError({
92
141
  ...baseMockError,
93
142
  stack:
94
- ' at foobar (eval at foobar (http://bam-test-1.nr-local.net:3334/tests/assets/instrumented.html))'
143
+ ' at foobar (eval at foobar (' + globalScopeLocation + '))'
95
144
  })
96
145
 
146
+ mockGlobalScopeLocation()
147
+ const { computeStackTrace } = await import('./compute-stack-trace')
97
148
  const result = computeStackTrace(mockError)
98
149
 
99
150
  expect(result).toEqual(expect.objectContaining({
@@ -108,7 +159,7 @@ describe('errors with stack property', () => {
108
159
  }))
109
160
  })
110
161
 
111
- test('parser can handle ie eval stack', () => {
162
+ test('parser can handle ie eval stack', async () => {
112
163
  const mockError = browserErrorUtils.constructError({
113
164
  toString: 'TypeError: Permission denied',
114
165
  name: 'TypeError',
@@ -118,6 +169,8 @@ describe('errors with stack property', () => {
118
169
  ' at Function code (Function code:23:23)'
119
170
  })
120
171
 
172
+ mockGlobalScopeLocation()
173
+ const { computeStackTrace } = await import('./compute-stack-trace')
121
174
  const result = computeStackTrace(mockError)
122
175
 
123
176
  expect(result).toEqual(expect.objectContaining({
@@ -132,13 +185,15 @@ describe('errors with stack property', () => {
132
185
  }))
133
186
  })
134
187
 
135
- test('parser can handle stack with anonymous function', () => {
188
+ test('parser can handle stack with anonymous function', async () => {
136
189
  const mockError = browserErrorUtils.constructError({
137
190
  ...baseMockError,
138
191
  stack:
139
192
  'anonymous'
140
193
  })
141
194
 
195
+ mockGlobalScopeLocation()
196
+ const { computeStackTrace } = await import('./compute-stack-trace')
142
197
  const result = computeStackTrace(mockError)
143
198
 
144
199
  expect(result).toEqual(expect.objectContaining({
@@ -158,7 +213,7 @@ describe('errors without stack property and with line property', () => {
158
213
  /**
159
214
  * @deprecated sourceURL is no longer present in errors for any browsers we support
160
215
  */
161
- test('parsed stack should contain sourceURL and line number', () => {
216
+ test('parsed stack should contain sourceURL and line number', async () => {
162
217
  const sourceURL = faker.internet.url()
163
218
  const mockError = browserErrorUtils.constructError({
164
219
  ...baseMockError,
@@ -167,6 +222,8 @@ describe('errors without stack property and with line property', () => {
167
222
  sourceURL
168
223
  })
169
224
 
225
+ mockGlobalScopeLocation()
226
+ const { computeStackTrace } = await import('./compute-stack-trace')
170
227
  const result = computeStackTrace(mockError)
171
228
 
172
229
  expect(result).toEqual(expect.objectContaining({
@@ -185,7 +242,7 @@ describe('errors without stack property and with line property', () => {
185
242
  /**
186
243
  * @deprecated sourceURL is no longer present in errors for any browsers we support
187
244
  */
188
- test('parsed stack should contain sourceURL, line number, and column number', () => {
245
+ test('parsed stack should contain sourceURL, line number, and column number', async () => {
189
246
  const sourceURL = faker.internet.url()
190
247
  const mockError = browserErrorUtils.constructError({
191
248
  ...baseMockError,
@@ -195,6 +252,8 @@ describe('errors without stack property and with line property', () => {
195
252
  sourceURL
196
253
  })
197
254
 
255
+ mockGlobalScopeLocation()
256
+ const { computeStackTrace } = await import('./compute-stack-trace')
198
257
  const result = computeStackTrace(mockError)
199
258
 
200
259
  expect(result).toEqual(expect.objectContaining({
@@ -211,7 +270,7 @@ describe('errors without stack property and with line property', () => {
211
270
  }))
212
271
  })
213
272
 
214
- test('parsed stack should contain "evaluated code" if sourceURL property is not present', () => {
273
+ test('parsed stack should contain "evaluated code" if sourceURL property is not present', async () => {
215
274
  const mockError = browserErrorUtils.constructError({
216
275
  ...baseMockError,
217
276
  line: 100,
@@ -219,6 +278,8 @@ describe('errors without stack property and with line property', () => {
219
278
  stack: undefined
220
279
  })
221
280
 
281
+ mockGlobalScopeLocation()
282
+ const { computeStackTrace } = await import('./compute-stack-trace')
222
283
  const result = computeStackTrace(mockError)
223
284
 
224
285
  expect(result).toEqual(expect.objectContaining({
@@ -233,6 +294,58 @@ describe('errors without stack property and with line property', () => {
233
294
  }))
234
295
  })
235
296
 
297
+ /**
298
+ * @deprecated sourceURL is no longer present in errors for any browsers we support
299
+ */
300
+ test('should show <inline> for same-page URLs', async () => {
301
+ const pageLocation = faker.internet.url()
302
+ const sourceURL = pageLocation + '?abc=123'
303
+ const mockError = browserErrorUtils.constructError({
304
+ ...baseMockError,
305
+ line: 100,
306
+ column: 200,
307
+ stack: undefined,
308
+ sourceURL: sourceURL
309
+ })
310
+
311
+ mockGlobalScopeLocation(pageLocation)
312
+ const { computeStackTrace } = await import('./compute-stack-trace')
313
+ const result = computeStackTrace(mockError)
314
+
315
+ expect(result).toEqual(expect.objectContaining({
316
+ stackString: `${mockError.name}: ${mockError.message}\n at <inline>:${mockError.line}:${mockError.column}`
317
+ }))
318
+ expect(result.frames).toContainEqual(expect.objectContaining({
319
+ url: '<inline>'
320
+ }))
321
+ })
322
+
323
+ /**
324
+ * @deprecated sourceURL is no longer present in errors for any browsers we support
325
+ */
326
+ test('should NOT show <inline> for same-domain URLs with a sub-path', async () => {
327
+ const pageLocation = faker.internet.url()
328
+ const sourceURL = pageLocation + '/path/to/script.js'
329
+ const mockError = browserErrorUtils.constructError({
330
+ ...baseMockError,
331
+ line: 100,
332
+ column: 200,
333
+ stack: undefined,
334
+ sourceURL
335
+ })
336
+
337
+ mockGlobalScopeLocation(pageLocation)
338
+ const { computeStackTrace } = await import('./compute-stack-trace')
339
+ const result = computeStackTrace(mockError)
340
+
341
+ expect(result).toEqual(expect.objectContaining({
342
+ stackString: `${mockError.name}: ${mockError.message}\n at ${sourceURL}:${mockError.line}:${mockError.column}`
343
+ }))
344
+ expect(result.frames).toContainEqual(expect.objectContaining({
345
+ url: sourceURL
346
+ }))
347
+ })
348
+
236
349
  // TODO: computeStackTraceBySourceAndLine does not respect firefox lineNumber and columnNumber properties when stack is empty
237
350
  })
238
351
 
@@ -241,12 +354,14 @@ describe('errors without stack property and with line property', () => {
241
354
  * error, including primitives.
242
355
  */
243
356
  describe('errors that are messages only or primitives', () => {
244
- test('parser should get error name from constructor', () => {
357
+ test('parser should get error name from constructor', async () => {
245
358
  const mockError = browserErrorUtils.constructError({
246
359
  toString: '0',
247
360
  constructor: 'function Number() { [native code] }'
248
361
  })
249
362
 
363
+ mockGlobalScopeLocation()
364
+ const { computeStackTrace } = await import('./compute-stack-trace')
250
365
  const result = computeStackTrace(mockError)
251
366
 
252
367
  expect(result).toEqual(expect.objectContaining({
@@ -257,13 +372,15 @@ describe('errors that are messages only or primitives', () => {
257
372
  }))
258
373
  })
259
374
 
260
- test('parser should get error name from name property', () => {
375
+ test('parser should get error name from name property', async () => {
261
376
  const mockError = browserErrorUtils.constructError({
262
377
  toString: '0',
263
378
  name: faker.datatype.uuid(),
264
379
  constructor: 'function Number() { [native code] }'
265
380
  })
266
381
 
382
+ mockGlobalScopeLocation()
383
+ const { computeStackTrace } = await import('./compute-stack-trace')
267
384
  const result = computeStackTrace(mockError)
268
385
 
269
386
  expect(result).toEqual(expect.objectContaining({
@@ -274,7 +391,7 @@ describe('errors that are messages only or primitives', () => {
274
391
  }))
275
392
  })
276
393
 
277
- test('parser should include the message property', () => {
394
+ test('parser should include the message property', async () => {
278
395
  const mockError = browserErrorUtils.constructError({
279
396
  toString: '0',
280
397
  name: faker.datatype.uuid(),
@@ -282,6 +399,8 @@ describe('errors that are messages only or primitives', () => {
282
399
  constructor: 'function Number() { [native code] }'
283
400
  })
284
401
 
402
+ mockGlobalScopeLocation()
403
+ const { computeStackTrace } = await import('./compute-stack-trace')
285
404
  const result = computeStackTrace(mockError)
286
405
 
287
406
  expect(result).toEqual(expect.objectContaining({
@@ -293,5 +412,3 @@ describe('errors that are messages only or primitives', () => {
293
412
  }))
294
413
  })
295
414
  })
296
-
297
- // describe('')
@@ -4,7 +4,6 @@
4
4
  */
5
5
 
6
6
  import { canonicalFunctionName } from './canonical-function-name'
7
- import { cleanURL } from '../../../common/url/clean-url'
8
7
  import { computeStackTrace } from './compute-stack-trace'
9
8
  import { stringHashCode } from './string-hash-code'
10
9
  import { truncateSize } from './format-stack-trace'
@@ -21,9 +20,13 @@ import { globalScope } from '../../../common/util/global-scope'
21
20
  import { FEATURE_NAME } from '../constants'
22
21
  import { drain } from '../../../common/drain/drain'
23
22
  import { FEATURE_NAMES } from '../../../loaders/features/features'
24
- import { FeatureBase } from '../../utils/feature-base'
23
+ import { AggregateBase } from '../../utils/aggregate-base'
25
24
 
26
- export class Aggregate extends FeatureBase {
25
+ /**
26
+ * @typedef {import('./compute-stack-trace.js').StackInfo} StackInfo
27
+ */
28
+
29
+ export class Aggregate extends AggregateBase {
27
30
  static featureName = FEATURE_NAME
28
31
  constructor (agentIdentifier, aggregator) {
29
32
  super(agentIdentifier, aggregator, FEATURE_NAME)
@@ -105,56 +108,27 @@ export class Aggregate extends FeatureBase {
105
108
  return this.nameHash(params) + ':' + stringHashCode(stringify(customParams))
106
109
  }
107
110
 
108
- canonicalizeURL (url, cleanedOrigin) {
109
- if (typeof url !== 'string') return ''
110
-
111
- var cleanedURL = cleanURL(url)
112
- if (cleanedURL === cleanedOrigin) {
113
- return '<inline>'
114
- } else {
115
- return cleanedURL
116
- }
117
- }
118
-
119
- buildCanonicalStackString (stackInfo, cleanedOrigin) {
120
- var canonicalStack = ''
111
+ /**
112
+ * Builds a standardized stack trace string from the frames in the given `stackInfo` object, with each frame separated
113
+ * by a newline character. Lines take the form `<functionName>@<url>:<lineNumber>`.
114
+ *
115
+ * @param {StackInfo} stackInfo - An object specifying a stack string and individual frames.
116
+ * @returns {string} A canonical stack string built from the URLs and function names in the given `stackInfo` object.
117
+ */
118
+ buildCanonicalStackString (stackInfo) {
119
+ var canonicalStackString = ''
121
120
 
122
121
  for (var i = 0; i < stackInfo.frames.length; i++) {
123
122
  var frame = stackInfo.frames[i]
124
123
  var func = canonicalFunctionName(frame.func)
125
124
 
126
- if (canonicalStack) canonicalStack += '\n'
127
- if (func) canonicalStack += func + '@'
128
- if (typeof frame.url === 'string') canonicalStack += frame.url
129
- if (frame.line) canonicalStack += ':' + frame.line
130
- }
131
-
132
- return canonicalStack
133
- }
134
-
135
- // Strip query parameters and fragments from the stackString property of the
136
- // given stackInfo, along with the 'url' properties of each frame in
137
- // stackInfo.frames.
138
- //
139
- // Any URLs that are equivalent to the cleaned version of the origin will also
140
- // be replaced with the string '<inline>'.
141
- //
142
- canonicalizeStackURLs (stackInfo) {
143
- // Currently, loader.origin might contain a fragment, but we don't want to use it
144
- // for comparing with frame URLs.
145
- var cleanedOrigin = cleanURL(getRuntime(this.agentIdentifier).origin)
146
-
147
- for (var i = 0; i < stackInfo.frames.length; i++) {
148
- var frame = stackInfo.frames[i]
149
- var originalURL = frame.url
150
- var cleanedURL = this.canonicalizeURL(originalURL, cleanedOrigin)
151
- if (cleanedURL && cleanedURL !== frame.url) {
152
- frame.url = cleanedURL
153
- stackInfo.stackString = stackInfo.stackString.split(originalURL).join(cleanedURL)
154
- }
125
+ if (canonicalStackString) canonicalStackString += '\n'
126
+ if (func) canonicalStackString += func + '@'
127
+ if (typeof frame.url === 'string') canonicalStackString += frame.url
128
+ if (frame.line) canonicalStackString += ':' + frame.line
155
129
  }
156
130
 
157
- return stackInfo
131
+ return canonicalStackString
158
132
  }
159
133
 
160
134
  storeError (err, time, internal, customAttributes) {
@@ -173,11 +147,11 @@ export class Aggregate extends FeatureBase {
173
147
  // Again as with previous usage, all falsey values would include the error.
174
148
  }
175
149
 
176
- var stackInfo = this.canonicalizeStackURLs(computeStackTrace(err))
177
- var canonicalStack = this.buildCanonicalStackString(stackInfo)
150
+ var stackInfo = computeStackTrace(err)
151
+ var canonicalStackString = this.buildCanonicalStackString(stackInfo)
178
152
 
179
153
  const params = {
180
- stackHash: stringHashCode(canonicalStack),
154
+ stackHash: stringHashCode(canonicalStackString),
181
155
  exceptionClass: stackInfo.name,
182
156
  request_uri: globalScope?.location.pathname
183
157
  }
@@ -215,10 +189,12 @@ export class Aggregate extends FeatureBase {
215
189
  var type = internal ? 'ierr' : 'err'
216
190
  var newMetrics = { time: time }
217
191
 
218
- // stn and spa aggregators listen to this event - stn sends the error in its payload,
192
+ // sr, stn and spa aggregators listen to this event - stn sends the error in its payload,
219
193
  // and spa annotates the error with interaction info
220
- handle('errorAgg', [type, bucketHash, params, newMetrics], undefined, FEATURE_NAMES.sessionTrace, this.ee)
221
- handle('errorAgg', [type, bucketHash, params, newMetrics], undefined, FEATURE_NAMES.spa, this.ee)
194
+ const msg = [type, bucketHash, params, newMetrics]
195
+ handle('errorAgg', msg, undefined, FEATURE_NAMES.sessionTrace, this.ee)
196
+ handle('errorAgg', msg, undefined, FEATURE_NAMES.spa, this.ee)
197
+ handle('errorAgg', msg, undefined, FEATURE_NAMES.sessionReplay, this.ee)
222
198
 
223
199
  // still send EE events for other features such as above, but stop this one from aggregating internal data
224
200
  if (this.blocked) return
@@ -7,7 +7,6 @@ import { handle } from '../../../common/event-emitter/handle'
7
7
  import { now } from '../../../common/timing/now'
8
8
  import { getOrSet } from '../../../common/util/get-or-set'
9
9
  import { wrapRaf, wrapTimer, wrapEvents, wrapXhr } from '../../../common/wrap'
10
- import slice from 'lodash._slice'
11
10
  import './debug'
12
11
  import { InstrumentBase } from '../../utils/instrument-base'
13
12
  import { FEATURE_NAME, NR_ERR_PROP } from '../constants'