diff --git a/packages/browser/src/integrations/httpclient.ts b/packages/browser/src/integrations/httpclient.ts index 8ab3c11fccd4..12cf929d0026 100644 --- a/packages/browser/src/integrations/httpclient.ts +++ b/packages/browser/src/integrations/httpclient.ts @@ -298,7 +298,7 @@ function _wrapFetch(client: Client, options: HttpClientOptions): void { } _fetchResponseHandler(options, requestInfo, response as Response, requestInit, error || virtualError); - }, false); + }); } /** diff --git a/packages/cloudflare/src/integrations/fetch.ts b/packages/cloudflare/src/integrations/fetch.ts index 133a92e8e738..fab9501e19e5 100644 --- a/packages/cloudflare/src/integrations/fetch.ts +++ b/packages/cloudflare/src/integrations/fetch.ts @@ -107,7 +107,7 @@ const _fetchIntegration = ((options: Partial = {}) => { if (breadcrumbs) { createBreadcrumb(handlerData); } - }, true); + }); }, setup(client) { HAS_CLIENT_MAP.set(client, true); diff --git a/packages/core/src/instrument/fetch.ts b/packages/core/src/instrument/fetch.ts index 66821e208581..b7d5d6dd0847 100644 --- a/packages/core/src/instrument/fetch.ts +++ b/packages/core/src/instrument/fetch.ts @@ -3,6 +3,7 @@ import { getClient } from '../currentScopes'; import type { HandlerDataFetch } from '../types/instrument'; import type { WebFetchHeaders } from '../types/webfetchapi'; import { isError, isObjectLike, isRequest } from '../utils/is'; +import { isBrowser } from '../utils/isBrowser'; import { addNonEnumerableProperty, fill } from '../utils/object'; import { supportsNativeFetch } from '../utils/supports'; import { timestampInSeconds } from '../utils/time'; @@ -20,13 +21,10 @@ type FetchResource = string | { toString(): string } | { url: string }; * Use at your own risk, this might break without changelog notice, only used internally. * @hidden */ -export function addFetchInstrumentationHandler( - handler: (data: HandlerDataFetch) => void, - skipNativeFetchCheck?: boolean, -): () => void { +export function addFetchInstrumentationHandler(handler: (data: HandlerDataFetch) => void): () => void { const type = 'fetch'; const removeHandler = addHandler(type, handler); - maybeInstrument(type, () => instrumentFetch(undefined, skipNativeFetchCheck)); + maybeInstrument(type, () => instrumentFetch()); return removeHandler; } @@ -46,8 +44,12 @@ export function addFetchEndInstrumentationHandler(handler: (data: HandlerDataFet return removeHandler; } -function instrumentFetch(onFetchResolved?: (response: Response) => void, skipNativeFetchCheck: boolean = false): void { - if (skipNativeFetchCheck && !supportsNativeFetch()) { +function instrumentFetch(onFetchResolved?: (response: Response) => void): void { + // The native-fetch check is only meaningful in the browser: it probes for `[native code]` and + // falls back to an iframe DOM check to detect a polyfilled/wrapped `fetch` (which we don't want to + // double-instrument alongside XHR). Outside the browser there is no DOM, and `fetch` may be + // legitimately wrapped by the host (e.g. Next.js on Bun), so we always patch the global there. + if (isBrowser() && !supportsNativeFetch()) { return; }