diff --git a/packages/browser-utils/src/instrument/xhr.ts b/packages/browser-utils/src/instrument/xhr.ts index f46ecd67b0b6..b85a27e923f8 100644 --- a/packages/browser-utils/src/instrument/xhr.ts +++ b/packages/browser-utils/src/instrument/xhr.ts @@ -82,7 +82,7 @@ export function instrumentXHR(): void { endTimestamp: timestampInSeconds() * 1000, startTimestamp, xhr: xhrOpenThisArg, - stack: virtualError.stack, + error: virtualError, }; triggerHandlers('xhr', handlerData); } diff --git a/packages/browser/src/integrations/httpclient.ts b/packages/browser/src/integrations/httpclient.ts index 15c8b3412963..f3d865c3bfbd 100644 --- a/packages/browser/src/integrations/httpclient.ts +++ b/packages/browser/src/integrations/httpclient.ts @@ -70,7 +70,7 @@ function _fetchResponseHandler( requestInfo: RequestInfo, response: Response, requestInit?: RequestInit, - stack?: string, + error?: unknown, ): void { if (_shouldCaptureResponse(options, response.status, response.url)) { const request = _getRequest(requestInfo, requestInit); @@ -90,7 +90,7 @@ function _fetchResponseHandler( responseHeaders, requestCookies, responseCookies, - stacktrace: stack, + error, }); captureEvent(event); @@ -129,7 +129,7 @@ function _xhrResponseHandler( xhr: XMLHttpRequest, method: string, headers: Record, - stack?: string, + error?: unknown, ): void { if (_shouldCaptureResponse(options, xhr.status, xhr.responseURL)) { let requestHeaders, responseCookies, responseHeaders; @@ -162,7 +162,7 @@ function _xhrResponseHandler( // Can't access request cookies from XHR responseHeaders, responseCookies, - stacktrace: stack, + error, }); captureEvent(event); @@ -292,14 +292,14 @@ function _wrapFetch(client: Client, options: HttpClientOptions): void { return; } - const { response, args } = handlerData; + const { response, args, error } = handlerData; const [requestInfo, requestInit] = args as [RequestInfo, RequestInit | undefined]; if (!response) { return; } - _fetchResponseHandler(options, requestInfo, response as Response, requestInit, handlerData.stack); + _fetchResponseHandler(options, requestInfo, response as Response, requestInit, error); }, false); } @@ -327,7 +327,7 @@ function _wrapXHR(client: Client, options: HttpClientOptions): void { const { method, request_headers: headers } = sentryXhrData; try { - _xhrResponseHandler(options, xhr, method, headers, handlerData.stack); + _xhrResponseHandler(options, xhr, method, headers, handlerData.error); } catch (e) { DEBUG_BUILD && logger.warn('Error while extracting response event form XHR response', e); } @@ -362,13 +362,12 @@ function _createEvent(data: { responseCookies?: Record; requestHeaders?: Record; requestCookies?: Record; - stacktrace?: string; + error?: unknown; }): SentryEvent { const client = getClient(); - const virtualStackTrace = client && data.stacktrace ? data.stacktrace : undefined; + const virtualStackTrace = client && data.error && data.error instanceof Error ? data.error.stack : undefined; // Remove the first frame from the stack as it's the HttpClient call const stack = virtualStackTrace && client ? client.getOptions().stackParser(virtualStackTrace, 0, 1) : undefined; - const message = `HTTP Client Error with status code: ${data.status}`; const event: SentryEvent = { diff --git a/packages/core/src/types-hoist/instrument.ts b/packages/core/src/types-hoist/instrument.ts index f779b2096597..f472a663c5d5 100644 --- a/packages/core/src/types-hoist/instrument.ts +++ b/packages/core/src/types-hoist/instrument.ts @@ -32,7 +32,7 @@ export interface HandlerDataXhr { xhr: SentryWrappedXMLHttpRequest; startTimestamp?: number; endTimestamp?: number; - stack?: string; + error?: unknown; } interface SentryFetchData { @@ -57,7 +57,6 @@ export interface HandlerDataFetch { headers: WebFetchHeaders; }; error?: unknown; - stack?: string; } export interface HandlerDataDom { diff --git a/packages/core/src/utils-hoist/instrument/fetch.ts b/packages/core/src/utils-hoist/instrument/fetch.ts index c822066a7c2d..4c21006b829e 100644 --- a/packages/core/src/utils-hoist/instrument/fetch.ts +++ b/packages/core/src/utils-hoist/instrument/fetch.ts @@ -48,7 +48,7 @@ function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNat fill(GLOBAL_OBJ, 'fetch', function (originalFetch: () => void): () => void { return function (...args: any[]): void { - // We capture the stack right here and not in the Promise error callback because Safari (and probably other + // We capture the error right here and not in the Promise error callback because Safari (and probably other // browsers too) will wipe the stack trace up to this point, only leaving us with this file which is useless. // NOTE: If you are a Sentry user, and you are seeing this stack frame, @@ -56,7 +56,6 @@ function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNat // have a stack trace, so the SDK backfilled the stack trace so // you can see which fetch call failed. const virtualError = new Error(); - const virtualStackTrace = virtualError.stack; const { method, url } = parseFetchArgs(args); const handlerData: HandlerDataFetch = { @@ -66,7 +65,8 @@ function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNat url, }, startTimestamp: timestampInSeconds() * 1000, - stack: virtualStackTrace, + // // Adding the error to be able to fingerprint the failed fetch event in HttpClient instrumentation + error: virtualError, }; // if there is no callback, fetch is instrumented directly @@ -82,7 +82,6 @@ function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNat if (onFetchResolved) { onFetchResolved(response); } else { - // Adding the stacktrace to be able to fingerprint the failed fetch event in HttpClient instrumentation triggerHandlers('fetch', { ...handlerData, endTimestamp: timestampInSeconds() * 1000, @@ -96,6 +95,7 @@ function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNat triggerHandlers('fetch', { ...handlerData, endTimestamp: timestampInSeconds() * 1000, + // Overriding the virtualError error, }); @@ -104,7 +104,7 @@ function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNat // it means the error, that was caused by your fetch call did not // have a stack trace, so the SDK backfilled the stack trace so // you can see which fetch call failed. - error.stack = virtualStackTrace; + error.stack = virtualError.stack; addNonEnumerableProperty(error, 'framesToPop', 1); }