@sentry/browser 11.4.0 → 11.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -47,7 +47,7 @@ const fetchStreamPerformanceIntegration = core.defineIntegration(() => {
47
47
  [attributes.HTTP_REQUEST_METHOD]: method,
48
48
  type: "fetch",
49
49
  [attributes.SENTRY_OP]: op.HTTP_CLIENT_STREAM,
50
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser.stream"
50
+ [attributes.SENTRY_ORIGIN]: "auto.http.browser.stream"
51
51
  }
52
52
  });
53
53
  responseToStreamSpan.set(handlerData.response, streamSpan);
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":["defineIntegration","addFetchEndInstrumentationHandler","addFetchInstrumentationHandler","parseStringToURLObject","stripDataUrlContent","getSanitizedUrlStringFromUrlObject","getUrlDomain","WINDOW","startInactiveSpan","hasSpanStreamingEnabled","URL_FULL","filterCollectedUrl","URL_DOMAIN","HTTP_REQUEST_METHOD","SENTRY_OP","HTTP_CLIENT_STREAM","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":"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"}
1
+ {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL, SENTRY_ORIGIN } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":["defineIntegration","addFetchEndInstrumentationHandler","addFetchInstrumentationHandler","parseStringToURLObject","stripDataUrlContent","getSanitizedUrlStringFromUrlObject","getUrlDomain","WINDOW","startInactiveSpan","hasSpanStreamingEnabled","URL_FULL","filterCollectedUrl","URL_DOMAIN","HTTP_REQUEST_METHOD","SENTRY_OP","HTTP_CLIENT_STREAM","SENTRY_ORIGIN"],"mappings":"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"}
@@ -178,7 +178,7 @@ function xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeaders2, spans,
178
178
  [attributes.URL_FULL]: core.filterCollectedUrl(sanitizedFullUrl),
179
179
  [attributes.SERVER_ADDRESS]: host,
180
180
  [attributes.URL_DOMAIN]: domain,
181
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser",
181
+ [attributes.SENTRY_ORIGIN]: "auto.http.browser",
182
182
  [attributes.SENTRY_OP]: op.HTTP_CLIENT,
183
183
  [attributes.URL_QUERY]: core.filterCollectedUrlQuery(core.getUrlQuery(parsedUrl?.search)),
184
184
  [attributes.URL_FRAGMENT]: core.getUrlFragment(parsedUrl?.hash)
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["addFetchInstrumentationHandler","instrumentFetchRequest","WINDOW","getFullURL","parseUrl","stripDataUrlContent","URL_FULL","filterCollectedUrl","SERVER_ADDRESS","addXhrInstrumentationHandler","createHeadersSafely","spanToJSON","hasSpanStreamingEnabled","timestampInSeconds","addPerformanceInstrumentationHandler","isPerformanceResourceTiming","resourceTimingToSpanAttributes","getLocationHref","matchesTracePropagationTargets","shouldAttachHeaders","SENTRY_XHR_DATA_KEY","hasSpansEnabled","span","setHttpStatus","parseXhrResponseHeaders","stripUrlQueryAndFragment","getClient","getActiveSpan","getUrlDomain","startInactiveSpan","HTTP_REQUEST_METHOD","URL_DOMAIN","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_OP","HTTP_CLIENT","URL_QUERY","filterCollectedUrlQuery","getUrlQuery","URL_FRAGMENT","getUrlFragment","SentryNonRecordingSpan","spanIsIgnored","getTraceData","baggageHeaderHasSentryValues"],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["addFetchInstrumentationHandler","instrumentFetchRequest","WINDOW","getFullURL","parseUrl","stripDataUrlContent","URL_FULL","filterCollectedUrl","SERVER_ADDRESS","addXhrInstrumentationHandler","createHeadersSafely","spanToJSON","hasSpanStreamingEnabled","timestampInSeconds","addPerformanceInstrumentationHandler","isPerformanceResourceTiming","resourceTimingToSpanAttributes","getLocationHref","matchesTracePropagationTargets","shouldAttachHeaders","SENTRY_XHR_DATA_KEY","hasSpansEnabled","span","setHttpStatus","parseXhrResponseHeaders","stripUrlQueryAndFragment","getClient","getActiveSpan","getUrlDomain","startInactiveSpan","HTTP_REQUEST_METHOD","URL_DOMAIN","SENTRY_ORIGIN","SENTRY_OP","HTTP_CLIENT","URL_QUERY","filterCollectedUrlQuery","getUrlQuery","URL_FRAGMENT","getUrlFragment","SentryNonRecordingSpan","spanIsIgnored","getTraceData","baggageHeaderHasSentryValues"],"mappings":";;;;;;;;;;AAyHO,MAAM,oCAAA,GAAsE;AAAA,EACjF,UAAA,EAAY,IAAA;AAAA,EACZ,QAAA,EAAU,IAAA;AAAA,EACV,iBAAA,EAAmB;AACrB;AAGO,SAAS,0BAAA,CAA2B,QAAgB,QAAA,EAAyD;AAClH,EAAA,MAAM;AAAA,IACJ,UAAA;AAAA,IACA,QAAA;AAAA,IACA,0BAAA;AAAA,IACA,iBAAA;AAAA,IACA,uBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF,GAAI;AAAA,IACF,GAAG,oCAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,MAAM,mBACJ,OAAO,0BAAA,KAA+B,UAAA,GAAa,0BAAA,GAA6B,CAAC,CAAA,KAAc,IAAA;AAEjG,EAAA,MAAM,8BAAA,GAAiC,CAAC,GAAA,KAAyB,mBAAA,CAAoB,KAAK,uBAAuB,CAAA;AAEjH,EAAA,MAAM,QAA8B,EAAC;AAErC,EAAA,MAAM,oBAAA,GAAwB,MAAA,CAAyB,UAAA,EAAW,CAAE,oBAAA;AAEpE,EAAA,IAAI,UAAA,EAAY;AACd,IAAAA,mCAAA,CAA+B,CAAA,WAAA,KAAe;AAC5C,MAAA,MAAM,WAAA,GAAcC,2BAAA,CAAuB,WAAA,EAAa,gBAAA,EAAkB,gCAAgC,KAAA,EAAO;AAAA,QAC/G,oBAAA;AAAA,QACA,gBAAA;AAAA;AAAA,QAEA,OAAA,EAASC,eAAO,QAAA,EAAU;AAAA,OAC3B,CAAA;AAKD,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,MAAM,OAAA,GAAUC,gBAAA,CAAW,WAAA,CAAY,SAAA,CAAU,GAAG,CAAA;AAEpD,QAAA,MAAM,IAAA,GAAO,UAAUC,aAAA,CAAS,OAAO,EAAE,IAAA,EAAM,OAAA,CAAQ,MAAA,EAAQ,EAAE,CAAA,GAAI,MAAA;AACrE,QAAA,MAAM,gBAAA,GAAmB,OAAA,GAAUC,wBAAA,CAAoB,OAAO,CAAA,GAAI,MAAA;AAClE,QAAA,WAAA,CAAY,aAAA,CAAc;AAAA,UACxB,CAACC,mBAAQ,GAAGC,uBAAA,CAAmB,gBAAgB,CAAA;AAAA,UAC/C,CAACC,yBAAc,GAAG;AAAA,SACnB,CAAA;AAED,QAAA,IAAI,iBAAA,EAAmB;AACrB,UAAA,cAAA,CAAe,aAAa,MAAM,CAAA;AAAA,QACpC;AAEA,QAAA,kBAAA,GAAqB,WAAA,EAAa,EAAE,OAAA,EAAS,WAAA,CAAY,SAAS,CAAA;AAAA,MACpE;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAEA,EAAA,IAAI,QAAA,EAAU;AACZ,IAAAC,yCAAA,CAA6B,CAAA,WAAA,KAAe;AAC1C,MAAA,MAAM,WAAA,GAAc,WAAA;AAAA,QAClB,WAAA;AAAA,QACA,gBAAA;AAAA,QACA,8BAAA;AAAA,QACA,KAAA;AAAA,QACA,oBAAA;AAAA,QACA;AAAA,OACF;AAEA,MAAA,IAAI,WAAA,EAAa;AACf,QAAA,IAAI,iBAAA,EAAmB;AACrB,UAAA,cAAA,CAAe,aAAa,MAAM,CAAA;AAAA,QACpC;AAEA,QAAA,kBAAA,GAAqB,WAAA,EAAa;AAAA,UAChC,OAAA,EAASC,yBAAA,CAAoB,WAAA,CAAY,GAAA,CAAI,mBAAmB,eAAe;AAAA,SAChF,CAAA;AAAA,MACH;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AACF;AAOA,MAAM,mBAAA,GAAsB,GAAA;AAQ5B,SAAS,cAAA,CAAe,MAAY,MAAA,EAAsB;AACxD,EAAA,MAAM,GAAA,GAAMC,eAAA,CAAW,IAAI,CAAA,CAAE,WAAWL,mBAAQ,CAAA;AAEhD,EAAA,IAAI,CAAC,GAAA,IAAO,OAAO,GAAA,KAAQ,QAAA,EAAU;AACnC,IAAA;AAAA,EACF;AAKA,EAAA,IAAI,YAAA,GAAe,MAAY,KAAK,UAAA,CAAW,6BAA6B,CAAA;AAI5E,EAAA,IAAIM,4BAAA,CAAwB,MAAM,CAAA,EAAG;AACnC,IAAA,MAAM,WAAA,GAAc,IAAA,CAAK,GAAA,CAAI,IAAA,CAAK,IAAI,CAAA;AAEtC,IAAA,IAAA,CAAK,GAAA,GAAM,CAAC,YAAA,KAAiC;AAC3C,MAAA,MAAM,oBAAA,GAAuB,gBAAgBC,uBAAA,EAAmB;AAChE,MAAA,IAAI,OAAA,GAAU,KAAA;AAEd,MAAA,MAAM,oBAAoB,MAAY;AACpC,QAAA,IAAI,OAAA,EAAS;AACX,UAAA;AAAA,QACF;AACA,QAAA,OAAA,GAAU,IAAA;AACV,QAAA,UAAA,CAAW,6BAA6B,CAAA;AACxC,QAAA,WAAA,CAAY,oBAAoB,CAAA;AAChC,QAAA,YAAA,CAAa,eAAe,CAAA;AAAA,MAC9B,CAAA;AAEA,MAAA,YAAA,GAAe,iBAAA;AAKf,MAAA,MAAM,eAAA,GAAkB,UAAA,CAAW,iBAAA,EAAmB,mBAAmB,CAAA;AAAA,IAC3E,CAAA;AAAA,EACF;AAEA,EAAA,MAAM,gCAAgCC,iDAAA,CAAqC,UAAA,EAAY,CAAC,EAAE,SAAQ,KAAM;AACtG,IAAA,OAAA,CAAQ,QAAQ,CAAA,KAAA,KAAS;AACvB,MAAA,IAAIC,kCAA4B,KAAK,CAAA,IAAK,MAAM,IAAA,CAAK,QAAA,CAAS,GAAG,CAAA,EAAG;AAClE,QAAA,IAAA,CAAK,aAAA,CAAcC,2CAAA,CAA+B,KAAK,CAAC,CAAA;AACxD,QAAA,YAAA,EAAa;AAAA,MACf;AAAA,IACF,CAAC,CAAA;AAAA,EACH,CAAC,CAAA;AACH;AAMO,SAAS,mBAAA,CACd,WACA,uBAAA,EACS;AAGT,EAAA,MAAM,OAAOC,4BAAA,EAAgB;AAE7B,EAAA,IAAI,CAAC,IAAA,EAAM;AAIT,IAAA,MAAM,2BAAA,GAA8B,CAAC,CAAC,SAAA,CAAU,MAAM,WAAW,CAAA;AACjE,IAAA,IAAI,CAAC,uBAAA,EAAyB;AAC5B,MAAA,OAAO,2BAAA;AAAA,IACT,CAAA,MAAO;AACL,MAAA,OAAOC,mCAAA,CAA+B,WAAW,uBAAuB,CAAA;AAAA,IAC1E;AAAA,EACF,CAAA,MAAO;AACL,IAAA,IAAI,WAAA;AACJ,IAAA,IAAI,aAAA;AAGJ,IAAA,IAAI;AACF,MAAA,WAAA,GAAc,IAAI,GAAA,CAAI,SAAA,EAAW,IAAI,CAAA;AACrC,MAAA,aAAA,GAAgB,IAAI,GAAA,CAAI,IAAI,CAAA,CAAE,MAAA;AAAA,IAChC,CAAA,CAAA,MAAQ;AACN,MAAA,OAAO,KAAA;AAAA,IACT;AAEA,IAAA,MAAM,mBAAA,GAAsB,YAAY,MAAA,KAAW,aAAA;AACnD,IAAA,IAAI,CAAC,uBAAA,EAAyB;AAC5B,MAAA,OAAO,mBAAA;AAAA,IACT,CAAA,MAAO;AACL,MAAA,OACEA,mCAAA,CAA+B,WAAA,CAAY,QAAA,EAAS,EAAG,uBAAuB,KAC7E,mBAAA,IAAuBA,mCAAA,CAA+B,WAAA,CAAY,QAAA,EAAU,uBAAuB,CAAA;AAAA,IAExG;AAAA,EACF;AACF;AAQA,SAAS,YACP,WAAA,EACA,gBAAA,EACAC,oBAAAA,EACA,KAAA,EACA,sBACA,gBAAA,EACkB;AAClB,EAAA,MAAM,MAAM,WAAA,CAAY,GAAA;AACxB,EAAA,MAAM,aAAA,GAAgB,MAAMC,gCAAmB,CAAA;AAE/C,EAAA,IAAI,CAAC,GAAA,IAAO,GAAA,CAAI,sBAAA,IAA0B,CAAC,aAAA,EAAe;AACxD,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,EAAE,GAAA,EAAK,MAAA,EAAO,GAAI,aAAA;AAExB,EAAA,MAAM,sBAAA,GAAyBC,oBAAA,EAAgB,IAAK,gBAAA,CAAiB,GAAG,CAAA;AAGxE,EAAA,IAAI,YAAY,YAAA,EAAc;AAC5B,IAAA,MAAM,SAAS,GAAA,CAAI,sBAAA;AACnB,IAAA,IAAI,CAAC,MAAA,EAAQ;AAEb,IAAA,MAAMC,KAAAA,GAAO,MAAM,MAAM,CAAA;AAEzB,IAAA,IAAIA,KAAAA,EAAM;AACR,MAAA,IAAI,sBAAA,IAA0B,aAAA,CAAc,WAAA,KAAgB,MAAA,EAAW;AACrE,QAAAC,kBAAA,CAAcD,KAAAA,EAAM,cAAc,WAAW,CAAA;AAC7C,QAAAA,MAAK,GAAA,EAAI;AAET,QAAA,gBAAA,GAAmBA,KAAAA,EAAM;AAAA,UACvB,OAAA,EAASZ,yBAAA,CAAoBc,oCAAA,CAAwB,GAAmD,CAAC,CAAA;AAAA,UACzG,OAAO,WAAA,CAAY;AAAA,SACpB,CAAA;AAAA,MACH;AAGA,MAAA,OAAO,MAAM,MAAM,CAAA;AAAA,IACrB;AAEA,IAAA,OAAO,MAAA;AAAA,EACT;AAEA,EAAA,MAAM,OAAA,GAAUrB,iBAAW,GAAG,CAAA;AAC9B,EAAA,MAAM,YAAY,OAAA,GAAUC,aAAA,CAAS,OAAO,CAAA,GAAIA,cAAS,GAAG,CAAA;AAC5D,EAAA,MAAM,gBAAA,GAAmB,OAAA,GAAUC,wBAAA,CAAoB,OAAO,CAAA,GAAI,MAAA;AAElE,EAAA,MAAM,cAAA,GAAiBA,wBAAA,CAAoBoB,6BAAA,CAAyB,GAAG,CAAC,CAAA;AAExE,EAAA,MAAM,SAASC,cAAA,EAAU;AACzB,EAAA,MAAM,SAAA,GAAY,CAAC,CAACC,kBAAA,EAAc;AAElC,EAAA,MAAM,iBAAiB,SAAA,IAAc,CAAC,CAAC,MAAA,IAAUf,6BAAwB,MAAM,CAAA;AAG/E,EAAA,MAAM,IAAA,GAAO,SAAA,EAAW,IAAA,EAAM,OAAA,CAAQ,QAAQ,EAAE,CAAA;AAEhD,EAAA,MAAM,MAAA,GAASgB,iBAAA,CAAa,OAAA,IAAW,GAAG,CAAA;AAG1C,EAAA,MAAM,eAAe,MAAA,GAAS,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,MAAM,CAAA,CAAA,GAAK,MAAA;AAEtD,EAAA,MAAM,IAAA,GACJ,sBAAA,IAA0B,cAAA,GACtBC,yBAAA,CAAkB;AAAA,IAChB,IAAA,EAAM,CAAC,CAAC,MAAA,IAAUjB,4BAAA,CAAwB,MAAM,CAAA,GAAI,YAAA,GAAe,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,cAAc,CAAA,CAAA;AAAA,IAC9F,UAAA,EAAY;AAAA,MACV,IAAA,EAAM,KAAA;AAAA;AAAA,MAEN,CAACkB,8BAAmB,GAAG,MAAA;AAAA,MACvB,CAACxB,mBAAQ,GAAGC,uBAAA,CAAmB,gBAAgB,CAAA;AAAA,MAC/C,CAACC,yBAAc,GAAG,IAAA;AAAA,MAClB,CAACuB,qBAAU,GAAG,MAAA;AAAA,MACd,CAACC,wBAAa,GAAG,mBAAA;AAAA,MACjB,CAACC,oBAAS,GAAGC,cAAA;AAAA,MACb,CAACC,oBAAS,GAAGC,6BAAwBC,gBAAA,CAAY,SAAA,EAAW,MAAM,CAAC,CAAA;AAAA,MACnE,CAACC,uBAAY,GAAGC,mBAAA,CAAe,WAAW,IAAI;AAAA;AAChD,GACD,CAAA,GACD,IAAIC,2BAAA,EAAuB;AAIjC,EAAA,MAAM,mBAAA,GAAsBC,kBAAA,CAAc,IAAI,CAAA,IAAK,YAAY,MAAA,GAAY,IAAA;AAE3E,EAAA,IAAI,sBAAA,IAA0B,CAAC,cAAA,EAAgB;AAC7C,IAAA,MAAA,EAAQ,kBAAA,CAAmB,kBAAkB,MAAM,CAAA;AAAA,EACrD;AAEA,EAAA,GAAA,CAAI,sBAAA,GAAyB,IAAA,CAAK,WAAA,EAAY,CAAE,MAAA;AAChD,EAAA,KAAA,CAAM,GAAA,CAAI,sBAAsB,CAAA,GAAI,IAAA;AAEpC,EAAA,IAAItB,oBAAAA,CAAoB,GAAG,CAAA,EAAG;AAC5B,IAAA,6BAAA;AAAA,MACE,GAAA;AAAA;AAAA;AAAA;AAAA,MAIAE,oBAAA,EAAgB,IAAK,cAAA,GAAiB,mBAAA,GAAsB,MAAA;AAAA,MAC5D;AAAA,KACF;AAAA,EACF;AAEA,EAAA,IAAI,MAAA,EAAQ;AACV,IAAA,MAAA,CAAO,IAAA,CAAK,2BAAA,EAA6B,IAAA,EAAM,WAAsB,CAAA;AAAA,EACvE;AAEA,EAAA,OAAO,IAAA;AACT;AAEA,SAAS,6BAAA,CACP,GAAA,EACA,IAAA,EACA,oBAAA,EACM;AACN,EAAA,MAAM,EAAE,cAAA,EAAgB,WAAA,EAAa,OAAA,EAAS,WAAA,KAAgBqB,iBAAA,CAAa,EAAE,IAAA,EAAM,oBAAA,EAAsB,CAAA;AAEzG,EAAA,IAAI,WAAA,EAAa;AACf,IAAA,cAAA,CAAe,GAAA,EAAK,WAAA,EAAa,OAAA,EAAS,WAAW,CAAA;AAAA,EACvD;AACF;AAEA,SAAS,cAAA,CACP,GAAA,EACA,iBAAA,EACA,mBAAA,EACA,iBAAA,EACM;AACN,EAAA,MAAM,eAAA,GAAkB,IAAI,iBAAA,EAAmB,eAAA;AAE/C,EAAA,IAAI,eAAA,GAAkB,cAAc,CAAA,IAAK,CAAC,IAAI,gBAAA,EAAkB;AAE9D,IAAA;AAAA,EACF;AAEA,EAAA,IAAI;AACF,IAAA,GAAA,CAAI,gBAAA,CAAiB,gBAAgB,iBAAiB,CAAA;AAEtD,IAAA,IAAI,iBAAA,IAAqB,CAAC,eAAA,GAAkB,aAAa,CAAA,EAAG;AAC1D,MAAA,GAAA,CAAI,gBAAA,CAAiB,eAAe,iBAAiB,CAAA;AAAA,IACvD;AAEA,IAAA,IAAI,mBAAA,EAAqB;AAIvB,MAAA,MAAM,qBAAA,GAAwB,kBAAkB,SAAS,CAAA;AACzD,MAAA,IAAI,CAAC,qBAAA,IAAyB,CAACC,kCAAA,CAA6B,qBAAqB,CAAA,EAAG;AAIlF,QAAA,GAAA,CAAI,gBAAA,CAAiB,WAAW,mBAAmB,CAAA;AAAA,MACrD;AAAA,IACF;AAAA,EACF,CAAA,CAAA,MAAQ;AAAA,EAER;AACF;;;;;;"}
@@ -47,7 +47,7 @@ const fetchStreamPerformanceIntegration = core.defineIntegration(() => {
47
47
  [attributes.HTTP_REQUEST_METHOD]: method,
48
48
  type: "fetch",
49
49
  [attributes.SENTRY_OP]: op.HTTP_CLIENT_STREAM,
50
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser.stream"
50
+ [attributes.SENTRY_ORIGIN]: "auto.http.browser.stream"
51
51
  }
52
52
  });
53
53
  responseToStreamSpan.set(handlerData.response, streamSpan);
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":["defineIntegration","addFetchEndInstrumentationHandler","addFetchInstrumentationHandler","parseStringToURLObject","stripDataUrlContent","getSanitizedUrlStringFromUrlObject","getUrlDomain","WINDOW","startInactiveSpan","hasSpanStreamingEnabled","URL_FULL","filterCollectedUrl","URL_DOMAIN","HTTP_REQUEST_METHOD","SENTRY_OP","HTTP_CLIENT_STREAM","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN"],"mappings":"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"}
1
+ {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL, SENTRY_ORIGIN } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":["defineIntegration","addFetchEndInstrumentationHandler","addFetchInstrumentationHandler","parseStringToURLObject","stripDataUrlContent","getSanitizedUrlStringFromUrlObject","getUrlDomain","WINDOW","startInactiveSpan","hasSpanStreamingEnabled","URL_FULL","filterCollectedUrl","URL_DOMAIN","HTTP_REQUEST_METHOD","SENTRY_OP","HTTP_CLIENT_STREAM","SENTRY_ORIGIN"],"mappings":"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"}
@@ -178,7 +178,7 @@ function xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeaders2, spans,
178
178
  [attributes.URL_FULL]: core.filterCollectedUrl(sanitizedFullUrl),
179
179
  [attributes.SERVER_ADDRESS]: host,
180
180
  [attributes.URL_DOMAIN]: domain,
181
- [core.SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser",
181
+ [attributes.SENTRY_ORIGIN]: "auto.http.browser",
182
182
  [attributes.SENTRY_OP]: op.HTTP_CLIENT,
183
183
  [attributes.URL_QUERY]: core.filterCollectedUrlQuery(core.getUrlQuery(parsedUrl?.search)),
184
184
  [attributes.URL_FRAGMENT]: core.getUrlFragment(parsedUrl?.hash)
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["addFetchInstrumentationHandler","instrumentFetchRequest","WINDOW","getFullURL","parseUrl","stripDataUrlContent","URL_FULL","filterCollectedUrl","SERVER_ADDRESS","addXhrInstrumentationHandler","createHeadersSafely","spanToJSON","hasSpanStreamingEnabled","timestampInSeconds","addPerformanceInstrumentationHandler","isPerformanceResourceTiming","resourceTimingToSpanAttributes","getLocationHref","matchesTracePropagationTargets","shouldAttachHeaders","SENTRY_XHR_DATA_KEY","hasSpansEnabled","span","setHttpStatus","parseXhrResponseHeaders","stripUrlQueryAndFragment","getClient","getActiveSpan","getUrlDomain","startInactiveSpan","HTTP_REQUEST_METHOD","URL_DOMAIN","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SENTRY_OP","HTTP_CLIENT","URL_QUERY","filterCollectedUrlQuery","getUrlQuery","URL_FRAGMENT","getUrlFragment","SentryNonRecordingSpan","spanIsIgnored","getTraceData","baggageHeaderHasSentryValues"],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["addFetchInstrumentationHandler","instrumentFetchRequest","WINDOW","getFullURL","parseUrl","stripDataUrlContent","URL_FULL","filterCollectedUrl","SERVER_ADDRESS","addXhrInstrumentationHandler","createHeadersSafely","spanToJSON","hasSpanStreamingEnabled","timestampInSeconds","addPerformanceInstrumentationHandler","isPerformanceResourceTiming","resourceTimingToSpanAttributes","getLocationHref","matchesTracePropagationTargets","shouldAttachHeaders","SENTRY_XHR_DATA_KEY","hasSpansEnabled","span","setHttpStatus","parseXhrResponseHeaders","stripUrlQueryAndFragment","getClient","getActiveSpan","getUrlDomain","startInactiveSpan","HTTP_REQUEST_METHOD","URL_DOMAIN","SENTRY_ORIGIN","SENTRY_OP","HTTP_CLIENT","URL_QUERY","filterCollectedUrlQuery","getUrlQuery","URL_FRAGMENT","getUrlFragment","SentryNonRecordingSpan","spanIsIgnored","getTraceData","baggageHeaderHasSentryValues"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { SENTRY_OP, HTTP_REQUEST_METHOD, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';
1
+ import { SENTRY_ORIGIN, SENTRY_OP, HTTP_REQUEST_METHOD, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';
2
2
  import { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';
3
- import { defineIntegration, addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, parseStringToURLObject, stripDataUrlContent, getSanitizedUrlStringFromUrlObject, getUrlDomain, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, filterCollectedUrl, hasSpanStreamingEnabled } from '@sentry/core';
3
+ import { defineIntegration, addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, parseStringToURLObject, stripDataUrlContent, getSanitizedUrlStringFromUrlObject, getUrlDomain, filterCollectedUrl, hasSpanStreamingEnabled } from '@sentry/core';
4
4
  import { startInactiveSpan } from '@sentry/core/browser';
5
5
  import { WINDOW } from '../helpers.js';
6
6
 
@@ -45,7 +45,7 @@ const fetchStreamPerformanceIntegration = defineIntegration(() => {
45
45
  [HTTP_REQUEST_METHOD]: method,
46
46
  type: "fetch",
47
47
  [SENTRY_OP]: HTTP_CLIENT_STREAM,
48
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser.stream"
48
+ [SENTRY_ORIGIN]: "auto.http.browser.stream"
49
49
  }
50
50
  });
51
51
  responseToStreamSpan.set(handlerData.response, streamSpan);
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL, SENTRY_ORIGIN } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"type":"module","version":"11.4.0","sideEffects":false}
1
+ {"type":"module","version":"11.5.0","sideEffects":false}
@@ -1,9 +1,9 @@
1
- import { addFetchInstrumentationHandler, instrumentFetchRequest, parseUrl, stripDataUrlContent, filterCollectedUrl, spanToJSON, hasSpanStreamingEnabled, timestampInSeconds, hasSpansEnabled, setHttpStatus, stripUrlQueryAndFragment, getClient, getActiveSpan, getUrlDomain, getUrlFragment, filterCollectedUrlQuery, getUrlQuery, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SentryNonRecordingSpan, spanIsIgnored, matchesTracePropagationTargets, getTraceData } from '@sentry/core';
1
+ import { addFetchInstrumentationHandler, instrumentFetchRequest, parseUrl, stripDataUrlContent, filterCollectedUrl, spanToJSON, hasSpanStreamingEnabled, timestampInSeconds, hasSpansEnabled, setHttpStatus, stripUrlQueryAndFragment, getClient, getActiveSpan, getUrlDomain, getUrlFragment, filterCollectedUrlQuery, getUrlQuery, SentryNonRecordingSpan, spanIsIgnored, matchesTracePropagationTargets, getTraceData } from '@sentry/core';
2
2
  import { startInactiveSpan } from '@sentry/core/browser';
3
3
  import { addXhrInstrumentationHandler, addPerformanceInstrumentationHandler, resourceTimingToSpanAttributes, SENTRY_XHR_DATA_KEY, parseXhrResponseHeaders, getLocationHref } from '@sentry/browser-utils';
4
4
  import { WINDOW } from '../helpers.js';
5
5
  import { getFullURL, createHeadersSafely, isPerformanceResourceTiming, baggageHeaderHasSentryValues } from './utils.js';
6
- import { SERVER_ADDRESS, URL_FULL, URL_FRAGMENT, URL_QUERY, SENTRY_OP, URL_DOMAIN, HTTP_REQUEST_METHOD } from '@sentry/conventions/attributes';
6
+ import { SERVER_ADDRESS, URL_FULL, URL_FRAGMENT, URL_QUERY, SENTRY_OP, SENTRY_ORIGIN, URL_DOMAIN, HTTP_REQUEST_METHOD } from '@sentry/conventions/attributes';
7
7
  import { HTTP_CLIENT } from '@sentry/conventions/op';
8
8
 
9
9
  const defaultRequestInstrumentationOptions = {
@@ -176,7 +176,7 @@ function xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeaders2, spans,
176
176
  [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),
177
177
  [SERVER_ADDRESS]: host,
178
178
  [URL_DOMAIN]: domain,
179
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser",
179
+ [SENTRY_ORIGIN]: "auto.http.browser",
180
180
  [SENTRY_OP]: HTTP_CLIENT,
181
181
  [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),
182
182
  [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash)
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["shouldAttachHeaders","span"],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["shouldAttachHeaders","span"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
- import { SENTRY_OP, HTTP_REQUEST_METHOD, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';
1
+ import { SENTRY_ORIGIN, SENTRY_OP, HTTP_REQUEST_METHOD, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';
2
2
  import { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';
3
- import { defineIntegration, addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, parseStringToURLObject, stripDataUrlContent, getSanitizedUrlStringFromUrlObject, getUrlDomain, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, filterCollectedUrl, hasSpanStreamingEnabled } from '@sentry/core';
3
+ import { defineIntegration, addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, parseStringToURLObject, stripDataUrlContent, getSanitizedUrlStringFromUrlObject, getUrlDomain, filterCollectedUrl, hasSpanStreamingEnabled } from '@sentry/core';
4
4
  import { startInactiveSpan } from '@sentry/core/browser';
5
5
  import { WINDOW } from '../helpers.js';
6
6
 
@@ -45,7 +45,7 @@ const fetchStreamPerformanceIntegration = defineIntegration(() => {
45
45
  [HTTP_REQUEST_METHOD]: method,
46
46
  type: "fetch",
47
47
  [SENTRY_OP]: HTTP_CLIENT_STREAM,
48
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser.stream"
48
+ [SENTRY_ORIGIN]: "auto.http.browser.stream"
49
49
  }
50
50
  });
51
51
  responseToStreamSpan.set(handlerData.response, streamSpan);
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"fetchStreamPerformance.js","sources":["../../../../../src/integrations/fetchStreamPerformance.ts"],"sourcesContent":["import { HTTP_REQUEST_METHOD, SENTRY_OP, URL_DOMAIN, URL_FULL, SENTRY_ORIGIN } from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT_STREAM } from '@sentry/conventions/op';\nimport type { IntegrationFn, Span } from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n defineIntegration,\n getSanitizedUrlStringFromUrlObject,\n getUrlDomain,\n hasSpanStreamingEnabled,\n parseStringToURLObject,\n stripDataUrlContent,\n filterCollectedUrl,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport { WINDOW } from '../helpers';\n\nconst responseToStreamSpan = new WeakMap<object, Span>();\nconst responseToFallbackTimeout = new WeakMap<object, ReturnType<typeof setTimeout>>();\n\n// Matches the max timeout in `resolveResponse` in packages/core/src/instrument/fetch.ts\nconst STREAM_RESOLVE_FALLBACK_MS = 90_000;\n\nconst STREAMING_CONTENT_TYPES = ['text/event-stream', 'application/x-ndjson', 'application/stream+json'];\n\n/**\n * Tracks streamed fetch response bodies by creating an `http.client.stream` sibling span.\n *\n * The regular `http.client` span ends when response headers arrive. This integration adds\n * a span that starts at header arrival and ends when the body fully resolves:\n *\n * ```\n * --------- pageload --------------------------------\n * -- http.client --\n * -- http.client.stream -------\n * ```\n */\nexport const fetchStreamPerformanceIntegration = defineIntegration(() => {\n return {\n name: 'FetchStreamPerformance' as const,\n\n setup(client) {\n // End the stream span when the response body finishes resolving\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const streamSpan = responseToStreamSpan.get(handlerData.response);\n if (streamSpan && handlerData.endTimestamp) {\n streamSpan.end(handlerData.endTimestamp);\n\n const fallbackTimeout = responseToFallbackTimeout.get(handlerData.response);\n if (fallbackTimeout) {\n clearTimeout(fallbackTimeout);\n }\n }\n }\n });\n\n addFetchInstrumentationHandler(handlerData => {\n // Only create the stream span once headers have arrived\n if (handlerData.endTimestamp && handlerData.response) {\n // Only create stream spans for responses that are likely streamed:\n // 1. No content-length header (streamed responses don't know the size upfront)\n // 2. Content-type is a known streaming type (avoids false positives on HTTP/2\n // where content-length is often omitted even for regular responses)\n const contentType = handlerData.response.headers?.get('content-type') || '';\n if (\n handlerData.response.headers?.get('content-length') ||\n !STREAMING_CONTENT_TYPES.some(t => contentType.startsWith(t))\n ) {\n return;\n }\n\n const url = handlerData.fetchData?.url || '';\n const method = handlerData.fetchData?.method || 'GET';\n\n const parsedUrl = parseStringToURLObject(url);\n const sanitizedUrl = url.startsWith('data:')\n ? stripDataUrlContent(url)\n : parsedUrl\n ? getSanitizedUrlStringFromUrlObject(parsedUrl)\n : url;\n\n // `http.client.stream` follows the same name rules as `http.client`.\n const domain = getUrlDomain(url, WINDOW.location?.origin);\n const streamedName = domain ? `${method} ${domain}` : method;\n const streamSpan = startInactiveSpan({\n name: hasSpanStreamingEnabled(client) ? streamedName : `${method} ${sanitizedUrl}`,\n startTime: handlerData.endTimestamp,\n attributes: {\n [URL_FULL]: filterCollectedUrl(stripDataUrlContent(url)),\n [URL_DOMAIN]: domain,\n [HTTP_REQUEST_METHOD]: method,\n type: 'fetch',\n [SENTRY_OP]: HTTP_CLIENT_STREAM,\n [SENTRY_ORIGIN]: 'auto.http.browser.stream',\n },\n });\n\n responseToStreamSpan.set(handlerData.response, streamSpan);\n\n // prevent the span from leaking indefinitely if the body never resolves\n const fallbackTimeout = setTimeout(() => {\n if (streamSpan.isRecording()) {\n streamSpan.end();\n }\n }, STREAM_RESOLVE_FALLBACK_MS);\n\n responseToFallbackTimeout.set(handlerData.response, fallbackTimeout);\n }\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"type":"module","version":"11.4.0","sideEffects":false}
1
+ {"type":"module","version":"11.5.0","sideEffects":false}
@@ -1,9 +1,9 @@
1
- import { addFetchInstrumentationHandler, instrumentFetchRequest, parseUrl, stripDataUrlContent, filterCollectedUrl, spanToJSON, hasSpanStreamingEnabled, timestampInSeconds, hasSpansEnabled, setHttpStatus, stripUrlQueryAndFragment, getClient, getActiveSpan, getUrlDomain, getUrlFragment, filterCollectedUrlQuery, getUrlQuery, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SentryNonRecordingSpan, spanIsIgnored, matchesTracePropagationTargets, getTraceData } from '@sentry/core';
1
+ import { addFetchInstrumentationHandler, instrumentFetchRequest, parseUrl, stripDataUrlContent, filterCollectedUrl, spanToJSON, hasSpanStreamingEnabled, timestampInSeconds, hasSpansEnabled, setHttpStatus, stripUrlQueryAndFragment, getClient, getActiveSpan, getUrlDomain, getUrlFragment, filterCollectedUrlQuery, getUrlQuery, SentryNonRecordingSpan, spanIsIgnored, matchesTracePropagationTargets, getTraceData } from '@sentry/core';
2
2
  import { startInactiveSpan } from '@sentry/core/browser';
3
3
  import { addXhrInstrumentationHandler, addPerformanceInstrumentationHandler, resourceTimingToSpanAttributes, SENTRY_XHR_DATA_KEY, parseXhrResponseHeaders, getLocationHref } from '@sentry/browser-utils';
4
4
  import { WINDOW } from '../helpers.js';
5
5
  import { getFullURL, createHeadersSafely, isPerformanceResourceTiming, baggageHeaderHasSentryValues } from './utils.js';
6
- import { SERVER_ADDRESS, URL_FULL, URL_FRAGMENT, URL_QUERY, SENTRY_OP, URL_DOMAIN, HTTP_REQUEST_METHOD } from '@sentry/conventions/attributes';
6
+ import { SERVER_ADDRESS, URL_FULL, URL_FRAGMENT, URL_QUERY, SENTRY_OP, SENTRY_ORIGIN, URL_DOMAIN, HTTP_REQUEST_METHOD } from '@sentry/conventions/attributes';
7
7
  import { HTTP_CLIENT } from '@sentry/conventions/op';
8
8
 
9
9
  const defaultRequestInstrumentationOptions = {
@@ -176,7 +176,7 @@ function xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeaders2, spans,
176
176
  [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),
177
177
  [SERVER_ADDRESS]: host,
178
178
  [URL_DOMAIN]: domain,
179
- [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: "auto.http.browser",
179
+ [SENTRY_ORIGIN]: "auto.http.browser",
180
180
  [SENTRY_OP]: HTTP_CLIENT,
181
181
  [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),
182
182
  [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash)
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["shouldAttachHeaders","span"],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, RequestHookInfo, ResponseHookInfo, Span, SpanTimeInput } from '@sentry/core';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getTraceData,\n getUrlDomain,\n getUrlFragment,\n getUrlQuery,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n matchesTracePropagationTargets,\n parseUrl,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanIsIgnored,\n spanToJSON,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport { startInactiveSpan } from '@sentry/core/browser';\nimport type { HandlerDataXhr, SentryWrappedXMLHttpRequest, XhrHint } from '@sentry/browser-utils';\nimport { filterCollectedUrl, filterCollectedUrlQuery } from '@sentry/core';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n getLocationHref,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\nimport {\n HTTP_REQUEST_METHOD,\n SENTRY_OP,\n SERVER_ADDRESS,\n URL_DOMAIN,\n URL_FRAGMENT,\n URL_FULL,\n URL_QUERY,\n SENTRY_ORIGIN,\n} from '@sentry/conventions/attributes';\nimport { HTTP_CLIENT } from '@sentry/conventions/op';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n * Matching is case-insensitive, so `'myApi.com'` and `/^myApi\\.com/` both match a request to `https://myapi.com`.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n // The generic fetch instrumentation has no page origin to resolve relative URLs against.\n urlBase: WINDOW.location?.origin,\n });\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = fullUrl ? parseUrl(fullUrl).host?.replace(/^.*@/, '') : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url.full` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const url = spanToJSON(span).attributes[URL_FULL];\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return matchesTracePropagationTargets(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n matchesTracePropagationTargets(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && matchesTracePropagationTargets(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\n// oxlint-disable-next-line complexity\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const client = getClient();\n const hasParent = !!getActiveSpan();\n // With span streaming, we always emit http.client spans, even without a parent span\n const shouldEmitSpan = hasParent || (!!client && hasSpanStreamingEnabled(client));\n\n // `parseUrl` returns the raw authority — userinfo credentials must never reach an attribute.\n const host = parsedUrl?.host?.replace(/^.*@/, '');\n // `getFullURL` already resolved relative URLs against the page origin; only data URLs have no domain.\n const domain = getUrlDomain(fullUrl || url);\n\n // With span streaming, span names have to be low cardinality, so only the domain is kept.\n const streamedName = domain ? `${method} ${domain}` : method;\n\n const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: !!client && hasSpanStreamingEnabled(client) ? streamedName : `${method} ${urlForSpanName}`,\n attributes: {\n type: 'xhr',\n // eslint-disable-next-line typescript/no-deprecated\n [HTTP_REQUEST_METHOD]: method,\n [URL_FULL]: filterCollectedUrl(sanitizedFullUrl),\n [SERVER_ADDRESS]: host,\n [URL_DOMAIN]: domain,\n [SENTRY_ORIGIN]: 'auto.http.browser',\n [SENTRY_OP]: HTTP_CLIENT,\n [URL_QUERY]: filterCollectedUrlQuery(getUrlQuery(parsedUrl?.search)),\n [URL_FRAGMENT]: getUrlFragment(parsedUrl?.hash),\n },\n })\n : new SentryNonRecordingSpan();\n\n // If the span is ignored, we don't want to continue the trace from it (NonRecordingSpan) but rather\n // from the active span. Passing `undefined` here will make `getTraceData` use the active span instead.\n const spanForTraceHeaders = spanIsIgnored(span) && hasParent ? undefined : span;\n\n if (shouldCreateSpanResult && !shouldEmitSpan) {\n client?.recordDroppedEvent('no_parent_span', 'span');\n }\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && shouldEmitSpan ? spanForTraceHeaders : undefined,\n propagateTraceparent,\n );\n }\n\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["shouldAttachHeaders","span"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/exports.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,cAAc,EACd,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACP,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,MAAM,EACN,IAAI,EACJ,OAAO,EACP,mBAAmB,EACnB,cAAc,EACd,kCAAkC,EAClC,GAAG,EACH,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,KAAK,EACL,eAAe,EACf,WAAW,EACX,KAAK,EACL,SAAS,EACT,aAAa,EACb,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAS,EACT,MAAM,EACN,OAAO,EACP,YAAY,EACZ,aAAa,EACb,OAAO,EACP,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EAClB,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,cAAc,EAEd,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EACL,4BAA4B,EAC5B,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"exports.d.ts","sourceRoot":"","sources":["../../../src/exports.ts"],"names":[],"mappings":"AAAA,YAAY,EACV,UAAU,EACV,cAAc,EACd,OAAO,EACP,QAAQ,EACR,gBAAgB,EAChB,OAAO,EACP,KAAK,EACL,SAAS,EACT,UAAU,EACV,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,MAAM,EACN,IAAI,EACJ,OAAO,EACP,mBAAmB,EACnB,cAAc,EACd,kCAAkC,EAClC,GAAG,EACH,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAE/C,OAAO,EACL,iBAAiB,EACjB,aAAa,EACb,cAAc,EACd,gBAAgB,EAChB,YAAY,EACZ,eAAe,EACf,cAAc,EACd,KAAK,EACL,eAAe,EACf,WAAW,EACX,KAAK,EACL,SAAS,EACT,aAAa,EACb,SAAS,EACT,eAAe,EACf,iBAAiB,EACjB,cAAc,EACd,gBAAgB,EAChB,KAAK,EACL,aAAa,EACb,YAAY,EACZ,eAAe,EACf,WAAW,EACX,UAAU,EACV,QAAQ,EACR,SAAS,EACT,MAAM,EACN,OAAO,EACP,YAAY,EACZ,aAAa,EACb,OAAO,EACP,iBAAiB,EACjB,SAAS,EACT,kBAAkB,EAClB,2BAA2B,EAC3B,uBAAuB,EACvB,iBAAiB,EACjB,kBAAkB,EAClB,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,UAAU,EACV,oBAAoB,EACpB,UAAU,EACV,iBAAiB,EACjB,mBAAmB,EACnB,cAAc,EACd,cAAc,EAEd,gBAAgB,GACjB,MAAM,cAAc,CAAC;AAEtB,OAAO,EAEL,4BAA4B,EAE5B,gCAAgC,EAChC,qCAAqC,GACtC,MAAM,cAAc,CAAC;AAEtB,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EACL,kBAAkB,EAClB,uBAAuB,EACvB,qBAAqB,EACrB,oBAAoB,EACpB,sBAAsB,EACtB,sBAAsB,EACtB,oBAAoB,GACrB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAC1F,OAAO,EAAE,0BAA0B,EAAE,MAAM,gBAAgB,CAAC;AAC5D,OAAO,EAAE,sBAAsB,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,OAAO,CAAC;AACxE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAC1E,OAAO,EAAE,sBAAsB,EAAE,MAAM,4BAA4B,CAAC;AACpE,OAAO,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AACtE,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,yBAAyB,EAAE,MAAM,+BAA+B,CAAC;AAE1E,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"fetchStreamPerformance.d.ts","sourceRoot":"","sources":["../../../../src/integrations/fetchStreamPerformance.ts"],"names":[],"mappings":"AA0BA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC;;CA2EpB,CAAC"}
1
+ {"version":3,"file":"fetchStreamPerformance.d.ts","sourceRoot":"","sources":["../../../../src/integrations/fetchStreamPerformance.ts"],"names":[],"mappings":"AAyBA;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC;;CA2EpB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sentry/browser",
3
- "version": "11.4.0",
3
+ "version": "11.5.0",
4
4
  "description": "Official Sentry SDK for browsers",
5
5
  "repository": "git://github.com/getsentry/sentry-javascript.git",
6
6
  "homepage": "https://github.com/getsentry/sentry-javascript/tree/master/packages/browser",
@@ -38,15 +38,15 @@
38
38
  "access": "public"
39
39
  },
40
40
  "dependencies": {
41
- "@sentry/browser-utils": "11.4.0",
42
- "@sentry/conventions": "^0.25.0",
43
- "@sentry/feedback": "11.4.0",
44
- "@sentry/replay": "11.4.0",
45
- "@sentry/replay-canvas": "11.4.0",
46
- "@sentry/core": "11.4.0"
41
+ "@sentry/browser-utils": "11.5.0",
42
+ "@sentry/conventions": "^0.26.0",
43
+ "@sentry/feedback": "11.5.0",
44
+ "@sentry/replay": "11.5.0",
45
+ "@sentry/replay-canvas": "11.5.0",
46
+ "@sentry/core": "11.5.0"
47
47
  },
48
48
  "devDependencies": {
49
- "@sentry-internal/integration-shims": "11.4.0",
49
+ "@sentry-internal/integration-shims": "11.5.0",
50
50
  "fake-indexeddb": "^6.2.5"
51
51
  },
52
52
  "scripts": {