All Downloads are FREE. Search and download functionalities are using the official Maven repository.

package.build.esm.instrument.fetch.js.map Maven / Gradle / Ivy

There is a newer version: 8.38.0
Show newest version
{"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 && res.body.getReader) {\n    const responseReader = res.body.getReader();\n\n    // eslint-disable-next-line no-inner-declarations\n    async function consumeChunks({ done }: { done: boolean }): Promise {\n      if (!done) {\n        try {\n          // abort reading if read op takes more than 5s\n          const result = await Promise.race([\n            responseReader.read(),\n            new Promise<{ done: boolean }>(res => {\n              setTimeout(() => {\n                res({ done: true });\n              }, 5000);\n            }),\n          ]);\n          await consumeChunks(result);\n        } catch (error) {\n          // handle error if needed\n        }\n      } else {\n        return Promise.resolve();\n      }\n    }\n\n    return responseReader\n      .read()\n      .then(consumeChunks)\n      .then(onFinishedResolving)\n      .catch(() => undefined);\n  }\n}\n\nasync function streamHandler(response: Response): Promise {\n  // clone response for awaiting stream\n  let clonedResponseForResolving: Response;\n  try {\n    clonedResponseForResolving = response.clone();\n  } catch {\n    return;\n  }\n\n  await 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