11import { captureException , flush , getCurrentHub , Handlers , startTransaction , withScope } from '@sentry/node' ;
22import { extractTraceparentData , getActiveTransaction , hasTracingEnabled } from '@sentry/tracing' ;
33import { addExceptionMechanism , isString , logger , stripUrlQueryAndFragment } from '@sentry/utils' ;
4- import { NextApiHandler } from 'next' ;
4+ import { NextApiHandler , NextApiResponse } from 'next' ;
55
66import { addRequestDataToEvent , NextRequest } from './instrumentServer' ;
77
@@ -51,6 +51,8 @@ export const withSentry = (handler: NextApiHandler): WrappedNextApiHandler => {
5151 { request : req } ,
5252 ) ;
5353 currentScope . setSpan ( transaction ) ;
54+
55+ res . on ( 'finish' , async ( ) => await finishTransaction ( res ) ) ;
5456 }
5557 }
5658
@@ -65,19 +67,44 @@ export const withSentry = (handler: NextApiHandler): WrappedNextApiHandler => {
6567 } ) ;
6668 captureException ( e ) ;
6769 } ) ;
70+ await finishTransaction ( res ) ;
6871 throw e ;
69- } finally {
70- const transaction = getActiveTransaction ( ) ;
71- if ( transaction ) {
72- transaction . setHttpStatus ( res . statusCode ) ;
72+ }
73+ } ;
74+ } ;
7375
74- transaction . finish ( ) ;
75- }
76+ async function finishTransaction ( res : NextApiResponse ) : Promise < void > {
77+ const transaction = getActiveTransaction ( ) ;
78+
79+ if ( ! transaction ) {
80+ // nothing to do
81+ return Promise . resolve ( ) ;
82+ }
83+
84+ // now that we have the transaction, pop it off of the scope so it doesn't affect future requests
85+ // TODO use domains?
86+ getCurrentHub ( )
87+ . getScope ( )
88+ ?. setSpan ( undefined ) ;
89+
90+ transaction . setHttpStatus ( res . statusCode ) ;
91+
92+ const finishPromise = new Promise < void > ( ( resolve , reject ) => {
93+ // Push `transaction.finish` to the next event loop so open spans have a chance to finish before the
94+ // transaction closes
95+ setImmediate ( async ( ) => {
96+ transaction . finish ( ) ;
7697 try {
98+ logger . log ( 'Flushing event buffer' ) ;
7799 await flush ( 2000 ) ;
78- } catch ( e ) {
79- // no-empty
100+ logger . log ( 'Buffer flushed' ) ;
101+ resolve ( ) ;
102+ } catch ( err ) {
103+ logger . log ( 'Error while flushing buffer:' , err ) ;
104+ reject ( err ) ;
80105 }
81- }
82- } ;
83- } ;
106+ } ) ;
107+ } ) ;
108+
109+ return finishPromise ;
110+ }
0 commit comments