11import { Backend , logger , Options , SentryError } from '@sentry/core' ;
2- import { SentryEvent , SentryResponse , Status } from '@sentry/types' ;
2+ import { SentryEvent , SentryEventHint , SentryResponse , Severity , Status , Transport } from '@sentry/types' ;
33import { isDOMError , isDOMException , isError , isErrorEvent , isPlainObject } from '@sentry/utils/is' ;
4- import { supportsFetch } from '@sentry/utils/supports' ;
4+ import { supportsBeacon , supportsFetch } from '@sentry/utils/supports' ;
55import { eventFromPlainObject , eventFromStacktrace , prepareFramesForEvent } from './parsers' ;
66import { computeStackTrace } from './tracekit' ;
7- import { FetchTransport , XHRTransport } from './transports' ;
7+ import { BeaconTransport , FetchTransport , XHRTransport } from './transports' ;
88
99/**
1010 * Configuration options for the Sentry Browser SDK.
@@ -37,6 +37,9 @@ export class BrowserBackend implements Backend {
3737 /** Creates a new browser backend instance. */
3838 public constructor ( private readonly options : BrowserOptions = { } ) { }
3939
40+ /** Cached transport used internally. */
41+ private transport ?: Transport ;
42+
4043 /**
4144 * @inheritDoc
4245 */
@@ -57,7 +60,7 @@ export class BrowserBackend implements Backend {
5760 /**
5861 * @inheritDoc
5962 */
60- public async eventFromException ( exception : any , syntheticException : Error | null ) : Promise < SentryEvent > {
63+ public async eventFromException ( exception : any , hint ?: SentryEventHint ) : Promise < SentryEvent > {
6164 let event ;
6265
6366 if ( isErrorEvent ( exception as ErrorEvent ) && ( exception as ErrorEvent ) . error ) {
@@ -74,16 +77,16 @@ export class BrowserBackend implements Backend {
7477 const name = ex . name || ( isDOMError ( ex ) ? 'DOMError' : 'DOMException' ) ;
7578 const message = ex . message ? `${ name } : ${ ex . message } ` : name ;
7679
77- event = await this . eventFromMessage ( message , syntheticException ) ;
80+ event = await this . eventFromMessage ( message , undefined , hint ) ;
7881 } else if ( isError ( exception as Error ) ) {
7982 // we have a real Error object, do nothing
8083 event = eventFromStacktrace ( computeStackTrace ( exception as Error ) ) ;
81- } else if ( isPlainObject ( exception as { } ) ) {
84+ } else if ( isPlainObject ( exception as { } ) && hint && hint . syntheticException ) {
8285 // If it is plain Object, serialize it manually and extract options
8386 // This will allow us to group events based on top-level keys
8487 // which is much better than creating new group when any key/value change
8588 const ex = exception as { } ;
86- event = eventFromPlainObject ( ex , syntheticException ) ;
89+ event = eventFromPlainObject ( ex , hint . syntheticException ) ;
8790 } else {
8891 // If none of previous checks were valid, then it means that
8992 // it's not a DOMError/DOMException
@@ -92,11 +95,12 @@ export class BrowserBackend implements Backend {
9295 // it's not an Error
9396 // So bail out and capture it as a simple message:
9497 const ex = exception as string ;
95- event = await this . eventFromMessage ( ex , syntheticException ) ;
98+ event = await this . eventFromMessage ( ex , undefined , hint ) ;
9699 }
97100
98101 event = {
99102 ...event ,
103+ event_id : hint && hint . event_id ,
100104 exception : {
101105 ...event . exception ,
102106 mechanism : {
@@ -112,14 +116,16 @@ export class BrowserBackend implements Backend {
112116 /**
113117 * @inheritDoc
114118 */
115- public async eventFromMessage ( message : string , syntheticException : Error | null ) : Promise < SentryEvent > {
119+ public async eventFromMessage ( message : string , level ?: Severity , hint ?: SentryEventHint ) : Promise < SentryEvent > {
116120 const event : SentryEvent = {
121+ event_id : hint && hint . event_id ,
117122 fingerprint : [ message ] ,
123+ level,
118124 message,
119125 } ;
120126
121- if ( this . options . attachStacktrace && syntheticException ) {
122- const stacktrace = computeStackTrace ( syntheticException ) ;
127+ if ( this . options . attachStacktrace && hint && hint . syntheticException ) {
128+ const stacktrace = computeStackTrace ( hint . syntheticException ) ;
123129 const frames = prepareFramesForEvent ( stacktrace . stack ) ;
124130 event . stacktrace = {
125131 frames,
@@ -139,15 +145,23 @@ export class BrowserBackend implements Backend {
139145 return { status : Status . Skipped } ;
140146 }
141147
142- const transportOptions = this . options . transportOptions ? this . options . transportOptions : { dsn : this . options . dsn } ;
143-
144- const transport = this . options . transport
145- ? new this . options . transport ( { dsn : this . options . dsn } )
146- : supportsFetch ( )
147- ? new FetchTransport ( transportOptions )
148- : new XHRTransport ( transportOptions ) ;
148+ if ( ! this . transport ) {
149+ const transportOptions = this . options . transportOptions
150+ ? this . options . transportOptions
151+ : { dsn : this . options . dsn } ;
152+
153+ if ( this . options . transport ) {
154+ this . transport = new this . options . transport ( { dsn : this . options . dsn } ) ;
155+ } else if ( supportsBeacon ( ) ) {
156+ this . transport = new BeaconTransport ( transportOptions ) ;
157+ } else if ( supportsFetch ( ) ) {
158+ this . transport = new FetchTransport ( transportOptions ) ;
159+ } else {
160+ this . transport = new XHRTransport ( transportOptions ) ;
161+ }
162+ }
149163
150- return transport . send ( event ) ;
164+ return this . transport . send ( event ) ;
151165 }
152166
153167 /**
0 commit comments