import { getCurrentHub , Scope } from '@sentry/core' ; import { Integration } from '@sentry/types' ; import { logger } from '@sentry/utils' ; import { NodeClient } from '../client' ; import { logAndExitProcess } from './utils/errorhandling' ; type OnFatalErrorHandler = ( firstError : Error , secondError ? : Error ) => void ; /** Global Promise Rejection handler */ export class OnUncaughtException implements Integration { inheritDoc public static id : string = 'OnUncaughtException' ; inheritDoc public name : string = OnUncaughtException . id ; inheritDoc public readonly handler : ( error : Error ) => void = this . _makeErrorHandler ( ) ; inheritDoc public constructor ( private readonly _options = { } ) { } inheritDoc public setupOnce ( ) { global . process . on ( 'uncaughtException' , this . handler . bind ( this ) ) ; } hidden private _makeErrorHandler ( ) { const timeout = 2000 ; let caughtFirstError = false ; let caughtSecondError = false ; let calledFatalError = false ; let firstError ; return ( error ) : void => { let onFatalError = logAndExitProcess ; const client = getCurrentHub ( ) . getClient < NodeClient > ( ) ; if ( this . _options . onFatalError ) { onFatalError = this . _options . onFatalError ; } else if ( client && client . getOptions ( ) . onFatalError ) { onFatalError = client . getOptions ( ) . onFatalError as OnFatalErrorHandler ; } if ( ! caughtFirstError ) { const hub = getCurrentHub ( ) ; firstError = error ; caughtFirstError = true ; if ( hub . getIntegration ( OnUncaughtException ) ) { hub . withScope ( ( scope ) => { scope . setLevel ( 'fatal' ) ; hub . captureException ( error , { originalException : error , data : { mechanism : { handled : false , type : 'onuncaughtexception' } } , } ) ; if ( ! calledFatalError ) { calledFatalError = true ; onFatalError ( error ) ; } } ) ; } else { if ( ! calledFatalError ) { calledFatalError = true ; onFatalError ( error ) ; } } } else if ( calledFatalError ) { logger . warn ( 'uncaught exception after calling fatal error shutdown callback - this is bad! forcing shutdown' ) ; logAndExitProcess ( error ) ; } else if ( ! caughtSecondError ) { caughtSecondError = true ; setTimeout ( ( ) => { if ( ! calledFatalError ) { calledFatalError = true ; onFatalError ( firstError , error ) ; } else { } } , timeout ) ; } } ; } }