1
1
import { captureException , flush , getCurrentHub , Handlers , startTransaction } from '@sentry/node' ;
2
2
import { extractTraceparentData , hasTracingEnabled } from '@sentry/tracing' ;
3
3
import { Transaction } from '@sentry/types' ;
4
- import { addExceptionMechanism , isString , logger , stripUrlQueryAndFragment } from '@sentry/utils' ;
4
+ import { addExceptionMechanism , isString , logger , objectify , stripUrlQueryAndFragment } from '@sentry/utils' ;
5
5
import * as domain from 'domain' ;
6
6
import { NextApiHandler , NextApiResponse } from 'next' ;
7
7
@@ -76,6 +76,12 @@ export const withSentry = (handler: NextApiHandler): WrappedNextApiHandler => {
76
76
try {
77
77
return await handler ( req , res ) ; // Call original handler
78
78
} catch ( e ) {
79
+ // In case we have a primitive, wrap it in the equivalent wrapper class (string -> String, etc.) so that we can
80
+ // store a seen flag on it. (Because of the one-way-on-Vercel-one-way-off-of-Vercel approach we've been forced
81
+ // to take, it can happen that the same thrown object gets caught in two different ways, and flagging it is a
82
+ // way to prevent it from actually being reported twice.)
83
+ const objectifiedErr = objectify ( e ) ;
84
+
79
85
if ( currentScope ) {
80
86
currentScope . addEventProcessor ( event => {
81
87
addExceptionMechanism ( event , {
@@ -84,9 +90,14 @@ export const withSentry = (handler: NextApiHandler): WrappedNextApiHandler => {
84
90
} ) ;
85
91
return event ;
86
92
} ) ;
87
- captureException ( e ) ;
93
+
94
+ captureException ( objectifiedErr ) ;
88
95
}
89
- throw e ;
96
+
97
+ // We rethrow here so that nextjs can do with the error whatever it would normally do. (Sometimes "whatever it
98
+ // would normally do" is to allow the error to bubble up to the global handlers - another reason we need to mark
99
+ // the error as already having been captured.)
100
+ throw objectifiedErr ;
90
101
}
91
102
} ) ;
92
103
0 commit comments