@sentry/browser 10.58.0 → 10.60.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.
- package/build/npm/cjs/dev/client.js.map +1 -1
- package/build/npm/cjs/dev/eventbuilder.js.map +1 -1
- package/build/npm/cjs/dev/index.js +1 -0
- package/build/npm/cjs/dev/index.js.map +1 -1
- package/build/npm/cjs/dev/integrations/httpclient.js.map +1 -1
- package/build/npm/cjs/dev/integrations/httpcontext.js +2 -1
- package/build/npm/cjs/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/dev/integrations/webVitals.js.map +1 -1
- package/build/npm/cjs/dev/profiling/integration.js.map +1 -1
- package/build/npm/cjs/dev/profiling/utils.js.map +1 -1
- package/build/npm/cjs/dev/sdk.js +1 -1
- package/build/npm/cjs/dev/sdk.js.map +1 -1
- package/build/npm/cjs/dev/tracing/browserTracingIntegration.js +3 -3
- package/build/npm/cjs/dev/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/dev/tracing/request.js +10 -2
- package/build/npm/cjs/dev/tracing/request.js.map +1 -1
- package/build/npm/cjs/prod/client.js.map +1 -1
- package/build/npm/cjs/prod/eventbuilder.js.map +1 -1
- package/build/npm/cjs/prod/index.js +1 -0
- package/build/npm/cjs/prod/index.js.map +1 -1
- package/build/npm/cjs/prod/integrations/httpclient.js.map +1 -1
- package/build/npm/cjs/prod/integrations/httpcontext.js +2 -1
- package/build/npm/cjs/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/prod/integrations/webVitals.js.map +1 -1
- package/build/npm/cjs/prod/profiling/integration.js.map +1 -1
- package/build/npm/cjs/prod/profiling/utils.js.map +1 -1
- package/build/npm/cjs/prod/sdk.js +1 -1
- package/build/npm/cjs/prod/sdk.js.map +1 -1
- package/build/npm/cjs/prod/tracing/browserTracingIntegration.js +3 -3
- package/build/npm/cjs/prod/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/prod/tracing/request.js +10 -2
- package/build/npm/cjs/prod/tracing/request.js.map +1 -1
- package/build/npm/esm/dev/client.js.map +1 -1
- package/build/npm/esm/dev/eventbuilder.js.map +1 -1
- package/build/npm/esm/dev/index.js +1 -1
- package/build/npm/esm/dev/integrations/httpclient.js.map +1 -1
- package/build/npm/esm/dev/integrations/httpcontext.js +3 -2
- package/build/npm/esm/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/dev/integrations/webVitals.js.map +1 -1
- package/build/npm/esm/dev/package.json +1 -1
- package/build/npm/esm/dev/profiling/integration.js.map +1 -1
- package/build/npm/esm/dev/profiling/utils.js.map +1 -1
- package/build/npm/esm/dev/sdk.js +1 -1
- package/build/npm/esm/dev/sdk.js.map +1 -1
- package/build/npm/esm/dev/tracing/browserTracingIntegration.js +3 -3
- package/build/npm/esm/dev/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/dev/tracing/request.js +10 -2
- package/build/npm/esm/dev/tracing/request.js.map +1 -1
- package/build/npm/esm/prod/client.js.map +1 -1
- package/build/npm/esm/prod/eventbuilder.js.map +1 -1
- package/build/npm/esm/prod/index.js +1 -1
- package/build/npm/esm/prod/integrations/httpclient.js.map +1 -1
- package/build/npm/esm/prod/integrations/httpcontext.js +3 -2
- package/build/npm/esm/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/prod/integrations/webVitals.js.map +1 -1
- package/build/npm/esm/prod/package.json +1 -1
- package/build/npm/esm/prod/profiling/integration.js.map +1 -1
- package/build/npm/esm/prod/profiling/utils.js.map +1 -1
- package/build/npm/esm/prod/sdk.js +1 -1
- package/build/npm/esm/prod/sdk.js.map +1 -1
- package/build/npm/esm/prod/tracing/browserTracingIntegration.js +3 -3
- package/build/npm/esm/prod/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/prod/tracing/request.js +10 -2
- package/build/npm/esm/prod/tracing/request.js.map +1 -1
- package/build/npm/types/index.d.ts +1 -1
- package/build/npm/types/index.d.ts.map +1 -1
- package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
- package/build/npm/types/integrations/webVitals.d.ts.map +1 -1
- package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
- package/build/npm/types/tracing/request.d.ts.map +1 -1
- package/build/npm/types-ts3.8/index.d.ts +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type {\n Client,\n HandlerDataXhr,\n RequestHookInfo,\n ResponseHookInfo,\n SentryWrappedXMLHttpRequest,\n Span,\n SpanTimeInput,\n} from '@sentry/core/browser';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getLocationHref,\n getTraceData,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanToJSON,\n startInactiveSpan,\n stringMatchesSomePattern,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core/browser';\nimport type { XhrHint } from '@sentry/browser-utils';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\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 *\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 * Flag to disable tracking of long-lived streams, like server-sent events (SSE) via fetch.\n * Do not enable this in case you have live streams or very long running streams.\n *\n * Disabled by default since it can lead to issues with streams using the `cancel()` api\n * (https://github.com/getsentry/sentry-javascript/issues/13950)\n *\n * Default: false\n *\n * @deprecated Use `fetchStreamPerformanceIntegration()` instead. Add it to your `integrations` array\n * to track the duration of streamed fetch response bodies.\n */\n trackFetchStreamPerformance: 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 trackFetchStreamPerformance: false,\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 });\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 const host = fullUrl ? parseUrl(fullUrl).host : undefined;\n createdSpan.setAttributes({\n 'http.url': fullUrl ? stripDataUrlContent(fullUrl) : undefined,\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` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const { url } = spanToJSON(span).data;\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 stringMatchesSomePattern(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 stringMatchesSomePattern(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && stringMatchesSomePattern(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 */\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\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 const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: `${method} ${urlForSpanName}`,\n attributes: {\n url: stripDataUrlContent(url),\n type: 'xhr',\n 'http.method': method,\n 'http.url': fullUrl ? stripDataUrlContent(fullUrl) : undefined,\n 'server.address': parsedUrl?.host,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\n ...(parsedUrl?.search && { 'http.query': parsedUrl?.search }),\n ...(parsedUrl?.hash && { 'http.fragment': parsedUrl?.hash }),\n },\n })\n : new SentryNonRecordingSpan();\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 ? span : 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 {\n Client,\n HandlerDataXhr,\n RequestHookInfo,\n ResponseHookInfo,\n SentryWrappedXMLHttpRequest,\n Span,\n SpanTimeInput,\n} from '@sentry/core/browser';\nimport {\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getLocationHref,\n getTraceData,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanToJSON,\n startInactiveSpan,\n stringMatchesSomePattern,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core/browser';\nimport type { XhrHint } from '@sentry/browser-utils';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\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 *\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 * Flag to disable tracking of long-lived streams, like server-sent events (SSE) via fetch.\n * Do not enable this in case you have live streams or very long running streams.\n *\n * Disabled by default since it can lead to issues with streams using the `cancel()` api\n * (https://github.com/getsentry/sentry-javascript/issues/13950)\n *\n * Default: false\n *\n * @deprecated Use `fetchStreamPerformanceIntegration()` instead. Add it to your `integrations` array\n * to track the duration of streamed fetch response bodies.\n */\n trackFetchStreamPerformance: 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 trackFetchStreamPerformance: false,\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 });\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 const host = fullUrl ? parseUrl(fullUrl).host : undefined;\n const sanitizedFullUrl = fullUrl ? stripDataUrlContent(fullUrl) : undefined;\n createdSpan.setAttributes({\n 'http.url': sanitizedFullUrl,\n // `url.full` must match `http.url`. Setting it here ensures parentless `http.client`\n // segment spans don't get `url.full` backfilled with the host page URL (see httpContextIntegration).\n 'url.full': 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` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const { url } = spanToJSON(span).data;\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 stringMatchesSomePattern(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 stringMatchesSomePattern(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && stringMatchesSomePattern(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 */\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 const span =\n shouldCreateSpanResult && shouldEmitSpan\n ? startInactiveSpan({\n name: `${method} ${urlForSpanName}`,\n attributes: {\n url: stripDataUrlContent(url),\n type: 'xhr',\n 'http.method': method,\n 'http.url': sanitizedFullUrl,\n // `url.full` must match `http.url`. Setting it here ensures parentless `http.client`\n // segment spans don't get `url.full` backfilled with the host page URL (see httpContextIntegration).\n 'url.full': sanitizedFullUrl,\n 'server.address': parsedUrl?.host,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\n ...(parsedUrl?.search && { 'http.query': parsedUrl?.search }),\n ...(parsedUrl?.hash && { 'http.fragment': parsedUrl?.hash }),\n },\n })\n : new SentryNonRecordingSpan();\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 ? span : 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":"client.js","sources":["../../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options as CoreOptions,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core/browser';\nimport {\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_flushMetricsBuffer,\n addAutoIpAddressToSession,\n applySdkMetadata,\n Client,\n getSDKSource,\n} from '@sentry/core/browser';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * A magic string that build tooling can leverage in order to inject a release value into the SDK.\n */\ndeclare const __SENTRY_RELEASE__: string | undefined;\n\ntype BrowserSpecificOptions = BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n };\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = CoreOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = applyDefaultOptions(options);\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n super(opts);\n\n const { userInfo } = this.getDataCollectionOptions();\n\n if (opts._metadata?.sdk) {\n opts._metadata.sdk.settings = {\n // Only allow IP inferral by Relay if the user opted in via dataCollection\n infer_ip: userInfo ? 'auto' : 'never',\n // purposefully allowing already passed settings to override the default\n ...opts._metadata.sdk.settings,\n };\n }\n\n const { sendClientReports, enableLogs, _experiments, enableMetrics: enableMetricsOption } = this._options;\n\n // todo(v11): Remove the experimental flag\n // eslint-disable-next-line
|
|
1
|
+
{"version":3,"file":"client.js","sources":["../../../../src/client.ts"],"sourcesContent":["import type {\n BrowserClientProfilingOptions,\n BrowserClientReplayOptions,\n ClientOptions,\n Event,\n EventHint,\n Options as CoreOptions,\n ParameterizedString,\n Scope,\n SeverityLevel,\n} from '@sentry/core/browser';\nimport {\n _INTERNAL_flushLogsBuffer,\n _INTERNAL_flushMetricsBuffer,\n addAutoIpAddressToSession,\n applySdkMetadata,\n Client,\n getSDKSource,\n} from '@sentry/core/browser';\nimport { eventFromException, eventFromMessage } from './eventbuilder';\nimport { WINDOW } from './helpers';\nimport type { BrowserTransportOptions } from './transports/types';\n\n/**\n * A magic string that build tooling can leverage in order to inject a release value into the SDK.\n */\ndeclare const __SENTRY_RELEASE__: string | undefined;\n\ntype BrowserSpecificOptions = BrowserClientReplayOptions &\n BrowserClientProfilingOptions & {\n /** If configured, this URL will be used as base URL for lazy loading integration. */\n cdnBaseUrl?: string;\n\n /**\n * Important: Only set this option if you know what you are doing!\n *\n * By default, the SDK will check if `Sentry.init` is called in a browser extension.\n * In case it is, it will stop initialization and log a warning\n * because browser extensions require a different Sentry initialization process:\n * https://docs.sentry.io/platforms/javascript/best-practices/shared-environments/\n *\n * Setting up the SDK in a browser extension with global error monitoring is not recommended\n * and will likely flood you with errors from other web sites or extensions. This can heavily\n * impact your quota and cause interference with your and other Sentry SDKs in shared environments.\n *\n * If this check wrongfully flags your setup as a browser extension, you can set this\n * option to `true` to skip the check.\n *\n * @default false\n */\n skipBrowserExtensionCheck?: boolean;\n\n /**\n * If you use Spotlight by Sentry during development, use\n * this option to forward captured Sentry events to Spotlight.\n *\n * Either set it to true, or provide a specific Spotlight Sidecar URL.\n *\n * More details: https://spotlightjs.com/\n *\n * IMPORTANT: Only set this option to `true` while developing, not in production!\n */\n spotlight?: boolean | string;\n };\n/**\n * Configuration options for the Sentry Browser SDK.\n * @see @sentry/core Options for more information.\n */\nexport type BrowserOptions = CoreOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * Configuration options for the Sentry Browser SDK Client class\n * @see BrowserClient for more information.\n */\nexport type BrowserClientOptions = ClientOptions<BrowserTransportOptions> & BrowserSpecificOptions;\n\n/**\n * The Sentry Browser SDK Client.\n *\n * @see BrowserOptions for documentation on configuration options.\n * @see SentryClient for usage documentation.\n */\nexport class BrowserClient extends Client<BrowserClientOptions> {\n /**\n * Creates a new Browser SDK instance.\n *\n * @param options Configuration options for this SDK.\n */\n public constructor(options: BrowserClientOptions) {\n const opts = applyDefaultOptions(options);\n const sdkSource = WINDOW.SENTRY_SDK_SOURCE || getSDKSource();\n applySdkMetadata(opts, 'browser', ['browser'], sdkSource);\n\n super(opts);\n\n const { userInfo } = this.getDataCollectionOptions();\n\n if (opts._metadata?.sdk) {\n opts._metadata.sdk.settings = {\n // Only allow IP inferral by Relay if the user opted in via dataCollection\n infer_ip: userInfo ? 'auto' : 'never',\n // purposefully allowing already passed settings to override the default\n ...opts._metadata.sdk.settings,\n };\n }\n\n const { sendClientReports, enableLogs, _experiments, enableMetrics: enableMetricsOption } = this._options;\n\n // todo(v11): Remove the experimental flag\n // eslint-disable-next-line typescript/no-deprecated\n const enableMetrics = enableMetricsOption ?? _experiments?.enableMetrics ?? true;\n\n // Flush logs and metrics when page becomes hidden (e.g., tab switch, navigation)\n // todo(v11): Remove the experimental flag\n if (WINDOW.document && (sendClientReports || enableLogs || enableMetrics)) {\n WINDOW.document.addEventListener('visibilitychange', () => {\n if (WINDOW.document.visibilityState === 'hidden') {\n if (sendClientReports) {\n this._flushOutcomes();\n }\n if (enableLogs) {\n _INTERNAL_flushLogsBuffer(this);\n }\n\n if (enableMetrics) {\n _INTERNAL_flushMetricsBuffer(this);\n }\n }\n });\n }\n\n if (userInfo) {\n this.on('beforeSendSession', addAutoIpAddressToSession);\n }\n }\n\n /**\n * @inheritDoc\n */\n public eventFromException(exception: unknown, hint?: EventHint): PromiseLike<Event> {\n return eventFromException(this._options.stackParser, exception, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n public eventFromMessage(\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n ): PromiseLike<Event> {\n return eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace);\n }\n\n /**\n * @inheritDoc\n */\n protected _prepareEvent(\n event: Event,\n hint: EventHint,\n currentScope: Scope,\n isolationScope: Scope,\n ): PromiseLike<Event | null> {\n event.platform = event.platform || 'javascript';\n\n return super._prepareEvent(event, hint, currentScope, isolationScope);\n }\n}\n\n/** Exported only for tests. */\nexport function applyDefaultOptions<T extends Partial<BrowserClientOptions>>(optionsArg: T): T {\n return {\n release:\n typeof __SENTRY_RELEASE__ === 'string' // This allows build tooling to find-and-replace __SENTRY_RELEASE__ to inject a release value\n ? __SENTRY_RELEASE__\n : WINDOW.SENTRY_RELEASE?.id, // This supports the variable that sentry-webpack-plugin injects\n sendClientReports: true,\n // We default this to true, as it is the safer scenario\n parentSpanIsAlwaysRootSpan: true,\n ...optionsArg,\n };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"eventbuilder.js","sources":["../../../../src/eventbuilder.ts"],"sourcesContent":["import type {\n Event,\n EventHint,\n Exception,\n ParameterizedString,\n SeverityLevel,\n StackFrame,\n StackParser,\n} from '@sentry/core/browser';\nimport {\n _INTERNAL_enhanceErrorWithSentryInfo,\n addExceptionMechanism,\n addExceptionTypeValue,\n extractExceptionKeysForMessage,\n getClient,\n isDOMError,\n isDOMException,\n isError,\n isErrorEvent,\n isEvent,\n isParameterizedString,\n isPlainObject,\n normalizeToSize,\n resolvedSyncPromise,\n} from '@sentry/core/browser';\n\ntype Prototype = { constructor: (...args: unknown[]) => unknown };\n\n/**\n * This function creates an exception from a JavaScript Error\n */\nexport function exceptionFromError(stackParser: StackParser, ex: Error): Exception {\n // Get the frames first since Opera can lose the stack if we touch anything else first\n const frames = parseStackFrames(stackParser, ex);\n\n const exception: Exception = {\n type: extractType(ex),\n value: extractMessage(ex),\n };\n\n if (frames.length) {\n exception.stacktrace = { frames };\n }\n\n if (exception.type === undefined && exception.value === '') {\n exception.value = 'Unrecoverable error caught';\n }\n\n return exception;\n}\n\nfunction eventFromPlainObject(\n stackParser: StackParser,\n exception: Record<string, unknown>,\n syntheticException?: Error,\n isUnhandledRejection?: boolean,\n): Event {\n const client = getClient();\n const normalizeDepth = client?.getOptions().normalizeDepth;\n\n // If we can, we extract an exception from the object properties\n const errorFromProp = getErrorPropertyFromObject(exception);\n\n const extra = {\n __serialized__: normalizeToSize(exception, normalizeDepth),\n };\n\n if (errorFromProp) {\n return {\n exception: {\n values: [exceptionFromError(stackParser, errorFromProp)],\n },\n extra,\n };\n }\n\n const event = {\n exception: {\n values: [\n {\n type: isEvent(exception) ? exception.constructor.name : isUnhandledRejection ? 'UnhandledRejection' : 'Error',\n value: getNonErrorObjectExceptionValue(exception, { isUnhandledRejection }),\n } as Exception,\n ],\n },\n extra,\n } satisfies Event;\n\n if (syntheticException) {\n const frames = parseStackFrames(stackParser, syntheticException);\n if (frames.length) {\n // event.exception.values[0] has been set above\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n event.exception.values[0]!.stacktrace = { frames };\n }\n }\n\n return event;\n}\n\nfunction eventFromError(stackParser: StackParser, ex: Error): Event {\n return {\n exception: {\n values: [exceptionFromError(stackParser, ex)],\n },\n };\n}\n\n/** Parses stack frames from an error */\nfunction parseStackFrames(\n stackParser: StackParser,\n ex: Error & { framesToPop?: number; stacktrace?: string },\n): StackFrame[] {\n // Access and store the stacktrace property before doing ANYTHING\n // else to it because Opera is not very good at providing it\n // reliably in other circumstances.\n const stacktrace = ex.stacktrace || ex.stack || '';\n\n const skipLines = getSkipFirstStackStringLines(ex);\n const framesToPop = getPopFirstTopFrames(ex);\n\n try {\n return stackParser(stacktrace, skipLines, framesToPop);\n } catch {\n // no-empty\n }\n\n return [];\n}\n\n// Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108\nconst reactMinifiedRegexp = /Minified React error #\\d+;/i;\n\n/**\n * Certain known React errors contain links that would be falsely\n * parsed as frames. This function check for these errors and\n * returns number of the stack string lines to skip.\n */\nfunction getSkipFirstStackStringLines(ex: Error): number {\n if (ex && reactMinifiedRegexp.test(ex.message)) {\n return 1;\n }\n\n return 0;\n}\n\n/**\n * If error has `framesToPop` property, it means that the\n * creator tells us the first x frames will be useless\n * and should be discarded. Typically error from wrapper function\n * which don't point to the actual location in the developer's code.\n *\n * Example: https://github.com/zertosh/invariant/blob/master/invariant.js#L46\n */\nfunction getPopFirstTopFrames(ex: Error & { framesToPop?: unknown }): number {\n if (typeof ex.framesToPop === 'number') {\n return ex.framesToPop;\n }\n\n return 0;\n}\n\n// https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Exception\n// @ts-expect-error - WebAssembly.Exception is a valid class\nfunction isWebAssemblyException(exception: unknown): exception is WebAssembly.Exception {\n // Check for support\n // @ts-expect-error - WebAssembly.Exception is a valid class\n // oxlint-disable-next-line typescript/prefer-optional-chain\n if (typeof WebAssembly !== 'undefined' && typeof WebAssembly.Exception !== 'undefined') {\n // @ts-expect-error - WebAssembly.Exception is a valid class\n return exception instanceof WebAssembly.Exception;\n } else {\n return false;\n }\n}\n\n/**\n * Extracts from errors what we use as the exception `type` in error events.\n *\n * Usually, this is the `name` property on Error objects but WASM errors need to be treated differently.\n */\nexport function extractType(ex: Error & { message: { error?: Error } }): string | undefined {\n const name = ex?.name;\n\n // The name for WebAssembly.Exception Errors needs to be extracted differently.\n // Context: https://github.com/getsentry/sentry-javascript/issues/13787\n if (!name && isWebAssemblyException(ex)) {\n // Emscripten sets array[type, message] to the \"message\" property on the WebAssembly.Exception object\n const hasTypeInMessage = ex.message && Array.isArray(ex.message) && ex.message.length == 2;\n return hasTypeInMessage ? ex.message[0] : 'WebAssembly.Exception';\n }\n\n return name;\n}\n\n/**\n * There are cases where stacktrace.message is an Event object\n * https://github.com/getsentry/sentry-javascript/issues/1949\n * In this specific case we try to extract stacktrace.message.error.message\n */\nexport function extractMessage(ex: Error & { message: { error?: Error } }): string {\n const message = ex?.message;\n\n if (isWebAssemblyException(ex)) {\n // For Node 18, Emscripten sets array[type, message] to the \"message\" property on the WebAssembly.Exception object\n if (Array.isArray(ex.message) && ex.message.length == 2) {\n return ex.message[1];\n }\n return 'wasm exception';\n }\n\n if (!message) {\n return 'No error message';\n }\n\n if (message.error && typeof message.error.message === 'string') {\n return _INTERNAL_enhanceErrorWithSentryInfo(message.error);\n }\n\n return _INTERNAL_enhanceErrorWithSentryInfo(ex);\n}\n\n/**\n * Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`.\n * @hidden\n */\nexport function eventFromException(\n stackParser: StackParser,\n exception: unknown,\n hint?: EventHint,\n attachStacktrace?: boolean,\n): PromiseLike<Event> {\n const syntheticException = hint?.syntheticException || undefined;\n const event = eventFromUnknownInput(stackParser, exception, syntheticException, attachStacktrace);\n addExceptionMechanism(event); // defaults to { type: 'generic', handled: true }\n event.level = 'error';\n if (hint?.event_id) {\n event.event_id = hint.event_id;\n }\n return resolvedSyncPromise(event);\n}\n\n/**\n * Builds and Event from a Message\n * @hidden\n */\nexport function eventFromMessage(\n stackParser: StackParser,\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n attachStacktrace?: boolean,\n): PromiseLike<Event> {\n const syntheticException = hint?.syntheticException || undefined;\n const event = eventFromString(stackParser, message, syntheticException, attachStacktrace);\n event.level = level;\n if (hint?.event_id) {\n event.event_id = hint.event_id;\n }\n return resolvedSyncPromise(event);\n}\n\n/**\n * @hidden\n */\nexport function eventFromUnknownInput(\n stackParser: StackParser,\n exception: unknown,\n syntheticException?: Error,\n attachStacktrace?: boolean,\n isUnhandledRejection?: boolean,\n): Event {\n let event: Event;\n\n if (isErrorEvent(exception as ErrorEvent) && (exception as ErrorEvent).error) {\n // If it is an ErrorEvent with `error` property, extract it to get actual Error\n const errorEvent = exception as ErrorEvent;\n return eventFromError(stackParser, errorEvent.error as Error);\n }\n\n // If it is a `DOMError` (which is a legacy API, but still supported in some browsers) then we just extract the name\n // and message, as it doesn't provide anything else. According to the spec, all `DOMExceptions` should also be\n // `Error`s, but that's not the case in IE11, so in that case we treat it the same as we do a `DOMError`.\n //\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMError\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMException\n // https://webidl.spec.whatwg.org/#es-DOMException-specialness\n if (isDOMError(exception) || isDOMException(exception as DOMException)) {\n const domException = exception as DOMException;\n\n if ('stack' in (exception as Error)) {\n event = eventFromError(stackParser, exception as Error);\n\n const firstException = event.exception?.values?.[0];\n if (attachStacktrace && syntheticException && firstException && !firstException.stacktrace) {\n const frames = parseStackFrames(stackParser, syntheticException);\n if (frames.length) {\n firstException.stacktrace = { frames };\n addExceptionMechanism(event, { synthetic: true });\n }\n }\n } else {\n const name = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException');\n const message = domException.message ? `${name}: ${domException.message}` : name;\n event = eventFromString(stackParser, message, syntheticException, attachStacktrace);\n addExceptionTypeValue(event, message);\n }\n if ('code' in domException) {\n // eslint-disable-next-line deprecation/deprecation\n event.tags = { ...event.tags, 'DOMException.code': `${domException.code}` };\n }\n\n return event;\n }\n if (isError(exception)) {\n // we have a real Error object, do nothing\n return eventFromError(stackParser, exception);\n }\n if (isPlainObject(exception) || isEvent(exception)) {\n // If it's a plain object or an instance of `Event` (the built-in JS kind, not this SDK's `Event` type), serialize\n // it manually. This will allow us to group events based on top-level keys which is much better than creating a new\n // group on any key/value change.\n const objectException = exception;\n event = eventFromPlainObject(stackParser, objectException, syntheticException, isUnhandledRejection);\n addExceptionMechanism(event, {\n synthetic: true,\n });\n return event;\n }\n\n // If none of previous checks were valid, then it means that it's not:\n // - an instance of DOMError\n // - an instance of DOMException\n // - an instance of Event\n // - an instance of Error\n // - a valid ErrorEvent (one with an error property)\n // - a plain Object\n //\n // So bail out and capture it as a simple message:\n event = eventFromString(stackParser, exception as string, syntheticException, attachStacktrace);\n addExceptionTypeValue(event, `${exception}`, undefined);\n addExceptionMechanism(event, {\n synthetic: true,\n });\n\n return event;\n}\n\nfunction eventFromString(\n stackParser: StackParser,\n message: ParameterizedString,\n syntheticException?: Error,\n attachStacktrace?: boolean,\n): Event {\n const event: Event = {};\n\n if (attachStacktrace && syntheticException) {\n const frames = parseStackFrames(stackParser, syntheticException);\n if (frames.length) {\n event.exception = {\n values: [{ value: message, stacktrace: { frames } }],\n };\n }\n addExceptionMechanism(event, { synthetic: true });\n }\n\n if (isParameterizedString(message)) {\n const { __sentry_template_string__, __sentry_template_values__ } = message;\n\n event.logentry = {\n message: __sentry_template_string__,\n params: __sentry_template_values__,\n };\n return event;\n }\n\n event.message = message;\n return event;\n}\n\nfunction getNonErrorObjectExceptionValue(\n exception: Record<string, unknown>,\n { isUnhandledRejection }: { isUnhandledRejection?: boolean },\n): string {\n const keys = extractExceptionKeysForMessage(exception);\n const captureType = isUnhandledRejection ? 'promise rejection' : 'exception';\n\n // Some ErrorEvent instances do not have an `error` property, which is why they are not handled before\n // We still want to try to get a decent message for these cases\n if (isErrorEvent(exception)) {\n return `Event \\`ErrorEvent\\` captured as ${captureType} with message \\`${exception.message}\\``;\n }\n\n if (isEvent(exception)) {\n const className = getObjectClassName(exception);\n return `Event \\`${className}\\` (type=${exception.type}) captured as ${captureType}`;\n }\n\n return `Object captured as ${captureType} with keys: ${keys}`;\n}\n\nfunction getObjectClassName(obj: unknown): string | undefined | void {\n try {\n const prototype: Prototype | null = Object.getPrototypeOf(obj);\n return prototype ? prototype.constructor.name : undefined;\n } catch {\n // ignore errors here\n }\n}\n\n/** If a plain object has a property that is an `Error`, return this error. */\nfunction getErrorPropertyFromObject(obj: Record<string, unknown>): Error | undefined {\n return Object.values(obj).find((v): v is Error => v instanceof Error);\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"eventbuilder.js","sources":["../../../../src/eventbuilder.ts"],"sourcesContent":["import type {\n Event,\n EventHint,\n Exception,\n ParameterizedString,\n SeverityLevel,\n StackFrame,\n StackParser,\n} from '@sentry/core/browser';\nimport {\n _INTERNAL_enhanceErrorWithSentryInfo,\n addExceptionMechanism,\n addExceptionTypeValue,\n extractExceptionKeysForMessage,\n getClient,\n isDOMError,\n isDOMException,\n isError,\n isErrorEvent,\n isEvent,\n isParameterizedString,\n isPlainObject,\n normalizeToSize,\n resolvedSyncPromise,\n} from '@sentry/core/browser';\n\ntype Prototype = { constructor: (...args: unknown[]) => unknown };\n\n/**\n * This function creates an exception from a JavaScript Error\n */\nexport function exceptionFromError(stackParser: StackParser, ex: Error): Exception {\n // Get the frames first since Opera can lose the stack if we touch anything else first\n const frames = parseStackFrames(stackParser, ex);\n\n const exception: Exception = {\n type: extractType(ex),\n value: extractMessage(ex),\n };\n\n if (frames.length) {\n exception.stacktrace = { frames };\n }\n\n if (exception.type === undefined && exception.value === '') {\n exception.value = 'Unrecoverable error caught';\n }\n\n return exception;\n}\n\nfunction eventFromPlainObject(\n stackParser: StackParser,\n exception: Record<string, unknown>,\n syntheticException?: Error,\n isUnhandledRejection?: boolean,\n): Event {\n const client = getClient();\n const normalizeDepth = client?.getOptions().normalizeDepth;\n\n // If we can, we extract an exception from the object properties\n const errorFromProp = getErrorPropertyFromObject(exception);\n\n const extra = {\n __serialized__: normalizeToSize(exception, normalizeDepth),\n };\n\n if (errorFromProp) {\n return {\n exception: {\n values: [exceptionFromError(stackParser, errorFromProp)],\n },\n extra,\n };\n }\n\n const event = {\n exception: {\n values: [\n {\n type: isEvent(exception) ? exception.constructor.name : isUnhandledRejection ? 'UnhandledRejection' : 'Error',\n value: getNonErrorObjectExceptionValue(exception, { isUnhandledRejection }),\n } as Exception,\n ],\n },\n extra,\n } satisfies Event;\n\n if (syntheticException) {\n const frames = parseStackFrames(stackParser, syntheticException);\n if (frames.length) {\n // event.exception.values[0] has been set above\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n event.exception.values[0]!.stacktrace = { frames };\n }\n }\n\n return event;\n}\n\nfunction eventFromError(stackParser: StackParser, ex: Error): Event {\n return {\n exception: {\n values: [exceptionFromError(stackParser, ex)],\n },\n };\n}\n\n/** Parses stack frames from an error */\nfunction parseStackFrames(\n stackParser: StackParser,\n ex: Error & { framesToPop?: number; stacktrace?: string },\n): StackFrame[] {\n // Access and store the stacktrace property before doing ANYTHING\n // else to it because Opera is not very good at providing it\n // reliably in other circumstances.\n const stacktrace = ex.stacktrace || ex.stack || '';\n\n const skipLines = getSkipFirstStackStringLines(ex);\n const framesToPop = getPopFirstTopFrames(ex);\n\n try {\n return stackParser(stacktrace, skipLines, framesToPop);\n } catch {\n // no-empty\n }\n\n return [];\n}\n\n// Based on our own mapping pattern - https://github.com/getsentry/sentry/blob/9f08305e09866c8bd6d0c24f5b0aabdd7dd6c59c/src/sentry/lang/javascript/errormapping.py#L83-L108\nconst reactMinifiedRegexp = /Minified React error #\\d+;/i;\n\n/**\n * Certain known React errors contain links that would be falsely\n * parsed as frames. This function check for these errors and\n * returns number of the stack string lines to skip.\n */\nfunction getSkipFirstStackStringLines(ex: Error): number {\n if (ex && reactMinifiedRegexp.test(ex.message)) {\n return 1;\n }\n\n return 0;\n}\n\n/**\n * If error has `framesToPop` property, it means that the\n * creator tells us the first x frames will be useless\n * and should be discarded. Typically error from wrapper function\n * which don't point to the actual location in the developer's code.\n *\n * Example: https://github.com/zertosh/invariant/blob/master/invariant.js#L46\n */\nfunction getPopFirstTopFrames(ex: Error & { framesToPop?: unknown }): number {\n if (typeof ex.framesToPop === 'number') {\n return ex.framesToPop;\n }\n\n return 0;\n}\n\n// https://developer.mozilla.org/en-US/docs/WebAssembly/JavaScript_interface/Exception\n// @ts-expect-error - WebAssembly.Exception is a valid class\nfunction isWebAssemblyException(exception: unknown): exception is WebAssembly.Exception {\n // Check for support\n // @ts-expect-error - WebAssembly.Exception is a valid class\n // oxlint-disable-next-line typescript/prefer-optional-chain\n if (typeof WebAssembly !== 'undefined' && typeof WebAssembly.Exception !== 'undefined') {\n // @ts-expect-error - WebAssembly.Exception is a valid class\n return exception instanceof WebAssembly.Exception;\n } else {\n return false;\n }\n}\n\n/**\n * Extracts from errors what we use as the exception `type` in error events.\n *\n * Usually, this is the `name` property on Error objects but WASM errors need to be treated differently.\n */\nexport function extractType(ex: Error & { message: { error?: Error } }): string | undefined {\n const name = ex?.name;\n\n // The name for WebAssembly.Exception Errors needs to be extracted differently.\n // Context: https://github.com/getsentry/sentry-javascript/issues/13787\n if (!name && isWebAssemblyException(ex)) {\n // Emscripten sets array[type, message] to the \"message\" property on the WebAssembly.Exception object\n const hasTypeInMessage = ex.message && Array.isArray(ex.message) && ex.message.length == 2;\n return hasTypeInMessage ? ex.message[0] : 'WebAssembly.Exception';\n }\n\n return name;\n}\n\n/**\n * There are cases where stacktrace.message is an Event object\n * https://github.com/getsentry/sentry-javascript/issues/1949\n * In this specific case we try to extract stacktrace.message.error.message\n */\nexport function extractMessage(ex: Error & { message: { error?: Error } }): string {\n const message = ex?.message;\n\n if (isWebAssemblyException(ex)) {\n // For Node 18, Emscripten sets array[type, message] to the \"message\" property on the WebAssembly.Exception object\n if (Array.isArray(ex.message) && ex.message.length == 2) {\n return ex.message[1];\n }\n return 'wasm exception';\n }\n\n if (!message) {\n return 'No error message';\n }\n\n if (message.error && typeof message.error.message === 'string') {\n return _INTERNAL_enhanceErrorWithSentryInfo(message.error);\n }\n\n return _INTERNAL_enhanceErrorWithSentryInfo(ex);\n}\n\n/**\n * Creates an {@link Event} from all inputs to `captureException` and non-primitive inputs to `captureMessage`.\n * @hidden\n */\nexport function eventFromException(\n stackParser: StackParser,\n exception: unknown,\n hint?: EventHint,\n attachStacktrace?: boolean,\n): PromiseLike<Event> {\n const syntheticException = hint?.syntheticException || undefined;\n const event = eventFromUnknownInput(stackParser, exception, syntheticException, attachStacktrace);\n addExceptionMechanism(event); // defaults to { type: 'generic', handled: true }\n event.level = 'error';\n if (hint?.event_id) {\n event.event_id = hint.event_id;\n }\n return resolvedSyncPromise(event);\n}\n\n/**\n * Builds and Event from a Message\n * @hidden\n */\nexport function eventFromMessage(\n stackParser: StackParser,\n message: ParameterizedString,\n level: SeverityLevel = 'info',\n hint?: EventHint,\n attachStacktrace?: boolean,\n): PromiseLike<Event> {\n const syntheticException = hint?.syntheticException || undefined;\n const event = eventFromString(stackParser, message, syntheticException, attachStacktrace);\n event.level = level;\n if (hint?.event_id) {\n event.event_id = hint.event_id;\n }\n return resolvedSyncPromise(event);\n}\n\n/**\n * @hidden\n */\nexport function eventFromUnknownInput(\n stackParser: StackParser,\n exception: unknown,\n syntheticException?: Error,\n attachStacktrace?: boolean,\n isUnhandledRejection?: boolean,\n): Event {\n let event: Event;\n\n if (isErrorEvent(exception as ErrorEvent) && (exception as ErrorEvent).error) {\n // If it is an ErrorEvent with `error` property, extract it to get actual Error\n const errorEvent = exception as ErrorEvent;\n return eventFromError(stackParser, errorEvent.error as Error);\n }\n\n // If it is a `DOMError` (which is a legacy API, but still supported in some browsers) then we just extract the name\n // and message, as it doesn't provide anything else. According to the spec, all `DOMExceptions` should also be\n // `Error`s, but that's not the case in IE11, so in that case we treat it the same as we do a `DOMError`.\n //\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMError\n // https://developer.mozilla.org/en-US/docs/Web/API/DOMException\n // https://webidl.spec.whatwg.org/#es-DOMException-specialness\n if (isDOMError(exception) || isDOMException(exception as DOMException)) {\n const domException = exception as DOMException;\n\n if ('stack' in (exception as Error)) {\n event = eventFromError(stackParser, exception as Error);\n\n const firstException = event.exception?.values?.[0];\n if (attachStacktrace && syntheticException && firstException && !firstException.stacktrace) {\n const frames = parseStackFrames(stackParser, syntheticException);\n if (frames.length) {\n firstException.stacktrace = { frames };\n addExceptionMechanism(event, { synthetic: true });\n }\n }\n } else {\n const name = domException.name || (isDOMError(domException) ? 'DOMError' : 'DOMException');\n const message = domException.message ? `${name}: ${domException.message}` : name;\n event = eventFromString(stackParser, message, syntheticException, attachStacktrace);\n addExceptionTypeValue(event, message);\n }\n if ('code' in domException) {\n // eslint-disable-next-line typescript/no-deprecated\n event.tags = { ...event.tags, 'DOMException.code': `${domException.code}` };\n }\n\n return event;\n }\n if (isError(exception)) {\n // we have a real Error object, do nothing\n return eventFromError(stackParser, exception);\n }\n if (isPlainObject(exception) || isEvent(exception)) {\n // If it's a plain object or an instance of `Event` (the built-in JS kind, not this SDK's `Event` type), serialize\n // it manually. This will allow us to group events based on top-level keys which is much better than creating a new\n // group on any key/value change.\n const objectException = exception;\n event = eventFromPlainObject(stackParser, objectException, syntheticException, isUnhandledRejection);\n addExceptionMechanism(event, {\n synthetic: true,\n });\n return event;\n }\n\n // If none of previous checks were valid, then it means that it's not:\n // - an instance of DOMError\n // - an instance of DOMException\n // - an instance of Event\n // - an instance of Error\n // - a valid ErrorEvent (one with an error property)\n // - a plain Object\n //\n // So bail out and capture it as a simple message:\n event = eventFromString(stackParser, exception as string, syntheticException, attachStacktrace);\n addExceptionTypeValue(event, `${exception}`, undefined);\n addExceptionMechanism(event, {\n synthetic: true,\n });\n\n return event;\n}\n\nfunction eventFromString(\n stackParser: StackParser,\n message: ParameterizedString,\n syntheticException?: Error,\n attachStacktrace?: boolean,\n): Event {\n const event: Event = {};\n\n if (attachStacktrace && syntheticException) {\n const frames = parseStackFrames(stackParser, syntheticException);\n if (frames.length) {\n event.exception = {\n values: [{ value: message, stacktrace: { frames } }],\n };\n }\n addExceptionMechanism(event, { synthetic: true });\n }\n\n if (isParameterizedString(message)) {\n const { __sentry_template_string__, __sentry_template_values__ } = message;\n\n event.logentry = {\n message: __sentry_template_string__,\n params: __sentry_template_values__,\n };\n return event;\n }\n\n event.message = message;\n return event;\n}\n\nfunction getNonErrorObjectExceptionValue(\n exception: Record<string, unknown>,\n { isUnhandledRejection }: { isUnhandledRejection?: boolean },\n): string {\n const keys = extractExceptionKeysForMessage(exception);\n const captureType = isUnhandledRejection ? 'promise rejection' : 'exception';\n\n // Some ErrorEvent instances do not have an `error` property, which is why they are not handled before\n // We still want to try to get a decent message for these cases\n if (isErrorEvent(exception)) {\n return `Event \\`ErrorEvent\\` captured as ${captureType} with message \\`${exception.message}\\``;\n }\n\n if (isEvent(exception)) {\n const className = getObjectClassName(exception);\n return `Event \\`${className}\\` (type=${exception.type}) captured as ${captureType}`;\n }\n\n return `Object captured as ${captureType} with keys: ${keys}`;\n}\n\nfunction getObjectClassName(obj: unknown): string | undefined | void {\n try {\n const prototype: Prototype | null = Object.getPrototypeOf(obj);\n return prototype ? prototype.constructor.name : undefined;\n } catch {\n // ignore errors here\n }\n}\n\n/** If a plain object has a property that is an `Error`, return this error. */\nfunction getErrorPropertyFromObject(obj: Record<string, unknown>): Error | undefined {\n return Object.values(obj).find((v): v is Error => v instanceof Error);\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export { feedbackAsyncIntegration } from './feedbackAsync.js';
|
|
2
2
|
export { feedbackSyncIntegration as feedbackIntegration, feedbackSyncIntegration } from './feedbackSync.js';
|
|
3
|
-
export { MULTIPLEXED_TRANSPORT_EXTRA_KEY, SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentCreateReactAgent, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentLangGraph, instrumentOpenAiClient, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, logger, makeMultiplexedTransport, metrics, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, withStreamedSpan, zodErrorsIntegration } from '@sentry/core/browser';
|
|
3
|
+
export { MULTIPLEXED_TRANSPORT_EXTRA_KEY, SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleLoggingIntegration, continueTrace, createConsolaReporter, createLangChainCallbackHandler, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, inboundFiltersIntegration, instrumentAnthropicAiClient, instrumentCreateReactAgent, instrumentGoogleGenAIClient, instrumentLangChainEmbeddings, instrumentLangGraph, instrumentOpenAiClient, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, logger, makeMultiplexedTransport, metrics, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanToBaggageHeader, spanToJSON, spanToTraceHeader, startInactiveSpan, startNewTrace, startSession, startSpan, startSpanManual, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, withStreamedSpan, zodErrorsIntegration } from '@sentry/core/browser';
|
|
4
4
|
export { WINDOW } from './helpers.js';
|
|
5
5
|
export { BrowserClient } from './client.js';
|
|
6
6
|
export { makeFetchTransport } from './transports/fetch.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpclient.js","sources":["../../../../../src/integrations/httpclient.ts"],"sourcesContent":["import type { Client, Event as SentryEvent, IntegrationFn, SentryWrappedXMLHttpRequest } from '@sentry/core/browser';\nimport {\n _INTERNAL_filterCookies,\n _INTERNAL_filterKeyValueData,\n addExceptionMechanism,\n addFetchInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n GLOBAL_OBJ,\n isSentryRequestUrl,\n supportsNativeFetch,\n} from '@sentry/core/browser';\nimport { addXhrInstrumentationHandler, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport type HttpStatusCodeRange = [number, number] | number;\nexport type HttpRequestTarget = string | RegExp;\n\nconst INTEGRATION_NAME = 'HttpClient';\n\ninterface HttpClientOptions {\n /**\n * HTTP status codes that should be considered failed.\n * This array can contain tuples of `[begin, end]` (both inclusive),\n * single status codes, or a combinations of both\n *\n * Example: [[500, 505], 507]\n * Default: [[500, 599]]\n */\n failedRequestStatusCodes: HttpStatusCodeRange[];\n\n /**\n * Targets to track for failed requests.\n * This array can contain strings or regular expressions.\n *\n * Example: ['http://localhost', /api\\/.*\\/]\n * Default: [/.*\\/]\n */\n failedRequestTargets: HttpRequestTarget[];\n}\n\nconst _httpClientIntegration = ((options: Partial<HttpClientOptions> = {}) => {\n const _options: HttpClientOptions = {\n failedRequestStatusCodes: [[500, 599]],\n failedRequestTargets: [/.*/],\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client): void {\n _wrapFetch(client, _options);\n _wrapXHR(client, _options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Create events for failed client side HTTP requests.\n */\nexport const httpClientIntegration = defineIntegration(_httpClientIntegration);\n\n/**\n * Interceptor function for fetch requests\n *\n * @param requestInfo The Fetch API request info\n * @param response The Fetch API response\n * @param requestInit The request init object\n */\nfunction _fetchResponseHandler(\n options: HttpClientOptions,\n requestInfo: RequestInfo,\n response: Response,\n requestInit?: RequestInit,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, response.status, response.url)) {\n const request = _getRequest(requestInfo, requestInit);\n\n let requestHeaders, responseHeaders, requestCookies, responseCookies;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(request.headers), dc.requestHeaders);\n }\n if (dc.responseHeaders !== false) {\n responseHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(response.headers), dc.responseHeaders);\n }\n if (dc.cookies !== false) {\n const reqCookieStr = request.headers.get('Cookie') || undefined;\n if (reqCookieStr) {\n const filtered = _INTERNAL_filterCookies(reqCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n requestCookies = filtered;\n }\n }\n const resCookieStr = response.headers.get('Set-Cookie') || undefined;\n if (resCookieStr) {\n const filtered = _INTERNAL_filterCookies(resCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n }\n\n const event = _createEvent({\n url: request.url,\n method: request.method,\n status: response.status,\n requestHeaders,\n responseHeaders,\n requestCookies,\n responseCookies,\n error,\n type: 'fetch',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Interceptor function for XHR requests\n *\n * @param xhr The XHR request\n * @param method The HTTP method\n * @param headers The HTTP headers\n */\nfunction _xhrResponseHandler(\n options: HttpClientOptions,\n xhr: XMLHttpRequest,\n method: string,\n headers: Record<string, string>,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, xhr.status, xhr.responseURL)) {\n let requestHeaders, responseCookies, responseHeaders;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.cookies !== false) {\n try {\n const cookieString = xhr.getResponseHeader('Set-Cookie') || xhr.getResponseHeader('set-cookie') || undefined;\n if (cookieString) {\n const filtered = _INTERNAL_filterCookies(cookieString, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.responseHeaders !== false) {\n try {\n responseHeaders = _INTERNAL_filterKeyValueData(_getXHRResponseHeaders(xhr), dc.responseHeaders);\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(headers, dc.requestHeaders);\n }\n\n const event = _createEvent({\n url: xhr.responseURL,\n method,\n status: xhr.status,\n requestHeaders,\n // Can't access request cookies from XHR\n responseHeaders,\n responseCookies,\n error,\n type: 'xhr',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Extracts response size from `Content-Length` header when possible\n *\n * @param headers\n * @returns The response size in bytes or undefined\n */\nfunction _getResponseSizeFromHeaders(headers?: Record<string, string>): number | undefined {\n if (headers) {\n const contentLength = headers['Content-Length'] || headers['content-length'];\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n }\n }\n\n return undefined;\n}\n\n/**\n * Extracts the headers as an object from the given Fetch API request or response object\n *\n * @param headers The headers to extract\n * @returns The extracted headers as an object\n */\nfunction _extractFetchHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n result[key] = value;\n });\n\n return result;\n}\n\n/**\n * Extracts the response headers as an object from the given XHR object\n *\n * @param xhr The XHR object to extract the response headers from\n * @returns The response headers as an object\n */\nfunction _getXHRResponseHeaders(xhr: XMLHttpRequest): Record<string, string> {\n const headers = xhr.getAllResponseHeaders();\n\n if (!headers) {\n return {};\n }\n\n return headers.split('\\r\\n').reduce((acc: Record<string, string>, line: string) => {\n const [key, value] = line.split(': ');\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\n/**\n * Checks if the given target url is in the given list of targets\n *\n * @param target The target url to check\n * @returns true if the target url is in the given list of targets, false otherwise\n */\nfunction _isInGivenRequestTargets(\n failedRequestTargets: HttpClientOptions['failedRequestTargets'],\n target: string,\n): boolean {\n return failedRequestTargets.some((givenRequestTarget: HttpRequestTarget) => {\n if (typeof givenRequestTarget === 'string') {\n return target.includes(givenRequestTarget);\n }\n\n return givenRequestTarget.test(target);\n });\n}\n\n/**\n * Checks if the given status code is in the given range\n *\n * @param status The status code to check\n * @returns true if the status code is in the given range, false otherwise\n */\nfunction _isInGivenStatusRanges(\n failedRequestStatusCodes: HttpClientOptions['failedRequestStatusCodes'],\n status: number,\n): boolean {\n return failedRequestStatusCodes.some((range: HttpStatusCodeRange) => {\n if (typeof range === 'number') {\n return range === status;\n }\n\n return status >= range[0] && status <= range[1];\n });\n}\n\n/**\n * Wraps `fetch` function to capture request and response data\n */\nfunction _wrapFetch(client: Client, options: HttpClientOptions): void {\n if (!supportsNativeFetch()) {\n return;\n }\n\n addFetchInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { response, args, error, virtualError } = handlerData;\n const [requestInfo, requestInit] = args as [RequestInfo, RequestInit | undefined];\n\n if (!response) {\n return;\n }\n\n _fetchResponseHandler(options, requestInfo, response as Response, requestInit, error || virtualError);\n }, false);\n}\n\n/**\n * Wraps XMLHttpRequest to capture request and response data\n */\nfunction _wrapXHR(client: Client, options: HttpClientOptions): void {\n if (!('XMLHttpRequest' in GLOBAL_OBJ)) {\n return;\n }\n\n addXhrInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { error, virtualError } = handlerData;\n\n const xhr = handlerData.xhr as SentryWrappedXMLHttpRequest & XMLHttpRequest;\n\n const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];\n\n if (!sentryXhrData) {\n return;\n }\n\n const { method, request_headers: headers } = sentryXhrData;\n\n try {\n _xhrResponseHandler(options, xhr, method, headers, error || virtualError);\n } catch (e) {\n DEBUG_BUILD && debug.warn('Error while extracting response event form XHR response', e);\n }\n });\n}\n\n/**\n * Checks whether to capture given response as an event\n *\n * @param status response status code\n * @param url response url\n */\nfunction _shouldCaptureResponse(options: HttpClientOptions, status: number, url: string): boolean {\n return (\n _isInGivenStatusRanges(options.failedRequestStatusCodes, status) &&\n _isInGivenRequestTargets(options.failedRequestTargets, url) &&\n !isSentryRequestUrl(url, getClient())\n );\n}\n\n/**\n * Creates a synthetic Sentry event from given response data\n *\n * @param data response data\n * @returns event\n */\nfunction _createEvent(data: {\n url: string;\n method: string;\n status: number;\n type: 'fetch' | 'xhr';\n responseHeaders?: Record<string, string>;\n responseCookies?: Record<string, string>;\n requestHeaders?: Record<string, string>;\n requestCookies?: Record<string, string>;\n error?: unknown;\n}): SentryEvent {\n const client = getClient();\n const virtualStackTrace = client && data.error && data.error instanceof Error ? data.error.stack : undefined;\n // Remove the first frame from the stack as it's the HttpClient call\n const stack = virtualStackTrace && client ? client.getOptions().stackParser(virtualStackTrace, 0, 1) : undefined;\n const message = `HTTP Client Error with status code: ${data.status}`;\n\n const event: SentryEvent = {\n message,\n exception: {\n values: [\n {\n type: 'Error',\n value: message,\n stacktrace: stack ? { frames: stack } : undefined,\n },\n ],\n },\n request: {\n url: data.url,\n method: data.method,\n headers: data.requestHeaders,\n cookies: data.requestCookies,\n },\n contexts: {\n response: {\n status_code: data.status,\n headers: data.responseHeaders,\n cookies: data.responseCookies,\n body_size: _getResponseSizeFromHeaders(data.responseHeaders),\n },\n },\n };\n\n addExceptionMechanism(event, {\n type: `auto.http.client.${data.type}`,\n handled: false,\n });\n\n return event;\n}\n\nfunction _getRequest(requestInfo: RequestInfo, requestInit?: RequestInit): Request {\n if (!requestInit && requestInfo instanceof Request) {\n return requestInfo;\n }\n\n // If both are set, we try to construct a new Request with the given arguments\n // However, if e.g. the original request has a `body`, this will throw an error because it was already accessed\n // In this case, as a fallback, we just use the original request - using both is rather an edge case\n if (requestInfo instanceof Request && requestInfo.bodyUsed) {\n return requestInfo;\n }\n\n return new Request(requestInfo, requestInit);\n}\n\nfunction _getDataCollectionSettings() {\n const client = getClient();\n if (!client) {\n return { cookies: false, requestHeaders: false, responseHeaders: false };\n }\n\n // todo(v11): Always use granular dataCollection settings and remove this legacy guard.\n // Currently, when dataCollection is not explicitly set, we gate all collection on\n // sendDefaultPii to avoid sending more data than before (the spec defaults would\n // collect headers/cookies with deny-list filtering even without sendDefaultPii).\n const options = client.getOptions();\n if (options.dataCollection == null) {\n // eslint-disable-next-line deprecation/deprecation\n const enabled = Boolean(options.sendDefaultPii);\n return { cookies: enabled, requestHeaders: enabled, responseHeaders: enabled };\n }\n\n const { cookies, httpHeaders } = client.getDataCollectionOptions();\n return { cookies, requestHeaders: httpHeaders.request, responseHeaders: httpHeaders.response };\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"httpclient.js","sources":["../../../../../src/integrations/httpclient.ts"],"sourcesContent":["import type { Client, Event as SentryEvent, IntegrationFn, SentryWrappedXMLHttpRequest } from '@sentry/core/browser';\nimport {\n _INTERNAL_filterCookies,\n _INTERNAL_filterKeyValueData,\n addExceptionMechanism,\n addFetchInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n GLOBAL_OBJ,\n isSentryRequestUrl,\n supportsNativeFetch,\n} from '@sentry/core/browser';\nimport { addXhrInstrumentationHandler, SENTRY_XHR_DATA_KEY } from '@sentry/browser-utils';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport type HttpStatusCodeRange = [number, number] | number;\nexport type HttpRequestTarget = string | RegExp;\n\nconst INTEGRATION_NAME = 'HttpClient';\n\ninterface HttpClientOptions {\n /**\n * HTTP status codes that should be considered failed.\n * This array can contain tuples of `[begin, end]` (both inclusive),\n * single status codes, or a combinations of both\n *\n * Example: [[500, 505], 507]\n * Default: [[500, 599]]\n */\n failedRequestStatusCodes: HttpStatusCodeRange[];\n\n /**\n * Targets to track for failed requests.\n * This array can contain strings or regular expressions.\n *\n * Example: ['http://localhost', /api\\/.*\\/]\n * Default: [/.*\\/]\n */\n failedRequestTargets: HttpRequestTarget[];\n}\n\nconst _httpClientIntegration = ((options: Partial<HttpClientOptions> = {}) => {\n const _options: HttpClientOptions = {\n failedRequestStatusCodes: [[500, 599]],\n failedRequestTargets: [/.*/],\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setup(client): void {\n _wrapFetch(client, _options);\n _wrapXHR(client, _options);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Create events for failed client side HTTP requests.\n */\nexport const httpClientIntegration = defineIntegration(_httpClientIntegration);\n\n/**\n * Interceptor function for fetch requests\n *\n * @param requestInfo The Fetch API request info\n * @param response The Fetch API response\n * @param requestInit The request init object\n */\nfunction _fetchResponseHandler(\n options: HttpClientOptions,\n requestInfo: RequestInfo,\n response: Response,\n requestInit?: RequestInit,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, response.status, response.url)) {\n const request = _getRequest(requestInfo, requestInit);\n\n let requestHeaders, responseHeaders, requestCookies, responseCookies;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(request.headers), dc.requestHeaders);\n }\n if (dc.responseHeaders !== false) {\n responseHeaders = _INTERNAL_filterKeyValueData(_extractFetchHeaders(response.headers), dc.responseHeaders);\n }\n if (dc.cookies !== false) {\n const reqCookieStr = request.headers.get('Cookie') || undefined;\n if (reqCookieStr) {\n const filtered = _INTERNAL_filterCookies(reqCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n requestCookies = filtered;\n }\n }\n const resCookieStr = response.headers.get('Set-Cookie') || undefined;\n if (resCookieStr) {\n const filtered = _INTERNAL_filterCookies(resCookieStr, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n }\n\n const event = _createEvent({\n url: request.url,\n method: request.method,\n status: response.status,\n requestHeaders,\n responseHeaders,\n requestCookies,\n responseCookies,\n error,\n type: 'fetch',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Interceptor function for XHR requests\n *\n * @param xhr The XHR request\n * @param method The HTTP method\n * @param headers The HTTP headers\n */\nfunction _xhrResponseHandler(\n options: HttpClientOptions,\n xhr: XMLHttpRequest,\n method: string,\n headers: Record<string, string>,\n error?: unknown,\n): void {\n if (_shouldCaptureResponse(options, xhr.status, xhr.responseURL)) {\n let requestHeaders, responseCookies, responseHeaders;\n\n const dc = _getDataCollectionSettings();\n\n if (dc.cookies !== false) {\n try {\n const cookieString = xhr.getResponseHeader('Set-Cookie') || xhr.getResponseHeader('set-cookie') || undefined;\n if (cookieString) {\n const filtered = _INTERNAL_filterCookies(cookieString, dc.cookies);\n if (typeof filtered === 'object') {\n responseCookies = filtered;\n }\n }\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.responseHeaders !== false) {\n try {\n responseHeaders = _INTERNAL_filterKeyValueData(_getXHRResponseHeaders(xhr), dc.responseHeaders);\n } catch {\n // ignore it if parsing fails\n }\n }\n\n if (dc.requestHeaders !== false) {\n requestHeaders = _INTERNAL_filterKeyValueData(headers, dc.requestHeaders);\n }\n\n const event = _createEvent({\n url: xhr.responseURL,\n method,\n status: xhr.status,\n requestHeaders,\n // Can't access request cookies from XHR\n responseHeaders,\n responseCookies,\n error,\n type: 'xhr',\n });\n\n captureEvent(event);\n }\n}\n\n/**\n * Extracts response size from `Content-Length` header when possible\n *\n * @param headers\n * @returns The response size in bytes or undefined\n */\nfunction _getResponseSizeFromHeaders(headers?: Record<string, string>): number | undefined {\n if (headers) {\n const contentLength = headers['Content-Length'] || headers['content-length'];\n\n if (contentLength) {\n return parseInt(contentLength, 10);\n }\n }\n\n return undefined;\n}\n\n/**\n * Extracts the headers as an object from the given Fetch API request or response object\n *\n * @param headers The headers to extract\n * @returns The extracted headers as an object\n */\nfunction _extractFetchHeaders(headers: Headers): Record<string, string> {\n const result: Record<string, string> = {};\n\n headers.forEach((value, key) => {\n result[key] = value;\n });\n\n return result;\n}\n\n/**\n * Extracts the response headers as an object from the given XHR object\n *\n * @param xhr The XHR object to extract the response headers from\n * @returns The response headers as an object\n */\nfunction _getXHRResponseHeaders(xhr: XMLHttpRequest): Record<string, string> {\n const headers = xhr.getAllResponseHeaders();\n\n if (!headers) {\n return {};\n }\n\n return headers.split('\\r\\n').reduce((acc: Record<string, string>, line: string) => {\n const [key, value] = line.split(': ');\n if (key && value) {\n acc[key] = value;\n }\n return acc;\n }, {});\n}\n\n/**\n * Checks if the given target url is in the given list of targets\n *\n * @param target The target url to check\n * @returns true if the target url is in the given list of targets, false otherwise\n */\nfunction _isInGivenRequestTargets(\n failedRequestTargets: HttpClientOptions['failedRequestTargets'],\n target: string,\n): boolean {\n return failedRequestTargets.some((givenRequestTarget: HttpRequestTarget) => {\n if (typeof givenRequestTarget === 'string') {\n return target.includes(givenRequestTarget);\n }\n\n return givenRequestTarget.test(target);\n });\n}\n\n/**\n * Checks if the given status code is in the given range\n *\n * @param status The status code to check\n * @returns true if the status code is in the given range, false otherwise\n */\nfunction _isInGivenStatusRanges(\n failedRequestStatusCodes: HttpClientOptions['failedRequestStatusCodes'],\n status: number,\n): boolean {\n return failedRequestStatusCodes.some((range: HttpStatusCodeRange) => {\n if (typeof range === 'number') {\n return range === status;\n }\n\n return status >= range[0] && status <= range[1];\n });\n}\n\n/**\n * Wraps `fetch` function to capture request and response data\n */\nfunction _wrapFetch(client: Client, options: HttpClientOptions): void {\n if (!supportsNativeFetch()) {\n return;\n }\n\n addFetchInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { response, args, error, virtualError } = handlerData;\n const [requestInfo, requestInit] = args as [RequestInfo, RequestInit | undefined];\n\n if (!response) {\n return;\n }\n\n _fetchResponseHandler(options, requestInfo, response as Response, requestInit, error || virtualError);\n }, false);\n}\n\n/**\n * Wraps XMLHttpRequest to capture request and response data\n */\nfunction _wrapXHR(client: Client, options: HttpClientOptions): void {\n if (!('XMLHttpRequest' in GLOBAL_OBJ)) {\n return;\n }\n\n addXhrInstrumentationHandler(handlerData => {\n if (getClient() !== client) {\n return;\n }\n\n const { error, virtualError } = handlerData;\n\n const xhr = handlerData.xhr as SentryWrappedXMLHttpRequest & XMLHttpRequest;\n\n const sentryXhrData = xhr[SENTRY_XHR_DATA_KEY];\n\n if (!sentryXhrData) {\n return;\n }\n\n const { method, request_headers: headers } = sentryXhrData;\n\n try {\n _xhrResponseHandler(options, xhr, method, headers, error || virtualError);\n } catch (e) {\n DEBUG_BUILD && debug.warn('Error while extracting response event form XHR response', e);\n }\n });\n}\n\n/**\n * Checks whether to capture given response as an event\n *\n * @param status response status code\n * @param url response url\n */\nfunction _shouldCaptureResponse(options: HttpClientOptions, status: number, url: string): boolean {\n return (\n _isInGivenStatusRanges(options.failedRequestStatusCodes, status) &&\n _isInGivenRequestTargets(options.failedRequestTargets, url) &&\n !isSentryRequestUrl(url, getClient())\n );\n}\n\n/**\n * Creates a synthetic Sentry event from given response data\n *\n * @param data response data\n * @returns event\n */\nfunction _createEvent(data: {\n url: string;\n method: string;\n status: number;\n type: 'fetch' | 'xhr';\n responseHeaders?: Record<string, string>;\n responseCookies?: Record<string, string>;\n requestHeaders?: Record<string, string>;\n requestCookies?: Record<string, string>;\n error?: unknown;\n}): SentryEvent {\n const client = getClient();\n const virtualStackTrace = client && data.error && data.error instanceof Error ? data.error.stack : undefined;\n // Remove the first frame from the stack as it's the HttpClient call\n const stack = virtualStackTrace && client ? client.getOptions().stackParser(virtualStackTrace, 0, 1) : undefined;\n const message = `HTTP Client Error with status code: ${data.status}`;\n\n const event: SentryEvent = {\n message,\n exception: {\n values: [\n {\n type: 'Error',\n value: message,\n stacktrace: stack ? { frames: stack } : undefined,\n },\n ],\n },\n request: {\n url: data.url,\n method: data.method,\n headers: data.requestHeaders,\n cookies: data.requestCookies,\n },\n contexts: {\n response: {\n status_code: data.status,\n headers: data.responseHeaders,\n cookies: data.responseCookies,\n body_size: _getResponseSizeFromHeaders(data.responseHeaders),\n },\n },\n };\n\n addExceptionMechanism(event, {\n type: `auto.http.client.${data.type}`,\n handled: false,\n });\n\n return event;\n}\n\nfunction _getRequest(requestInfo: RequestInfo, requestInit?: RequestInit): Request {\n if (!requestInit && requestInfo instanceof Request) {\n return requestInfo;\n }\n\n // If both are set, we try to construct a new Request with the given arguments\n // However, if e.g. the original request has a `body`, this will throw an error because it was already accessed\n // In this case, as a fallback, we just use the original request - using both is rather an edge case\n if (requestInfo instanceof Request && requestInfo.bodyUsed) {\n return requestInfo;\n }\n\n return new Request(requestInfo, requestInit);\n}\n\nfunction _getDataCollectionSettings() {\n const client = getClient();\n if (!client) {\n return { cookies: false, requestHeaders: false, responseHeaders: false };\n }\n\n // todo(v11): Always use granular dataCollection settings and remove this legacy guard.\n // Currently, when dataCollection is not explicitly set, we gate all collection on\n // sendDefaultPii to avoid sending more data than before (the spec defaults would\n // collect headers/cookies with deny-list filtering even without sendDefaultPii).\n const options = client.getOptions();\n if (options.dataCollection == null) {\n // eslint-disable-next-line typescript/no-deprecated\n const enabled = Boolean(options.sendDefaultPii);\n return { cookies: enabled, requestHeaders: enabled, responseHeaders: enabled };\n }\n\n const { cookies, httpHeaders } = client.getDataCollectionOptions();\n return { cookies, requestHeaders: httpHeaders.request, responseHeaders: httpHeaders.response };\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { defineIntegration, safeSetSpanJSONAttributes } from '@sentry/core/browser';
|
|
1
|
+
import { defineIntegration, SEMANTIC_ATTRIBUTE_SENTRY_OP, safeSetSpanJSONAttributes } from '@sentry/core/browser';
|
|
2
2
|
import { WINDOW, getHttpRequestData } from '../helpers.js';
|
|
3
3
|
|
|
4
4
|
const httpContextIntegration = defineIntegration(() => {
|
|
@@ -20,6 +20,7 @@ const httpContextIntegration = defineIntegration(() => {
|
|
|
20
20
|
};
|
|
21
21
|
},
|
|
22
22
|
processSegmentSpan(span) {
|
|
23
|
+
const spanOp = span.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP];
|
|
23
24
|
if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {
|
|
24
25
|
return;
|
|
25
26
|
}
|
|
@@ -27,7 +28,7 @@ const httpContextIntegration = defineIntegration(() => {
|
|
|
27
28
|
safeSetSpanJSONAttributes(span, {
|
|
28
29
|
// Coerce empty string to undefined so the helper's nullish check drops it,
|
|
29
30
|
// rather than writing an empty `url.full` attribute onto the span.
|
|
30
|
-
"url.full": reqData.url
|
|
31
|
+
"url.full": spanOp !== "http.client" ? reqData.url : void 0,
|
|
31
32
|
"http.request.header.user_agent": reqData.headers["User-Agent"],
|
|
32
33
|
"http.request.header.referer": reqData.headers["Referer"]
|
|
33
34
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpcontext.js","sources":["../../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import { defineIntegration, safeSetSpanJSONAttributes } from '@sentry/core/browser';\nimport { getHttpRequestData, WINDOW } from '../helpers';\n\n/**\n * Collects information about HTTP request headers and\n * attaches them to the event.\n */\nexport const httpContextIntegration = defineIntegration(() => {\n return {\n name: 'HttpContext',\n preprocessEvent(event) {\n // if none of the information we want exists, don't bother\n if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {\n return;\n }\n\n const reqData = getHttpRequestData();\n const headers = {\n ...reqData.headers,\n ...event.request?.headers,\n };\n\n event.request = {\n ...reqData,\n ...event.request,\n headers,\n };\n },\n processSegmentSpan(span) {\n // if none of the information we want exists, don't bother\n if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {\n return;\n }\n\n const reqData = getHttpRequestData();\n\n safeSetSpanJSONAttributes(span, {\n // Coerce empty string to undefined so the helper's nullish check drops it,\n // rather than writing an empty `url.full` attribute onto the span.\n 'url.full': reqData.url
|
|
1
|
+
{"version":3,"file":"httpcontext.js","sources":["../../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import { defineIntegration, safeSetSpanJSONAttributes, SEMANTIC_ATTRIBUTE_SENTRY_OP } from '@sentry/core/browser';\nimport { getHttpRequestData, WINDOW } from '../helpers';\n\n/**\n * Collects information about HTTP request headers and\n * attaches them to the event.\n */\nexport const httpContextIntegration = defineIntegration(() => {\n return {\n name: 'HttpContext',\n preprocessEvent(event) {\n // if none of the information we want exists, don't bother\n if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {\n return;\n }\n\n const reqData = getHttpRequestData();\n const headers = {\n ...reqData.headers,\n ...event.request?.headers,\n };\n\n event.request = {\n ...reqData,\n ...event.request,\n headers,\n };\n },\n processSegmentSpan(span) {\n const spanOp = span.attributes?.[SEMANTIC_ATTRIBUTE_SENTRY_OP];\n\n // if none of the information we want exists, don't bother\n if (!WINDOW.navigator && !WINDOW.location && !WINDOW.document) {\n return;\n }\n\n const reqData = getHttpRequestData();\n\n safeSetSpanJSONAttributes(span, {\n // Coerce empty string to undefined so the helper's nullish check drops it,\n // rather than writing an empty `url.full` attribute onto the span.\n 'url.full': spanOp !== 'http.client' ? reqData.url : undefined,\n 'http.request.header.user_agent': reqData.headers['User-Agent'],\n 'http.request.header.referer': reqData.headers['Referer'],\n });\n },\n };\n});\n"],"names":[],"mappings":";;;AAOO,MAAM,sBAAA,GAAyB,kBAAkB,MAAM;AAC5D,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,gBAAgB,KAAA,EAAO;AAErB,MAAA,IAAI,CAAC,OAAO,SAAA,IAAa,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,EAAU;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAU,kBAAA,EAAmB;AACnC,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,GAAG,OAAA,CAAQ,OAAA;AAAA,QACX,GAAG,MAAM,OAAA,EAAS;AAAA,OACpB;AAEA,MAAA,KAAA,CAAM,OAAA,GAAU;AAAA,QACd,GAAG,OAAA;AAAA,QACH,GAAG,KAAA,CAAM,OAAA;AAAA,QACT;AAAA,OACF;AAAA,IACF,CAAA;AAAA,IACA,mBAAmB,IAAA,EAAM;AACvB,MAAA,MAAM,MAAA,GAAS,IAAA,CAAK,UAAA,GAAa,4BAA4B,CAAA;AAG7D,MAAA,IAAI,CAAC,OAAO,SAAA,IAAa,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,EAAU;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAU,kBAAA,EAAmB;AAEnC,MAAA,yBAAA,CAA0B,IAAA,EAAM;AAAA;AAAA;AAAA,QAG9B,UAAA,EAAY,MAAA,KAAW,aAAA,GAAgB,OAAA,CAAQ,GAAA,GAAM,MAAA;AAAA,QACrD,gCAAA,EAAkC,OAAA,CAAQ,OAAA,CAAQ,YAAY,CAAA;AAAA,QAC9D,6BAAA,EAA+B,OAAA,CAAQ,OAAA,CAAQ,SAAS;AAAA,OACzD,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webVitals.js","sources":["../../../../../src/integrations/webVitals.ts"],"sourcesContent":["import type { IntegrationFn, Span } from '@sentry/core/browser';\nimport { defineIntegration, hasSpanStreamingEnabled } from '@sentry/core/browser';\nimport {\n addWebVitalsToSpan,\n registerInpInteractionListener,\n startTrackingINP,\n startTrackingWebVitals,\n trackClsAsSpan,\n trackInpAsSpan,\n trackLcpAsSpan,\n} from '@sentry/browser-utils';\n\nexport const WEB_VITALS_INTEGRATION_NAME = 'WebVitals';\n\nexport type WebVitalName = 'cls' | 'inp' | 'lcp';\n\nexport interface WebVitalsOptions {\n /**\n * Web vitals to skip.\n */\n ignore?: WebVitalName[];\n\n /**\n * @experimental\n */\n _experiments?: Partial<{\n enableStandaloneClsSpans: boolean;\n enableStandaloneLcpSpans: boolean;\n }>;\n}\n\n/**\n * Captures Core Web Vitals (LCP, CLS, INP) and related pageload vitals.\n *\n * `browserTracingIntegration` auto-registers this integration if no\n * `webVitalsIntegration` is already present, so explicit registration is only\n * needed to customize options or to use it without `browserTracingIntegration`.\n */\nexport const webVitalsIntegration = defineIntegration((options: WebVitalsOptions = {}) => {\n const ignored = new Set(options.ignore ?? []);\n\n return {\n name: WEB_VITALS_INTEGRATION_NAME,\n setup(client) {\n const spanStreamingEnabled = hasSpanStreamingEnabled(client);\n const { enableStandaloneClsSpans, enableStandaloneLcpSpans } = options._experiments ?? {};\n\n const recordClsStandaloneSpans =\n spanStreamingEnabled || ignored.has('cls') ? undefined : enableStandaloneClsSpans || false;\n const recordLcpStandaloneSpans =\n spanStreamingEnabled || ignored.has('lcp') ? undefined : enableStandaloneLcpSpans || false;\n\n const finalizeWebVitals = startTrackingWebVitals({\n recordClsStandaloneSpans,\n recordLcpStandaloneSpans,\n client,\n });\n\n const pageloadSpans = new WeakSet<Span>();\n\n client.on('afterStartPageLoadSpan', span => {\n pageloadSpans.add(span);\n });\n\n client.on('spanEnd', span => {\n if (!pageloadSpans.delete(span)) {\n return;\n }\n\n finalizeWebVitals();\n addWebVitalsToSpan(span, {\n // CLS/LCP are recorded as pageload span measurements only when they're neither\n // tracked as standalone spans nor handled by span streaming (and not ignored).\n recordClsOnPageloadSpan: recordClsStandaloneSpans === false,\n recordLcpOnPageloadSpan: recordLcpStandaloneSpans === false,\n spanStreamingEnabled,\n });\n });\n\n if (spanStreamingEnabled) {\n if (!ignored.has('lcp')) {\n trackLcpAsSpan(client);\n }\n if (!ignored.has('cls')) {\n trackClsAsSpan(client);\n }\n if (!ignored.has('inp')) {\n trackInpAsSpan();\n }\n } else if (!ignored.has('inp')) {\n startTrackingINP();\n }\n },\n afterAllSetup() {\n if (!ignored.has('inp')) {\n registerInpInteractionListener();\n }\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":";;;AAYO,MAAM,2BAAA,GAA8B;AA0BpC,MAAM,oBAAA,GAAuB,iBAAA,CAAkB,CAAC,OAAA,GAA4B,EAAC,KAAM;AACxF,EAAA,MAAM,UAAU,IAAI,GAAA,CAAI,OAAA,CAAQ,MAAA,IAAU,EAAE,CAAA;AAE5C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,2BAAA;AAAA,IACN,MAAM,MAAA,EAAQ;AACZ,MAAA,MAAM,oBAAA,GAAuB,wBAAwB,MAAM,CAAA;AAC3D,MAAA,MAAM,EAAE,wBAAA,EAA0B,wBAAA,EAAyB,GAAI,OAAA,CAAQ,gBAAgB,EAAC;AAExF,MAAA,MAAM,2BACJ,oBAAA,IAAwB,OAAA,CAAQ,IAAI,KAAK,CAAA,GAAI,SAAY,wBAAA,IAA4B,KAAA;AACvF,MAAA,MAAM,2BACJ,oBAAA,IAAwB,OAAA,CAAQ,IAAI,KAAK,CAAA,GAAI,SAAY,wBAAA,IAA4B,KAAA;
|
|
1
|
+
{"version":3,"file":"webVitals.js","sources":["../../../../../src/integrations/webVitals.ts"],"sourcesContent":["import type { IntegrationFn, Span } from '@sentry/core/browser';\nimport { defineIntegration, hasSpanStreamingEnabled } from '@sentry/core/browser';\nimport {\n addWebVitalsToSpan,\n registerInpInteractionListener,\n startTrackingINP,\n startTrackingWebVitals,\n trackClsAsSpan,\n trackInpAsSpan,\n trackLcpAsSpan,\n} from '@sentry/browser-utils';\n\nexport const WEB_VITALS_INTEGRATION_NAME = 'WebVitals';\n\nexport type WebVitalName = 'cls' | 'inp' | 'lcp';\n\nexport interface WebVitalsOptions {\n /**\n * Web vitals to skip.\n */\n ignore?: WebVitalName[];\n\n /**\n * @experimental\n */\n _experiments?: Partial<{\n enableStandaloneClsSpans: boolean;\n enableStandaloneLcpSpans: boolean;\n }>;\n}\n\n/**\n * Captures Core Web Vitals (LCP, CLS, INP) and related pageload vitals.\n *\n * `browserTracingIntegration` auto-registers this integration if no\n * `webVitalsIntegration` is already present, so explicit registration is only\n * needed to customize options or to use it without `browserTracingIntegration`.\n */\nexport const webVitalsIntegration = defineIntegration((options: WebVitalsOptions = {}) => {\n const ignored = new Set(options.ignore ?? []);\n\n return {\n name: WEB_VITALS_INTEGRATION_NAME,\n setup(client) {\n const spanStreamingEnabled = hasSpanStreamingEnabled(client);\n const { enableStandaloneClsSpans, enableStandaloneLcpSpans } = options._experiments ?? {};\n\n const recordClsStandaloneSpans =\n spanStreamingEnabled || ignored.has('cls') ? undefined : enableStandaloneClsSpans || false;\n const recordLcpStandaloneSpans =\n spanStreamingEnabled || ignored.has('lcp') ? undefined : enableStandaloneLcpSpans || false;\n\n // eslint-disable-next-line typescript/no-deprecated\n const finalizeWebVitals = startTrackingWebVitals({\n recordClsStandaloneSpans,\n recordLcpStandaloneSpans,\n client,\n });\n\n const pageloadSpans = new WeakSet<Span>();\n\n client.on('afterStartPageLoadSpan', span => {\n pageloadSpans.add(span);\n });\n\n client.on('spanEnd', span => {\n if (!pageloadSpans.delete(span)) {\n return;\n }\n\n finalizeWebVitals();\n addWebVitalsToSpan(span, {\n // CLS/LCP are recorded as pageload span measurements only when they're neither\n // tracked as standalone spans nor handled by span streaming (and not ignored).\n recordClsOnPageloadSpan: recordClsStandaloneSpans === false,\n recordLcpOnPageloadSpan: recordLcpStandaloneSpans === false,\n spanStreamingEnabled,\n });\n });\n\n if (spanStreamingEnabled) {\n if (!ignored.has('lcp')) {\n trackLcpAsSpan(client);\n }\n if (!ignored.has('cls')) {\n trackClsAsSpan(client);\n }\n if (!ignored.has('inp')) {\n trackInpAsSpan();\n }\n } else if (!ignored.has('inp')) {\n startTrackingINP();\n }\n },\n afterAllSetup() {\n if (!ignored.has('inp')) {\n registerInpInteractionListener();\n }\n },\n };\n}) satisfies IntegrationFn;\n"],"names":[],"mappings":";;;AAYO,MAAM,2BAAA,GAA8B;AA0BpC,MAAM,oBAAA,GAAuB,iBAAA,CAAkB,CAAC,OAAA,GAA4B,EAAC,KAAM;AACxF,EAAA,MAAM,UAAU,IAAI,GAAA,CAAI,OAAA,CAAQ,MAAA,IAAU,EAAE,CAAA;AAE5C,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,2BAAA;AAAA,IACN,MAAM,MAAA,EAAQ;AACZ,MAAA,MAAM,oBAAA,GAAuB,wBAAwB,MAAM,CAAA;AAC3D,MAAA,MAAM,EAAE,wBAAA,EAA0B,wBAAA,EAAyB,GAAI,OAAA,CAAQ,gBAAgB,EAAC;AAExF,MAAA,MAAM,2BACJ,oBAAA,IAAwB,OAAA,CAAQ,IAAI,KAAK,CAAA,GAAI,SAAY,wBAAA,IAA4B,KAAA;AACvF,MAAA,MAAM,2BACJ,oBAAA,IAAwB,OAAA,CAAQ,IAAI,KAAK,CAAA,GAAI,SAAY,wBAAA,IAA4B,KAAA;AAGvF,MAAA,MAAM,oBAAoB,sBAAA,CAAuB;AAAA,QAC/C,wBAAA;AAAA,QACA,wBAAA;AAAA,QACA;AAAA,OACD,CAAA;AAED,MAAA,MAAM,aAAA,uBAAoB,OAAA,EAAc;AAExC,MAAA,MAAA,CAAO,EAAA,CAAG,0BAA0B,CAAA,IAAA,KAAQ;AAC1C,QAAA,aAAA,CAAc,IAAI,IAAI,CAAA;AAAA,MACxB,CAAC,CAAA;AAED,MAAA,MAAA,CAAO,EAAA,CAAG,WAAW,CAAA,IAAA,KAAQ;AAC3B,QAAA,IAAI,CAAC,aAAA,CAAc,MAAA,CAAO,IAAI,CAAA,EAAG;AAC/B,UAAA;AAAA,QACF;AAEA,QAAA,iBAAA,EAAkB;AAClB,QAAA,kBAAA,CAAmB,IAAA,EAAM;AAAA;AAAA;AAAA,UAGvB,yBAAyB,wBAAA,KAA6B,KAAA;AAAA,UACtD,yBAAyB,wBAAA,KAA6B,KAAA;AAAA,UACtD;AAAA,SACD,CAAA;AAAA,MACH,CAAC,CAAA;AAED,MAAA,IAAI,oBAAA,EAAsB;AACxB,QAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACvB,UAAA,cAAA,CAAe,MAAM,CAAA;AAAA,QACvB;AACA,QAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACvB,UAAA,cAAA,CAAe,MAAM,CAAA;AAAA,QACvB;AACA,QAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACvB,UAAA,cAAA,EAAe;AAAA,QACjB;AAAA,MACF,CAAA,MAAA,IAAW,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AAC9B,QAAA,gBAAA,EAAiB;AAAA,MACnB;AAAA,IACF,CAAA;AAAA,IACA,aAAA,GAAgB;AACd,MAAA,IAAI,CAAC,OAAA,CAAQ,GAAA,CAAI,KAAK,CAAA,EAAG;AACvB,QAAA,8BAAA,EAA+B;AAAA,MACjC;AAAA,IACF;AAAA,GACF;AACF,CAAC;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"type":"module","version":"10.
|
|
1
|
+
{"type":"module","version":"10.60.0","sideEffects":false}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"integration.js","sources":["../../../../../src/profiling/integration.ts"],"sourcesContent":["import type { EventEnvelope, IntegrationFn, Profile, Span } from '@sentry/core/browser';\nimport { debug, defineIntegration, getActiveSpan, getRootSpan, hasSpansEnabled } from '@sentry/core/browser';\nimport type { BrowserOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\nimport { startProfileForSpan } from './startProfileForSpan';\nimport { UIProfiler } from './UIProfiler';\nimport type { ProfiledEvent } from './utils';\nimport {\n addProfilesToEnvelope,\n createProfilingEvent,\n findProfiledTransactionsFromEnvelope,\n getActiveProfilesCount,\n hasLegacyProfiling,\n isAutomatedPageLoadSpan,\n PROFILED_ROOT_SPANS,\n setThreadAttributes,\n shouldProfileSpanLegacy,\n takeProfileFromGlobalCache,\n} from './utils';\n\nconst INTEGRATION_NAME = 'BrowserProfiling';\n\nconst _browserProfilingIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n const options = client.getOptions() as BrowserOptions;\n const profiler = new UIProfiler();\n\n if (!hasLegacyProfiling(options) && !options.profileLifecycle) {\n // Set default lifecycle mode\n options.profileLifecycle = 'manual';\n }\n\n // eslint-disable-next-line
|
|
1
|
+
{"version":3,"file":"integration.js","sources":["../../../../../src/profiling/integration.ts"],"sourcesContent":["import type { EventEnvelope, IntegrationFn, Profile, Span } from '@sentry/core/browser';\nimport { debug, defineIntegration, getActiveSpan, getRootSpan, hasSpansEnabled } from '@sentry/core/browser';\nimport type { BrowserOptions } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\nimport { startProfileForSpan } from './startProfileForSpan';\nimport { UIProfiler } from './UIProfiler';\nimport type { ProfiledEvent } from './utils';\nimport {\n addProfilesToEnvelope,\n createProfilingEvent,\n findProfiledTransactionsFromEnvelope,\n getActiveProfilesCount,\n hasLegacyProfiling,\n isAutomatedPageLoadSpan,\n PROFILED_ROOT_SPANS,\n setThreadAttributes,\n shouldProfileSpanLegacy,\n takeProfileFromGlobalCache,\n} from './utils';\n\nconst INTEGRATION_NAME = 'BrowserProfiling';\n\nconst _browserProfilingIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setup(client) {\n const options = client.getOptions() as BrowserOptions;\n const profiler = new UIProfiler();\n\n if (!hasLegacyProfiling(options) && !options.profileLifecycle) {\n // Set default lifecycle mode\n options.profileLifecycle = 'manual';\n }\n\n // eslint-disable-next-line typescript/no-deprecated\n if (hasLegacyProfiling(options) && !options.profilesSampleRate) {\n DEBUG_BUILD && debug.log('[Profiling] Profiling disabled, no profiling options found.');\n return;\n }\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan && getRootSpan(activeSpan);\n\n if (hasLegacyProfiling(options) && options.profileSessionSampleRate !== undefined) {\n DEBUG_BUILD &&\n debug.warn(\n '[Profiling] Both legacy profiling (`profilesSampleRate`) and UI profiling settings are defined. `profileSessionSampleRate` has no effect when legacy profiling is enabled.',\n );\n }\n\n // UI PROFILING (Profiling V2)\n if (!hasLegacyProfiling(options)) {\n const lifecycleMode = options.profileLifecycle;\n\n // Registering hooks in all lifecycle modes to be able to notify users in case they want to start/stop the profiler manually in `trace` mode\n client.on('startUIProfiler', () => profiler.start());\n client.on('stopUIProfiler', () => profiler.stop());\n\n if (lifecycleMode === 'manual') {\n profiler.initialize(client);\n } else if (lifecycleMode === 'trace') {\n if (!hasSpansEnabled(options)) {\n DEBUG_BUILD &&\n debug.warn(\n \"[Profiling] `profileLifecycle` is 'trace' but tracing is disabled. Set a `tracesSampleRate` or `tracesSampler` to enable span tracing.\",\n );\n return;\n }\n\n profiler.initialize(client);\n\n // If there is an active, sampled root span already, notify the profiler\n if (rootSpan) {\n profiler.notifyRootSpanActive(rootSpan);\n }\n\n // In case rootSpan is created slightly after setup -> schedule microtask to re-check and notify.\n WINDOW.setTimeout(() => {\n const laterActiveSpan = getActiveSpan();\n const laterRootSpan = laterActiveSpan && getRootSpan(laterActiveSpan);\n if (laterRootSpan) {\n profiler.notifyRootSpanActive(laterRootSpan);\n }\n }, 0);\n }\n } else {\n // LEGACY PROFILING (v1)\n if (rootSpan && isAutomatedPageLoadSpan(rootSpan)) {\n if (shouldProfileSpanLegacy(rootSpan)) {\n startProfileForSpan(rootSpan);\n }\n }\n\n client.on('spanStart', (span: Span) => {\n const rootSpan = getRootSpan(span);\n if (span === rootSpan) {\n if (shouldProfileSpanLegacy(span)) {\n startProfileForSpan(span);\n }\n } else if (PROFILED_ROOT_SPANS.has(rootSpan)) {\n setThreadAttributes(span);\n }\n });\n\n client.on('beforeEnvelope', (envelope): void => {\n // if not profiles are in queue, there is nothing to add to the envelope.\n if (!getActiveProfilesCount()) {\n return;\n }\n\n const profiledTransactionEvents = findProfiledTransactionsFromEnvelope(envelope);\n if (!profiledTransactionEvents.length) {\n return;\n }\n\n const profilesToAddToEnvelope: Profile[] = [];\n\n for (const profiledTransaction of profiledTransactionEvents) {\n const context = profiledTransaction?.contexts;\n const profile_id = context?.profile?.['profile_id'];\n const start_timestamp = context?.profile?.['start_timestamp'];\n\n if (typeof profile_id !== 'string') {\n DEBUG_BUILD && debug.log('[Profiling] cannot find profile for a span without a profile context');\n continue;\n }\n\n if (!profile_id) {\n DEBUG_BUILD && debug.log('[Profiling] cannot find profile for a span without a profile context');\n continue;\n }\n\n // Remove the profile from the span context before sending, relay will take care of the rest.\n if (context?.profile) {\n delete context.profile;\n }\n\n const profile = takeProfileFromGlobalCache(profile_id);\n if (!profile) {\n DEBUG_BUILD && debug.log(`[Profiling] Could not retrieve profile for span: ${profile_id}`);\n continue;\n }\n\n const profileEvent = createProfilingEvent(\n profile_id,\n start_timestamp as number | undefined,\n profile,\n profiledTransaction as ProfiledEvent,\n );\n if (profileEvent) {\n profilesToAddToEnvelope.push(profileEvent);\n }\n }\n\n addProfilesToEnvelope(envelope as EventEnvelope, profilesToAddToEnvelope);\n });\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const browserProfilingIntegration = defineIntegration(_browserProfilingIntegration);\n"],"names":["rootSpan"],"mappings":"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"}
|