package.build.esm.instrument.fetch.js.map Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of utils Show documentation
Show all versions of utils Show documentation
Utilities for all Sentry JavaScript SDKs
{"version":3,"file":"fetch.js","sources":["../../../src/instrument/fetch.ts"],"sourcesContent":["/* eslint-disable @typescript-eslint/no-explicit-any */\nimport type { HandlerDataFetch } from '@sentry/types';\n\nimport { isError } from '../is';\nimport { addNonEnumerableProperty, fill } from '../object';\nimport { supportsNativeFetch } from '../supports';\nimport { timestampInSeconds } from '../time';\nimport { GLOBAL_OBJ } from '../worldwide';\nimport { addHandler, maybeInstrument, triggerHandlers } from './handlers';\n\ntype FetchResource = string | { toString(): string } | { url: string };\n\n/**\n * Add an instrumentation handler for when a fetch request happens.\n * The handler function is called once when the request starts and once when it ends,\n * which can be identified by checking if it has an `endTimestamp`.\n *\n * Use at your own risk, this might break without changelog notice, only used internally.\n * @hidden\n */\nexport function addFetchInstrumentationHandler(\n handler: (data: HandlerDataFetch) => void,\n skipNativeFetchCheck?: boolean,\n): void {\n const type = 'fetch';\n addHandler(type, handler);\n maybeInstrument(type, () => instrumentFetch(undefined, skipNativeFetchCheck));\n}\n\n/**\n * Add an instrumentation handler for long-lived fetch requests, like consuming server-sent events (SSE) via fetch.\n * The handler will resolve the request body and emit the actual `endTimestamp`, so that the\n * span can be updated accordingly.\n *\n * Only used internally\n * @hidden\n */\nexport function addFetchEndInstrumentationHandler(handler: (data: HandlerDataFetch) => void): void {\n const type = 'fetch-body-resolved';\n addHandler(type, handler);\n maybeInstrument(type, () => instrumentFetch(streamHandler));\n}\n\nfunction instrumentFetch(onFetchResolved?: (response: Response) => void, skipNativeFetchCheck: boolean = false): void {\n if (skipNativeFetchCheck && !supportsNativeFetch()) {\n return;\n }\n\n fill(GLOBAL_OBJ, 'fetch', function (originalFetch: () => void): () => void {\n return function (...args: any[]): void {\n const { method, url } = parseFetchArgs(args);\n const handlerData: HandlerDataFetch = {\n args,\n fetchData: {\n method,\n url,\n },\n startTimestamp: timestampInSeconds() * 1000,\n };\n\n // if there is no callback, fetch is instrumented directly\n if (!onFetchResolved) {\n triggerHandlers('fetch', {\n ...handlerData,\n });\n }\n\n // We capture the stack right here and not in the Promise error callback because Safari (and probably other\n // browsers too) will wipe the stack trace up to this point, only leaving us with this file which is useless.\n\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your fetch call did not\n // have a stack trace, so the SDK backfilled the stack trace so\n // you can see which fetch call failed.\n const virtualStackTrace = new Error().stack;\n\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return originalFetch.apply(GLOBAL_OBJ, args).then(\n async (response: Response) => {\n if (onFetchResolved) {\n onFetchResolved(response);\n } else {\n triggerHandlers('fetch', {\n ...handlerData,\n endTimestamp: timestampInSeconds() * 1000,\n response,\n });\n }\n\n return response;\n },\n (error: Error) => {\n triggerHandlers('fetch', {\n ...handlerData,\n endTimestamp: timestampInSeconds() * 1000,\n error,\n });\n\n if (isError(error) && error.stack === undefined) {\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the error, that was caused by your fetch call did not\n // have a stack trace, so the SDK backfilled the stack trace so\n // you can see which fetch call failed.\n error.stack = virtualStackTrace;\n addNonEnumerableProperty(error, 'framesToPop', 1);\n }\n\n // NOTE: If you are a Sentry user, and you are seeing this stack frame,\n // it means the sentry.javascript SDK caught an error invoking your application code.\n // This is expected behavior and NOT indicative of a bug with sentry.javascript.\n throw error;\n },\n );\n };\n });\n}\n\nasync function resolveResponse(res: Response | undefined, onFinishedResolving: () => void): Promise {\n if (res && res.body) {\n const body = res.body;\n const responseReader = body.getReader();\n\n // Define a maximum duration after which we just cancel\n const maxFetchDurationTimeout = setTimeout(\n () => {\n body.cancel().then(null, () => {\n // noop\n });\n },\n 90 * 1000, // 90s\n );\n\n let readingActive = true;\n while (readingActive) {\n let chunkTimeout;\n try {\n // abort reading if read op takes more than 5s\n chunkTimeout = setTimeout(() => {\n body.cancel().then(null, () => {\n // noop on error\n });\n }, 5000);\n\n // This .read() call will reject/throw when we abort due to timeouts through `body.cancel()`\n const { done } = await responseReader.read();\n\n clearTimeout(chunkTimeout);\n\n if (done) {\n onFinishedResolving();\n readingActive = false;\n }\n } catch (error) {\n readingActive = false;\n } finally {\n clearTimeout(chunkTimeout);\n }\n }\n\n clearTimeout(maxFetchDurationTimeout);\n\n responseReader.releaseLock();\n body.cancel().then(null, () => {\n // noop on error\n });\n }\n}\n\nfunction streamHandler(response: Response): void {\n // clone response for awaiting stream\n let clonedResponseForResolving: Response;\n try {\n clonedResponseForResolving = response.clone();\n } catch {\n return;\n }\n\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n resolveResponse(clonedResponseForResolving, () => {\n triggerHandlers('fetch-body-resolved', {\n endTimestamp: timestampInSeconds() * 1000,\n response,\n });\n });\n}\n\nfunction hasProp(obj: unknown, prop: T): obj is Record {\n return !!obj && typeof obj === 'object' && !!(obj as Record)[prop];\n}\n\nfunction getUrlFromResource(resource: FetchResource): string {\n if (typeof resource === 'string') {\n return resource;\n }\n\n if (!resource) {\n return '';\n }\n\n if (hasProp(resource, 'url')) {\n return resource.url;\n }\n\n if (resource.toString) {\n return resource.toString();\n }\n\n return '';\n}\n\n/**\n * Parses the fetch arguments to find the used Http method and the url of the request.\n * Exported for tests only.\n */\nexport function parseFetchArgs(fetchArgs: unknown[]): { method: string; url: string } {\n if (fetchArgs.length === 0) {\n return { method: 'GET', url: '' };\n }\n\n if (fetchArgs.length === 2) {\n const [url, options] = fetchArgs as [FetchResource, object];\n\n return {\n url: getUrlFromResource(url),\n method: hasProp(options, 'method') ? String(options.method).toUpperCase() : 'GET',\n };\n }\n\n const arg = fetchArgs[0];\n return {\n url: getUrlFromResource(arg as FetchResource),\n method: hasProp(arg, 'method') ? String(arg.method).toUpperCase() : 'GET',\n };\n}\n"],"names":[],"mappings":"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"}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy