8000 add function to track whether an exception has been seen · andreialecu/sentry-javascript@c8ccec8 · GitHub
[go: up one dir, main page]

10000
Skip to content

Commit c8ccec8

Browse files
committed
add function to track whether an exception has been seen
1 parent 84a6dc0 commit c8ccec8

File tree

1 file changed

+38
-0
lines changed

1 file changed

+38
-0
lines changed

packages/utils/src/misc.ts

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Event, StackFrame } from '@sentry/types';
33

44
import { getGlobalObject } from './global';
5+
import { logger } from './logger';
56
import { snipLine } from './string';
67

78
/**
@@ -241,3 +242,40 @@ export function stripUrlQueryAndFragment(urlPath: string): string {
241242
// eslint-disable-next-line no-useless-escape
242243
return urlPath.split(/[\?#]/, 1)[0];
243244
}
245+
246+
/**
247+
* Checks whether or not we've already captured the given exception (note: not an identical exception - the very object
248+
* in question), and marks it captured if not.
249+
*
250+
* Sometimes an error gets captured by more than one mechanism. (This happens, for example, in frameworks where we
251+
* intercept thrown errors, capture them, and then rethrow them so that the framework can handle them however it
252+
* normally would, which may or may not lead to them being caught again by something like the global error handler.)
253+
* This prevents us from actually recording it twice.
254+
*
255+
* Note: It will ignore primitives, as properties can't be set on them. {@link: Object.objectify} can be used on
256+
* exceptions to convert any that are primitives into their equivalent object wrapper forms so that this check will
257+
* always work. However, because we need to flag the exact object which will get rethrown, and because that rethrowing
258+
* happens outside of the event processing pipeline, the objectification must be done before the exception captured.
259+
*
260+
* @param A thrown exception to check or flag as having been seen
261+
* @returns `true` if the exception has already been captured, `false` if not (with the side effect of marking it seen)
262+
*/
263+
export function checkOrSetAlreadyCaught(exception: unknown): boolean {
264+
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
265+
if ((exception as any)?.__sentry_captured__) {
266+
logger.log("Not capturing exception because it's already been captured.");
267+
return true;
268+
}
269+
270+
try {
271+
// set it this way rather than by assignment so that it's not ennumerable and therefore isn't recorded by the
272+
// `ExtraErrorData` integration
273+
Object.defineProperty(exception, '__sentry_captured__', {
274+
value: true,
275+
});
276+
} catch (err) {
277+
// `exception` is a primitive, so we can't mark it seen
278+
}
279+
280+
return false;
281+
}

0 commit comments

Comments
 (0)
0