@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.
- package/dist/cjs/cdn/polyfills.js +5 -2
- package/dist/cjs/common/config/state/configurable.js +15 -26
- package/dist/cjs/common/config/state/info.js +1 -1
- package/dist/cjs/common/config/state/init.js +101 -56
- package/dist/cjs/common/config/state/loader-config.js +1 -1
- package/dist/cjs/common/config/state/runtime.js +1 -5
- package/dist/cjs/common/constants/env.cdn.js +1 -1
- package/dist/cjs/common/constants/env.npm.js +1 -1
- package/dist/cjs/common/drain/drain.js +1 -1
- package/dist/cjs/common/harvest/harvest-scheduler.js +30 -10
- package/dist/cjs/common/harvest/harvest.js +119 -55
- package/dist/cjs/common/session/session-entity.js +35 -22
- package/dist/cjs/common/session/session-entity.test.js +73 -49
- package/dist/cjs/common/timer/interaction-timer.js +9 -12
- package/dist/cjs/common/url/canonicalize-url.js +32 -0
- package/dist/cjs/common/url/canonicalize-url.test.js +42 -0
- package/dist/cjs/common/url/clean-url.js +10 -3
- package/dist/cjs/common/url/protocol.test.js +0 -1
- package/dist/cjs/common/util/feature-flags.js +2 -1
- package/dist/cjs/common/util/global-scope.js +4 -2
- package/dist/cjs/common/util/submit-data.js +57 -18
- package/dist/cjs/common/wrap/wrap-fetch.js +1 -3
- package/dist/cjs/common/wrap/wrap-function.js +1 -3
- package/dist/cjs/common/wrap/wrap-promise.js +1 -1
- package/dist/cjs/features/ajax/aggregate/index.js +2 -2
- package/dist/cjs/features/ajax/instrument/index.js +1 -1
- package/dist/cjs/features/jserrors/aggregate/canonical-function-name.js +12 -4
- package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.js +93 -10
- package/dist/cjs/features/jserrors/aggregate/compute-stack-trace.test.js +164 -38
- package/dist/cjs/features/jserrors/aggregate/index.js +29 -48
- package/dist/cjs/features/jserrors/instrument/index.js +0 -2
- package/dist/cjs/features/metrics/aggregate/framework-detection.js +67 -0
- package/dist/cjs/features/metrics/aggregate/framework-detection.test.js +137 -0
- package/dist/cjs/features/metrics/aggregate/index.js +7 -3
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.js +14 -0
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.es5.test.js +17 -0
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.js +53 -0
- package/dist/cjs/features/metrics/aggregate/polyfill-detection.test.js +165 -0
- package/dist/cjs/features/page_action/aggregate/index.js +2 -2
- package/dist/cjs/features/page_view_event/aggregate/index.js +6 -3
- package/dist/cjs/features/page_view_timing/aggregate/index.js +2 -2
- package/dist/cjs/features/session_replay/aggregate/index.js +333 -0
- package/dist/cjs/features/session_replay/constants.js +9 -0
- package/dist/cjs/features/session_replay/index.js +12 -0
- package/dist/cjs/features/session_replay/instrument/index.js +29 -0
- package/dist/cjs/features/session_trace/aggregate/index.js +163 -164
- package/dist/cjs/features/session_trace/constants.js +2 -9
- package/dist/cjs/features/session_trace/instrument/index.js +24 -66
- package/dist/cjs/features/spa/aggregate/index.js +2 -2
- package/dist/cjs/features/utils/agent-session.js +1 -2
- package/dist/cjs/features/utils/aggregate-base.js +64 -0
- package/dist/cjs/features/utils/feature-base.js +0 -31
- package/dist/cjs/features/utils/handler-cache.js +3 -4
- package/dist/cjs/features/utils/instrument-base.js +42 -10
- package/dist/cjs/features/utils/{lazy-loader.js → lazy-feature-loader.js} +4 -2
- package/dist/cjs/loaders/agent.js +1 -1
- package/dist/cjs/loaders/api/apiAsync.js +3 -1
- package/dist/cjs/loaders/configure/configure.js +3 -3
- package/dist/cjs/loaders/features/featureDependencies.js +0 -12
- package/dist/cjs/loaders/features/features.js +3 -1
- package/dist/cjs/loaders/micro-agent.js +6 -6
- package/dist/esm/cdn/polyfills.js +5 -2
- package/dist/esm/common/config/state/configurable.js +14 -24
- package/dist/esm/common/config/state/info.js +2 -2
- package/dist/esm/common/config/state/init.js +102 -57
- package/dist/esm/common/config/state/loader-config.js +2 -2
- package/dist/esm/common/config/state/runtime.js +2 -4
- package/dist/esm/common/constants/env.cdn.js +1 -1
- package/dist/esm/common/constants/env.npm.js +1 -1
- package/dist/esm/common/drain/drain.js +1 -1
- package/dist/esm/common/harvest/harvest-scheduler.js +30 -10
- package/dist/esm/common/harvest/harvest.js +121 -56
- package/dist/esm/common/session/session-entity.js +35 -22
- package/dist/esm/common/session/session-entity.test.js +73 -49
- package/dist/esm/common/timer/interaction-timer.js +9 -12
- package/dist/esm/common/url/canonicalize-url.js +27 -0
- package/dist/esm/common/url/canonicalize-url.test.js +38 -0
- package/dist/esm/common/url/clean-url.js +10 -3
- package/dist/esm/common/url/protocol.test.js +0 -1
- package/dist/esm/common/util/feature-flags.js +2 -1
- package/dist/esm/common/util/global-scope.js +1 -0
- package/dist/esm/common/util/submit-data.js +57 -18
- package/dist/esm/common/wrap/wrap-fetch.js +1 -2
- package/dist/esm/common/wrap/wrap-function.js +1 -2
- package/dist/esm/common/wrap/wrap-promise.js +1 -1
- package/dist/esm/features/ajax/aggregate/index.js +2 -2
- package/dist/esm/features/ajax/instrument/index.js +1 -1
- package/dist/esm/features/jserrors/aggregate/canonical-function-name.js +12 -4
- package/dist/esm/features/jserrors/aggregate/compute-stack-trace.js +93 -10
- package/dist/esm/features/jserrors/aggregate/compute-stack-trace.test.js +149 -25
- package/dist/esm/features/jserrors/aggregate/index.js +30 -48
- package/dist/esm/features/jserrors/instrument/index.js +0 -1
- package/dist/esm/features/metrics/aggregate/framework-detection.js +61 -0
- package/dist/esm/features/metrics/aggregate/framework-detection.test.js +133 -0
- package/dist/esm/features/metrics/aggregate/index.js +7 -3
- package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.js +8 -0
- package/dist/esm/features/metrics/aggregate/polyfill-detection.es5.test.js +15 -0
- package/dist/esm/features/metrics/aggregate/polyfill-detection.js +47 -0
- package/dist/esm/features/metrics/aggregate/polyfill-detection.test.js +163 -0
- package/dist/esm/features/page_action/aggregate/index.js +2 -2
- package/dist/esm/features/page_view_event/aggregate/index.js +6 -3
- package/dist/esm/features/page_view_timing/aggregate/index.js +2 -2
- package/dist/esm/features/session_replay/aggregate/index.js +327 -0
- package/dist/esm/features/session_replay/constants.js +2 -0
- package/dist/esm/features/session_replay/index.js +12 -0
- package/dist/esm/features/session_replay/instrument/index.js +21 -0
- package/dist/esm/features/session_trace/aggregate/index.js +163 -163
- package/dist/esm/features/session_trace/constants.js +1 -5
- package/dist/esm/features/session_trace/instrument/index.js +24 -66
- package/dist/esm/features/spa/aggregate/index.js +2 -2
- package/dist/esm/features/utils/agent-session.js +1 -2
- package/dist/esm/features/utils/aggregate-base.js +57 -0
- package/dist/esm/features/utils/feature-base.js +1 -32
- package/dist/esm/features/utils/handler-cache.js +3 -4
- package/dist/esm/features/utils/instrument-base.js +42 -10
- package/dist/esm/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
- package/dist/esm/loaders/agent.js +1 -1
- package/dist/esm/loaders/api/apiAsync.js +3 -1
- package/dist/esm/loaders/configure/configure.js +3 -3
- package/dist/esm/loaders/features/featureDependencies.js +0 -11
- package/dist/esm/loaders/features/features.js +3 -1
- package/dist/esm/loaders/micro-agent.js +6 -6
- package/dist/types/common/config/state/configurable.d.ts +1 -3
- package/dist/types/common/config/state/configurable.d.ts.map +1 -1
- package/dist/types/common/config/state/init.d.ts.map +1 -1
- package/dist/types/common/config/state/runtime.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest-scheduler.d.ts.map +1 -1
- package/dist/types/common/harvest/harvest.d.ts +37 -34
- package/dist/types/common/harvest/harvest.d.ts.map +1 -1
- package/dist/types/common/session/session-entity.d.ts +6 -3
- package/dist/types/common/session/session-entity.d.ts.map +1 -1
- package/dist/types/common/timer/interaction-timer.d.ts +2 -1
- package/dist/types/common/timer/interaction-timer.d.ts.map +1 -1
- package/dist/types/common/url/canonicalize-url.d.ts +9 -0
- package/dist/types/common/url/canonicalize-url.d.ts.map +1 -0
- package/dist/types/common/url/clean-url.d.ts +7 -1
- package/dist/types/common/url/clean-url.d.ts.map +1 -1
- package/dist/types/common/util/feature-flags.d.ts.map +1 -1
- package/dist/types/common/util/global-scope.d.ts +1 -0
- package/dist/types/common/util/global-scope.d.ts.map +1 -1
- package/dist/types/common/util/submit-data.d.ts +40 -14
- package/dist/types/common/util/submit-data.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-fetch.d.ts.map +1 -1
- package/dist/types/common/wrap/wrap-function.d.ts.map +1 -1
- package/dist/types/features/ajax/aggregate/index.d.ts +2 -2
- package/dist/types/features/ajax/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts +8 -1
- package/dist/types/features/jserrors/aggregate/canonical-function-name.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts +48 -19
- package/dist/types/features/jserrors/aggregate/compute-stack-trace.d.ts.map +1 -1
- package/dist/types/features/jserrors/aggregate/index.d.ts +14 -5
- package/dist/types/features/jserrors/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/jserrors/instrument/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/framework-detection.d.ts.map +1 -0
- package/dist/types/features/metrics/aggregate/index.d.ts +2 -2
- package/dist/types/features/metrics/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts +6 -0
- package/dist/types/features/metrics/aggregate/polyfill-detection.d.ts.map +1 -0
- package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts +7 -0
- package/dist/types/features/metrics/aggregate/polyfill-detection.es5.d.ts.map +1 -0
- package/dist/types/features/page_action/aggregate/index.d.ts +3 -3
- package/dist/types/features/page_action/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_event/aggregate/index.d.ts +2 -2
- package/dist/types/features/page_view_event/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/page_view_timing/aggregate/index.d.ts +2 -2
- package/dist/types/features/page_view_timing/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_replay/aggregate/index.d.ts +96 -0
- package/dist/types/features/session_replay/aggregate/index.d.ts.map +1 -0
- package/dist/types/features/session_replay/constants.d.ts +2 -0
- package/dist/types/features/session_replay/constants.d.ts.map +1 -0
- package/dist/types/features/session_replay/index.d.ts +2 -0
- package/dist/types/features/session_replay/index.d.ts.map +1 -0
- package/dist/types/features/session_replay/instrument/index.d.ts +6 -0
- package/dist/types/features/session_replay/instrument/index.d.ts.map +1 -0
- package/dist/types/features/session_trace/aggregate/index.d.ts +8 -57
- package/dist/types/features/session_trace/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/session_trace/constants.d.ts +0 -3
- package/dist/types/features/session_trace/constants.d.ts.map +1 -1
- package/dist/types/features/session_trace/instrument/index.d.ts +1 -3
- package/dist/types/features/session_trace/instrument/index.d.ts.map +1 -1
- package/dist/types/features/spa/aggregate/index.d.ts +2 -2
- package/dist/types/features/spa/aggregate/index.d.ts.map +1 -1
- package/dist/types/features/utils/agent-session.d.ts.map +1 -1
- package/dist/types/features/utils/aggregate-base.d.ts +11 -0
- package/dist/types/features/utils/aggregate-base.d.ts.map +1 -0
- package/dist/types/features/utils/feature-base.d.ts +0 -5
- package/dist/types/features/utils/feature-base.d.ts.map +1 -1
- package/dist/types/features/utils/handler-cache.d.ts.map +1 -1
- package/dist/types/features/utils/instrument-base.d.ts +3 -1
- package/dist/types/features/utils/instrument-base.d.ts.map +1 -1
- package/dist/types/features/utils/{lazy-loader.d.ts → lazy-feature-loader.d.ts} +2 -2
- package/dist/types/features/utils/lazy-feature-loader.d.ts.map +1 -0
- package/dist/types/loaders/configure/configure.d.ts.map +1 -1
- package/dist/types/loaders/features/featureDependencies.d.ts +0 -1
- package/dist/types/loaders/features/featureDependencies.d.ts.map +1 -1
- package/dist/types/loaders/features/features.d.ts +1 -0
- package/dist/types/loaders/features/features.d.ts.map +1 -1
- package/package.json +31 -22
- package/src/cdn/polyfills.js +4 -1
- package/src/common/config/state/configurable.js +18 -24
- package/src/common/config/state/info.js +2 -2
- package/src/common/config/state/init.js +62 -28
- package/src/common/config/state/loader-config.js +2 -2
- package/src/common/config/state/runtime.js +2 -4
- package/src/common/drain/drain.js +1 -1
- package/src/common/harvest/harvest-scheduler.js +35 -10
- package/src/common/harvest/harvest.js +73 -50
- package/src/common/session/session-entity.js +34 -23
- package/src/common/session/session-entity.test.js +57 -51
- package/src/common/timer/interaction-timer.js +9 -12
- package/src/common/url/canonicalize-url.js +28 -0
- package/src/common/url/canonicalize-url.test.js +34 -0
- package/src/common/url/clean-url.js +10 -3
- package/src/common/url/protocol.test.js +0 -1
- package/src/common/util/feature-flags.js +2 -2
- package/src/common/util/global-scope.js +2 -0
- package/src/common/util/submit-data.js +28 -17
- package/src/common/wrap/wrap-fetch.js +1 -2
- package/src/common/wrap/wrap-function.js +1 -2
- package/src/common/wrap/wrap-promise.js +1 -1
- package/src/features/ajax/aggregate/index.js +2 -2
- package/src/features/ajax/instrument/index.js +1 -1
- package/src/features/jserrors/aggregate/canonical-function-name.js +12 -4
- package/src/features/jserrors/aggregate/compute-stack-trace.js +85 -11
- package/src/features/jserrors/aggregate/compute-stack-trace.test.js +141 -24
- package/src/features/jserrors/aggregate/index.js +28 -52
- package/src/features/jserrors/instrument/index.js +0 -1
- package/src/features/metrics/aggregate/framework-detection.js +73 -0
- package/src/features/metrics/aggregate/framework-detection.test.js +201 -0
- package/src/features/metrics/aggregate/index.js +8 -3
- package/src/features/metrics/aggregate/polyfill-detection.es5.js +9 -0
- package/src/features/metrics/aggregate/polyfill-detection.es5.test.js +16 -0
- package/src/features/metrics/aggregate/polyfill-detection.js +48 -0
- package/src/features/metrics/aggregate/polyfill-detection.test.js +163 -0
- package/src/features/page_action/aggregate/index.js +2 -2
- package/src/features/page_view_event/aggregate/index.js +5 -5
- package/src/features/page_view_timing/aggregate/index.js +2 -2
- package/src/features/session_replay/aggregate/index.js +314 -0
- package/src/features/session_replay/constants.js +3 -0
- package/src/features/session_replay/index.js +12 -0
- package/src/features/session_replay/instrument/index.js +22 -0
- package/src/features/session_trace/aggregate/index.js +148 -188
- package/src/features/session_trace/constants.js +0 -4
- package/src/features/session_trace/instrument/index.js +17 -69
- package/src/features/spa/aggregate/index.js +2 -2
- package/src/features/utils/agent-session.js +1 -2
- package/src/features/utils/aggregate-base.js +51 -0
- package/src/features/utils/feature-base.js +1 -31
- package/src/features/utils/handler-cache.js +3 -4
- package/src/features/utils/instrument-base.js +40 -8
- package/src/features/utils/{lazy-loader.js → lazy-feature-loader.js} +3 -1
- package/src/loaders/agent.js +1 -1
- package/src/loaders/api/apiAsync.js +1 -1
- package/src/loaders/configure/configure.js +4 -3
- package/src/loaders/features/featureDependencies.js +0 -12
- package/src/loaders/features/features.js +3 -1
- package/src/loaders/micro-agent.js +4 -4
- package/dist/cjs/common/metrics/framework-detection.js +0 -72
- package/dist/cjs/common/util/user-agent.js +0 -57
- package/dist/cjs/common/window/supports-performance-observer.js +0 -15
- package/dist/esm/common/metrics/framework-detection.js +0 -66
- package/dist/esm/common/util/user-agent.js +0 -48
- package/dist/esm/common/window/supports-performance-observer.js +0 -9
- package/dist/types/common/metrics/framework-detection.d.ts.map +0 -1
- package/dist/types/common/util/user-agent.d.ts +0 -5
- package/dist/types/common/util/user-agent.d.ts.map +0 -1
- package/dist/types/common/window/supports-performance-observer.d.ts +0 -2
- package/dist/types/common/window/supports-performance-observer.d.ts.map +0 -1
- package/dist/types/features/utils/lazy-loader.d.ts.map +0 -1
- package/src/common/metrics/framework-detection.js +0 -71
- package/src/common/util/user-agent.js +0 -56
- package/src/common/window/supports-performance-observer.js +0 -10
- /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
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
148
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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('
|
|
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 (
|
|
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
|
-
|
|
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:
|
|
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 (
|
|
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 {
|
|
23
|
+
import { AggregateBase } from '../../utils/aggregate-base'
|
|
25
24
|
|
|
26
|
-
|
|
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
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
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 (
|
|
127
|
-
if (func)
|
|
128
|
-
if (typeof frame.url === 'string')
|
|
129
|
-
if (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
|
|
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 =
|
|
177
|
-
var
|
|
150
|
+
var stackInfo = computeStackTrace(err)
|
|
151
|
+
var canonicalStackString = this.buildCanonicalStackString(stackInfo)
|
|
178
152
|
|
|
179
153
|
const params = {
|
|
180
|
-
stackHash: stringHashCode(
|
|
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
|
-
|
|
221
|
-
handle('errorAgg',
|
|
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'
|