@sentry/browser 11.0.0-rc.0 → 11.0.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/helpers.js +24 -2
- package/build/npm/cjs/dev/helpers.js.map +1 -1
- package/build/npm/cjs/dev/index.js +0 -1
- package/build/npm/cjs/dev/index.js.map +1 -1
- package/build/npm/cjs/dev/integrations/globalhandlers.js +2 -1
- package/build/npm/cjs/dev/integrations/globalhandlers.js.map +1 -1
- package/build/npm/cjs/dev/integrations/httpclient.js +3 -12
- package/build/npm/cjs/dev/integrations/httpclient.js.map +1 -1
- package/build/npm/cjs/dev/integrations/httpcontext.js +6 -0
- package/build/npm/cjs/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/dev/integrations/spotlight.js +4 -1
- package/build/npm/cjs/dev/integrations/spotlight.js.map +1 -1
- package/build/npm/cjs/dev/integrations/webVitals.js.map +1 -1
- package/build/npm/cjs/dev/integrations/webWorker.js +73 -19
- package/build/npm/cjs/dev/integrations/webWorker.js.map +1 -1
- package/build/npm/cjs/dev/tracing/browserTracingIntegration.js +1 -1
- package/build/npm/cjs/dev/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/prod/helpers.js +24 -2
- package/build/npm/cjs/prod/helpers.js.map +1 -1
- package/build/npm/cjs/prod/index.js +0 -1
- package/build/npm/cjs/prod/index.js.map +1 -1
- package/build/npm/cjs/prod/integrations/globalhandlers.js +2 -1
- package/build/npm/cjs/prod/integrations/globalhandlers.js.map +1 -1
- package/build/npm/cjs/prod/integrations/httpclient.js +3 -12
- package/build/npm/cjs/prod/integrations/httpclient.js.map +1 -1
- package/build/npm/cjs/prod/integrations/httpcontext.js +6 -0
- package/build/npm/cjs/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/prod/integrations/spotlight.js +4 -1
- package/build/npm/cjs/prod/integrations/spotlight.js.map +1 -1
- package/build/npm/cjs/prod/integrations/webVitals.js.map +1 -1
- package/build/npm/cjs/prod/integrations/webWorker.js +73 -19
- package/build/npm/cjs/prod/integrations/webWorker.js.map +1 -1
- package/build/npm/cjs/prod/tracing/browserTracingIntegration.js +1 -1
- package/build/npm/cjs/prod/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/dev/helpers.js +24 -3
- package/build/npm/esm/dev/helpers.js.map +1 -1
- package/build/npm/esm/dev/index.js +1 -1
- package/build/npm/esm/dev/integrations/globalhandlers.js +2 -2
- package/build/npm/esm/dev/integrations/globalhandlers.js.map +1 -1
- package/build/npm/esm/dev/integrations/httpclient.js +3 -12
- package/build/npm/esm/dev/integrations/httpclient.js.map +1 -1
- package/build/npm/esm/dev/integrations/httpcontext.js +6 -0
- package/build/npm/esm/dev/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/dev/integrations/spotlight.js +4 -1
- package/build/npm/esm/dev/integrations/spotlight.js.map +1 -1
- package/build/npm/esm/dev/integrations/webVitals.js.map +1 -1
- package/build/npm/esm/dev/integrations/webWorker.js +77 -23
- package/build/npm/esm/dev/integrations/webWorker.js.map +1 -1
- package/build/npm/esm/dev/package.json +1 -1
- package/build/npm/esm/dev/tracing/browserTracingIntegration.js +1 -1
- package/build/npm/esm/dev/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/prod/helpers.js +24 -3
- package/build/npm/esm/prod/helpers.js.map +1 -1
- package/build/npm/esm/prod/index.js +1 -1
- package/build/npm/esm/prod/integrations/globalhandlers.js +2 -2
- package/build/npm/esm/prod/integrations/globalhandlers.js.map +1 -1
- package/build/npm/esm/prod/integrations/httpclient.js +3 -12
- package/build/npm/esm/prod/integrations/httpclient.js.map +1 -1
- package/build/npm/esm/prod/integrations/httpcontext.js +6 -0
- package/build/npm/esm/prod/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/prod/integrations/spotlight.js +4 -1
- package/build/npm/esm/prod/integrations/spotlight.js.map +1 -1
- package/build/npm/esm/prod/integrations/webVitals.js.map +1 -1
- package/build/npm/esm/prod/integrations/webWorker.js +77 -23
- package/build/npm/esm/prod/integrations/webWorker.js.map +1 -1
- package/build/npm/esm/prod/package.json +1 -1
- package/build/npm/esm/prod/tracing/browserTracingIntegration.js +1 -1
- package/build/npm/esm/prod/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/types/exports.d.ts +1 -1
- package/build/npm/types/exports.d.ts.map +1 -1
- package/build/npm/types/helpers.d.ts +10 -2
- package/build/npm/types/helpers.d.ts.map +1 -1
- package/build/npm/types/integrations/globalhandlers.d.ts +4 -0
- package/build/npm/types/integrations/globalhandlers.d.ts.map +1 -1
- package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
- package/build/npm/types/integrations/spotlight.d.ts +9 -2
- package/build/npm/types/integrations/spotlight.d.ts.map +1 -1
- package/build/npm/types/integrations/webVitals.d.ts +1 -1
- package/build/npm/types/integrations/webWorker.d.ts +5 -4
- package/build/npm/types/integrations/webWorker.d.ts.map +1 -1
- package/package.json +7 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browserTracingIntegration.js","sources":["../../../../../src/tracing/browserTracingIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, IntegrationFn, RequestHookInfo, ResponseHookInfo, Span, StartSpanOptions } from '@sentry/core';\nimport {\n addNonEnumerableProperty,\n consoleSandbox,\n dateTimestampInSeconds,\n debug,\n generateSpanId,\n generateTraceId,\n getClient,\n getCurrentScope,\n getDynamicSamplingContextFromSpan,\n GLOBAL_OBJ,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n NAVIGATION_SPAN_NAME_FALLBACK,\n PAGELOAD_SPAN_NAME_FALLBACK,\n isURLObjectRelative,\n parseStringToURLObject,\n propagationContextFromHeaders,\n registerSpanErrorInstrumentation,\n spanIsSampled,\n spanToJSON,\n timestampInSeconds,\n TRACING_DEFAULTS,\n browserPerformanceTimeOrigin,\n} from '@sentry/core';\nimport { _INTERNAL_ensureBrowserSpanStreaming, startIdleSpan, startInactiveSpan } from '@sentry/core/browser';\nimport {\n addHistoryInstrumentationHandler,\n addPerformanceEntries,\n getLocationHref,\n isBotUserAgent,\n startTrackingLongAnimationFrames,\n startTrackingLongTasks,\n} from '@sentry/browser-utils';\nimport { BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { filterCollectedUrl } from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\nimport type { WebVitalsOptions } from '../integrations/webVitals';\nimport { WEB_VITALS_INTEGRATION_NAME, webVitalsIntegration } from '../integrations/webVitals';\nimport { registerBackgroundTabDetection } from './backgroundtab';\nimport { linkTraces } from './linkedTraces';\nimport { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request';\nimport {\n SENTRY_SEGMENT_NAME_SOURCE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n SENTRY_ORIGIN,\n SENTRY_IDLE_SPAN_FINISH_REASON,\n} from '@sentry/conventions/attributes';\nimport { NAVIGATION, NAVIGATION_REDIRECT, PAGELOAD } from '@sentry/conventions/op';\n\nexport const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';\n\n/** Options for Browser Tracing integration */\nexport interface BrowserTracingOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n *\n * Default: 1000 (ms)\n */\n idleTimeout: number;\n\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 30000 (ms)\n */\n finalTimeout: number;\n\n /**\n The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 15000 (ms)\n */\n childSpanTimeout: number;\n\n /**\n * If a span should be created on page load.\n * If this is set to `false`, this integration will not start the default page load span.\n * Default: true\n */\n instrumentPageLoad: boolean;\n\n /**\n * If a span should be created on navigation (history change).\n * If this is set to `false`, this integration will not start the default navigation spans.\n * Default: true\n */\n instrumentNavigation: boolean;\n\n /**\n * If a navigation span should be created when the page is restored from the back/forward cache.\n *\n * This is deliberately independent of {@link BrowserTracingOptions.instrumentNavigation}: a restore\n * is not a history change, and the framework integrations that own their own navigation spans turn\n * that option off without ever handling a restore. The point of this span is trace hygiene, keeping\n * everything after the restore off the trace the page had before it was frozen, so it is worth\n * having even where history instrumentation is not.\n *\n * Default: true\n */\n instrumentBfcacheRestore: boolean;\n\n /**\n * Flag spans where tabs moved to background with \"cancelled\". Browser background tab timing is\n * not suited towards doing precise measurements of operations. By default, we recommend that this option\n * be enabled as background transactions can mess up your statistics in nondeterministic ways.\n *\n * Default: true\n */\n markBackgroundSpan: boolean;\n\n /**\n * If true, Sentry will capture long tasks and add them to the corresponding transaction.\n *\n * Default: true\n */\n enableLongTask: boolean;\n\n /**\n * If true, Sentry will capture long animation frames and add them to the corresponding transaction.\n *\n * Default: false\n */\n enableLongAnimationFrame: boolean;\n\n /**\n * If true, Sentry will capture first input delay and add it to the corresponding transaction.\n *\n * Default: true\n *\n * @deprecated Use {@link BrowserTracingOptions.webVitals} instead: `webVitals: { ignore: ['inp'] }`.\n */\n enableInp: boolean;\n\n /**\n * Options for the `webVitalsIntegration` that is auto-registered when none is present.\n * Ignored if you register `webVitalsIntegration` yourself.\n */\n webVitals?: WebVitalsOptions;\n\n /**\n * @deprecated This option is no longer used. Element timing is now tracked via the standalone\n * `elementTimingIntegration`. Add it to your `integrations` array to collect element timing metrics.\n */\n enableElementTiming?: boolean;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * By default, the SDK will try to detect redirects and avoid creating separate spans for them.\n * If you want to opt-out of this behavior, you can set this option to `false`.\n *\n * Default: true\n */\n detectRedirects: boolean;\n\n /**\n * Link the currently started trace to a previous trace (e.g. a prior pageload, navigation or\n * manually started span). When enabled, this option will allow you to navigate between traces\n * in the Sentry UI.\n *\n * You can set this option to the following values:\n *\n * - `'in-memory'`: The previous trace data will be stored in memory.\n * This is useful for single-page applications and enabled by default.\n *\n * - `'session-storage'`: The previous trace data will be stored in the `sessionStorage`.\n * This is useful for multi-page applications or static sites but it means that the\n * Sentry SDK writes to the browser's `sessionStorage`.\n *\n * - `'off'`: The previous trace data will not be stored or linked.\n *\n * You can also use {@link BrowserTracingOptions.consistentTraceSampling} to get\n * consistent trace sampling of subsequent traces. Otherwise, by default, your\n * `tracesSampleRate` or `tracesSampler` config significantly influences how often\n * traces will be linked.\n *\n * @default 'in-memory' - see explanation above\n */\n linkPreviousTrace: 'in-memory' | 'session-storage' | 'off';\n\n /**\n * If true, Sentry will consistently sample subsequent traces based on the\n * sampling decision of the initial trace. For example, if the initial page\n * load trace was sampled positively, all subsequent traces (e.g. navigations)\n * are also sampled positively. In case the initial trace was sampled negatively,\n * all subsequent traces are also sampled negatively.\n *\n * This option allows you to get consistent, linked traces within a user journey\n * while maintaining an overall quota based on your trace sampling settings.\n *\n * This option is only effective if {@link BrowserTracingOptions.linkPreviousTrace}\n * is enabled (i.e. not set to `'off'`).\n *\n * @default `false` - this is an opt-in feature.\n */\n consistentTraceSampling: boolean;\n\n /**\n * If set to `true`, the pageload span will not end itself automatically, unless it\n * runs until the {@link BrowserTracingOptions.finalTimeout} (30 seconds by default) is reached.\n *\n * Set this option to `true`, if you want full control over the pageload span duration.\n * You can use `Sentry.reportPageLoaded()` to manually end the pageload span whenever convenient.\n * Be aware that you have to ensure that this is always called, regardless of the chosen route\n * or path in the application.\n *\n * @default `false`. By default, the pageload span will end itself automatically, based on\n * the {@link BrowserTracingOptions.finalTimeout}, {@link BrowserTracingOptions.idleTimeout}\n * and {@link BrowserTracingOptions.childSpanTimeout}. This is more convenient to use but means\n * that the pageload duration can be arbitrary and might not be fully representative of a perceived\n * page load time.\n */\n enableReportPageLoaded: boolean;\n\n /**\n * A callback which is called before a span for a pageload or navigation is started.\n * It receives the options passed to `startSpan`, and expects to return an updated options object.\n */\n beforeStartSpan?: (options: StartSpanOptions) => StartSpanOptions;\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 * This callback is invoked directly after a span is started for an outgoing fetch or XHR request.\n * You can use it to annotate the span with additional data or attributes, for example by setting\n * attributes based on the passed request headers.\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\nconst DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {\n ...TRACING_DEFAULTS,\n instrumentNavigation: true,\n instrumentBfcacheRestore: true,\n instrumentPageLoad: true,\n markBackgroundSpan: true,\n enableLongTask: true,\n enableLongAnimationFrame: true,\n // oxlint-disable-next-line typescript/no-deprecated -- still honoured until it is removed\n enableInp: true,\n ignoreResourceSpans: [],\n detectRedirects: true,\n linkPreviousTrace: 'in-memory',\n consistentTraceSampling: false,\n enableReportPageLoaded: false,\n ...defaultRequestInstrumentationOptions,\n};\n\n/**\n * The Browser Tracing integration automatically instruments browser pageload/navigation\n * actions as transactions, and captures requests, metrics and errors as spans.\n *\n * The integration can be configured with a variety of options, and can be extended to use\n * any routing library.\n *\n * We explicitly export the proper type here, as this has to be extended in some cases.\n */\nexport const browserTracingIntegration = ((options: Partial<BrowserTracingOptions> = {}) => {\n if ('enableElementTiming' in options) {\n consoleSandbox(() => {\n // oxlint-disable-next-line no-console\n console.warn(\n '[Sentry] `enableElementTiming` is deprecated and no longer has any effect. Use the standalone `elementTimingIntegration` instead.',\n );\n });\n }\n\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const {\n // oxlint-disable-next-line typescript/no-deprecated -- still honoured until it is removed\n enableInp,\n enableLongTask,\n enableLongAnimationFrame,\n webVitals,\n beforeStartSpan,\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n markBackgroundSpan,\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n ignoreResourceSpans,\n instrumentPageLoad,\n instrumentNavigation,\n instrumentBfcacheRestore,\n detectRedirects,\n linkPreviousTrace,\n consistentTraceSampling,\n enableReportPageLoaded,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...DEFAULT_BROWSER_TRACING_OPTIONS,\n ...options,\n };\n\n const _isBot = isBotUserAgent();\n\n let lastInteractionTimestamp: number | undefined;\n\n let _pageloadSpan: Span | undefined;\n\n /** Create routing idle transaction. */\n function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions, makeActive = true, url?: string): void {\n const isPageloadSpan = startSpanOptions.op === 'pageload';\n\n const initialSpanName = startSpanOptions.name;\n const finalStartSpanOptions: StartSpanOptions = beforeStartSpan\n ? beforeStartSpan(startSpanOptions)\n : startSpanOptions;\n\n // For navigations, `url` is the destination URL, so we use it to reflect the post-navigation location.\n // For pageloads (and manual navigation spans without a URL) we fall back to the current location.\n const urlObject = parseStringToURLObject(url || getLocationHref());\n\n const attributes = {\n ...(urlObject?.pathname && { [URL_PATH]: urlObject.pathname }),\n ...(urlObject && !isURLObjectRelative(urlObject) && { [URL_FULL]: filterCollectedUrl(urlObject.href) }),\n ...finalStartSpanOptions.attributes,\n };\n\n // If `finalStartSpanOptions.name` is different than `startSpanOptions.name`\n // it is because `beforeStartSpan` set a custom name. Therefore we set the source to 'custom'.\n if (initialSpanName !== finalStartSpanOptions.name) {\n attributes[SENTRY_SEGMENT_NAME_SOURCE] = 'custom';\n }\n\n finalStartSpanOptions.attributes = attributes;\n\n if (!makeActive) {\n // We want to ensure this has 0s duration\n const now = dateTimestampInSeconds();\n startInactiveSpan({\n ...finalStartSpanOptions,\n startTime: now,\n }).end(now);\n return;\n }\n\n const idleSpan = startIdleSpan(finalStartSpanOptions, {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n // should wait for finish signal if it's a pageload transaction\n disableAutoFinish: isPageloadSpan,\n trimIdleSpanEndTimestamp: !enableReportPageLoaded,\n });\n\n if (isPageloadSpan && enableReportPageLoaded) {\n _pageloadSpan = idleSpan;\n }\n\n setActiveIdleSpan(client, idleSpan);\n\n function emitFinish(): void {\n if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {\n client.emit('idleSpanEnableAutoFinish', idleSpan);\n // Once the finish signal has been emitted, the listener is no longer needed. Removing it here (rather than\n // relying on `{ once: true }`) also covers the common case where the document is already loaded when the span\n // starts, so the listener never fires and would otherwise leak together with the `idleSpan` it closes over.\n optionalWindowDocument.removeEventListener('readystatechange', emitFinish);\n }\n }\n\n // Enable auto finish of the pageload span if users are not explicitly ending it\n if (isPageloadSpan && !enableReportPageLoaded && optionalWindowDocument) {\n optionalWindowDocument.addEventListener('readystatechange', emitFinish);\n\n emitFinish();\n }\n }\n\n return {\n name: BROWSER_TRACING_INTEGRATION_ID,\n setup(client) {\n if (_isBot) {\n DEBUG_BUILD && debug.log('[Tracing] Skipping browserTracingIntegration setup for bot user agent.');\n return;\n }\n\n registerSpanErrorInstrumentation();\n\n if (\n enableLongAnimationFrame &&\n GLOBAL_OBJ.PerformanceObserver &&\n PerformanceObserver.supportedEntryTypes?.includes('long-animation-frame')\n ) {\n startTrackingLongAnimationFrames();\n } else if (enableLongTask) {\n startTrackingLongTasks();\n }\n\n if (detectRedirects && optionalWindowDocument) {\n const interactionHandler = (): void => {\n lastInteractionTimestamp = timestampInSeconds();\n };\n addEventListener('click', interactionHandler, { capture: true });\n addEventListener('keydown', interactionHandler, { capture: true, passive: true });\n }\n\n function maybeEndActiveSpan(): void {\n const activeSpan = getActiveIdleSpan(client);\n\n if (activeSpan && !spanToJSON(activeSpan).end_timestamp) {\n DEBUG_BUILD &&\n debug.log(\n `[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).attributes[SENTRY_OP]}`,\n );\n // If there's an open active span, we need to finish it before creating an new one.\n activeSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'cancelled');\n activeSpan.end();\n }\n }\n\n client.on('beforeIdleSpanEnd', span => {\n // Interaction idle spans also flow through this hook, but the route bookkeeping below only\n // applies to the pageload/navigation span. We identify it by reference rather than by op:\n // only the route span is registered as the active idle span.\n if (getActiveIdleSpan(client) !== span) {\n return;\n }\n\n addPerformanceEntries(span, {\n ignoreResourceSpans,\n spanStreamingEnabled: hasSpanStreamingEnabled(client),\n });\n setActiveIdleSpan(client, undefined);\n\n // A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.\n // Only when another navigation happens, we want to create a new trace.\n // This way, e.g. errors that occur after the pageload span ended are still associated to the pageload trace.\n const scope = getCurrentScope();\n const oldPropagationContext = scope.getPropagationContext();\n\n scope.setPropagationContext({\n ...oldPropagationContext,\n traceId: span.spanContext().traceId,\n sampled: spanIsSampled(span),\n dsc: getDynamicSamplingContextFromSpan(span),\n });\n\n if (_pageloadSpan === span) {\n // clean up the stored pageload span on the integration.\n _pageloadSpan = undefined;\n }\n });\n\n client.on('startNavigationSpan', (startSpanOptions, navigationOptions) => {\n if (getClient() !== client) {\n return;\n }\n\n if (navigationOptions?.isRedirect) {\n DEBUG_BUILD &&\n debug.warn('[Tracing] Detected redirect, navigation span will not be the root span, but a child span.');\n _createRouteSpan(\n client,\n {\n op: NAVIGATION_REDIRECT,\n ...startSpanOptions,\n },\n false,\n navigationOptions.url,\n );\n return;\n }\n\n // Reset the last interaction timestamp since we now start a new navigation.\n // Any subsequent navigation span starts could again be a redirect, so we\n // should reset our heuristic detectors.\n lastInteractionTimestamp = undefined;\n\n maybeEndActiveSpan();\n\n const scope = getCurrentScope();\n scope.setPropagationContext({\n traceId: generateTraceId(),\n sampleRand: Math.random(),\n propagationSpanId: hasSpansEnabled() ? undefined : generateSpanId(),\n });\n\n // We reset this to ensure we do not have lingering incorrect data here\n // places that call this hook may set this where appropriate - else, the URL at span sending time is used\n scope.setSDKProcessingMetadata({\n normalizedRequest: undefined,\n });\n\n _createRouteSpan(\n client,\n {\n op: NAVIGATION,\n ...startSpanOptions,\n // Navigation starts a new trace and is NOT parented under any active interaction (e.g. ui.action.click)\n parentSpan: null,\n },\n true,\n navigationOptions?.url,\n );\n });\n\n client.on('startPageLoadSpan', (startSpanOptions, traceOptions = {}) => {\n if (getClient() !== client) {\n return;\n }\n maybeEndActiveSpan();\n\n const sentryTrace =\n traceOptions.sentryTrace || getMetaContent('sentry-trace') || getServerTiming('sentry-trace');\n const baggage = traceOptions.baggage || getMetaContent('baggage') || getServerTiming('baggage');\n\n const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);\n\n const scope = getCurrentScope();\n scope.setPropagationContext(propagationContext);\n if (!hasSpansEnabled()) {\n // for browser, we wanna keep the spanIds consistent during the entire lifetime of the trace\n // this works by setting the propagationSpanId to a random spanId so that we have a consistent\n // span id to propagate in TwP mode (!hasSpansEnabled())\n scope.getPropagationContext().propagationSpanId = generateSpanId();\n }\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n scope.setSDKProcessingMetadata({\n normalizedRequest: getHttpRequestData(),\n });\n\n _createRouteSpan(client, {\n op: PAGELOAD,\n ...startSpanOptions,\n });\n });\n\n client.on('endPageloadSpan', () => {\n if (enableReportPageLoaded && _pageloadSpan) {\n _pageloadSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'reportPageLoaded');\n _pageloadSpan.end();\n }\n });\n\n // `pagehide` is the last moment a document leaving the page can still send. We cannot rely on\n // `registerBackgroundTabDetection`, which ends the span on `visibilitychange`: the client's own\n // `visibilitychange` flush is registered first and its deferring microtask runs after that\n // listener but before background tab detection's, so the buffer is still empty when it drains.\n // The segment span is buffered right after with nothing left to flush it, and the children have\n // been streamed all along, which leaves a rootless trace. Ending and flushing together here\n // keeps this self-contained instead of depending on that ordering.\n WINDOW.addEventListener?.('pagehide', () => {\n const activeSpan = getActiveIdleSpan(client);\n if (activeSpan && !spanToJSON(activeSpan).end_timestamp) {\n activeSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'documentHidden');\n activeSpan.end();\n }\n void client.flush();\n });\n },\n\n afterAllSetup(client) {\n if (_isBot) {\n return;\n }\n\n // Technically, every startSpan call already ensures that `spanStreamingIntegration` is installed,\n // but we do it here anyway for the edge case that users disabled pageload and navigation spans and\n // purely rely on manual startSpan calls.\n _INTERNAL_ensureBrowserSpanStreaming(client);\n\n // Auto-register webVitalsIntegration if the user hasn't added one. We do this in\n // afterAllSetup so that a user-provided webVitalsIntegration - which may be ordered after\n // browserTracingIntegration in the integrations array - has already been installed.\n if (client.addIntegration && !client.getIntegrationByName?.(WEB_VITALS_INTEGRATION_NAME)) {\n const ignore = webVitals?.ignore ?? [];\n client.addIntegration(\n webVitalsIntegration({\n ...webVitals,\n ignore: enableInp || ignore.includes('inp') ? ignore : [...ignore, 'inp'],\n }),\n );\n }\n\n let startingUrl: string | undefined = getLocationHref();\n\n if (linkPreviousTrace !== 'off') {\n linkTraces(client, { linkPreviousTrace, consistentTraceSampling });\n }\n\n if (WINDOW.location) {\n if (instrumentPageLoad) {\n startBrowserTracingPageLoadSpan(client, {\n // With span streaming, span names have to be low cardinality, and there is no route\n // information available here.\n name: hasSpanStreamingEnabled(client) ? PAGELOAD_SPAN_NAME_FALLBACK : WINDOW.location.pathname,\n attributes: {\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SENTRY_ORIGIN]: 'auto.pageload.browser',\n },\n });\n }\n\n if (instrumentNavigation) {\n addHistoryInstrumentationHandler(({ to, from }) => {\n /**\n * This early return is there to account for some cases where a navigation transaction starts right after\n * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't\n * create an uneccessary navigation transaction.\n *\n * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also\n * only be caused in certain development environments where the usage of a hot module reloader is causing\n * errors.\n */\n if (from === undefined && startingUrl !== undefined && startingUrl.indexOf(to) !== -1) {\n startingUrl = undefined;\n return;\n }\n\n startingUrl = undefined;\n const parsed = parseStringToURLObject(to);\n const activeSpan = getActiveIdleSpan(client);\n const navigationIsRedirect =\n activeSpan && detectRedirects && isRedirect(activeSpan, lastInteractionTimestamp);\n\n startBrowserTracingNavigationSpan(\n client,\n {\n // With span streaming, span names have to be low cardinality, and there is no route\n // information available here.\n name: hasSpanStreamingEnabled(client)\n ? NAVIGATION_SPAN_NAME_FALLBACK\n : parsed?.pathname || WINDOW.location.pathname,\n attributes: {\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SENTRY_ORIGIN]: 'auto.navigation.browser',\n },\n },\n { url: to, isRedirect: navigationIsRedirect },\n );\n });\n }\n\n // A bfcache restore resurrects the frozen document, so there is no document load and no\n // usable history event: `popstate` either doesn't fire or is swallowed because the URL is\n // unchanged from when the page was frozen. Without a span of its own, everything after the\n // restore joins the trace the page had before it was frozen, separated by however long it\n // sat in the cache.\n if (instrumentBfcacheRestore) {\n WINDOW.addEventListener?.('pageshow', (event: PageTransitionEvent) => {\n if (!event.persisted) {\n return;\n }\n\n // A navigation has happened, so the pageload guard in the history handler above must not\n // suppress the next one.\n startingUrl = undefined;\n\n startBrowserTracingNavigationSpan(\n client,\n {\n // Deliberately no `startTime`: the span starts now, at the restore. The\n // `PerformanceNavigationTiming` entry still describes the original document load and\n // would date the span to before the page was frozen.\n //\n // TODO(routing): resolve the parameterized route via the route provider (#23551) and set\n // the source from it. No router event fires on a restore, so in a framework app this is\n // the only navigation span still named from a raw pathname.\n name: hasSpanStreamingEnabled(client)\n ? NAVIGATION_SPAN_NAME_FALLBACK\n : WINDOW.location?.pathname || '/',\n attributes: {\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SENTRY_ORIGIN]: 'auto.navigation.browser.bfcache',\n // A bfcache restore is near-instant, so these spans would otherwise drag\n // navigation duration percentiles down with no way to tell them apart.\n [BROWSER_NAVIGATION_TYPE]: 'bfcache',\n },\n },\n { url: WINDOW.location?.href },\n );\n });\n }\n }\n\n if (markBackgroundSpan) {\n registerBackgroundTabDetection();\n }\n\n instrumentOutgoingRequests(client, {\n traceFetch,\n traceXHR,\n tracePropagationTargets: client.getOptions().tracePropagationTargets,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n onRequestSpanStart,\n onRequestSpanEnd,\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Manually start a page load span.\n * This will only do something if a browser tracing integration integration has been setup.\n *\n * If you provide a custom `traceOptions` object, it will be used to continue the trace\n * instead of the default behavior, which is to look it up on the <meta> tags.\n */\nexport function startBrowserTracingPageLoadSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n traceOptions?: { sentryTrace?: string | undefined; baggage?: string | undefined },\n): Span | undefined {\n // `Pageload` is a low-cardinality span name, not a description of the page. The scope's\n // transaction name is what error events are grouped by, so it keeps the URL instead.\n const isFallbackSpanName = spanOptions.name === PAGELOAD_SPAN_NAME_FALLBACK;\n getCurrentScope().setTransactionName(isFallbackSpanName ? WINDOW.location?.pathname : spanOptions.name);\n // A pageload span always covers the entire page load, no matter how late the SDK or a routing\n // instrumentation gets around to starting it. Everything that happened before (DNS, TLS, TTFB,\n // HTML parsing, chunk loading) is part of the page load and the performance child spans we attach\n // later are anchored at the time origin anyway.\n const timeOrigin = browserPerformanceTimeOrigin();\n const pageloadSpanOptions: StartSpanOptions = {\n ...spanOptions,\n // startTime needs to be in seconds, not ms\n startTime: spanOptions.startTime ?? (timeOrigin ? timeOrigin / 1000 : undefined),\n };\n\n client.emit('startPageLoadSpan', pageloadSpanOptions, traceOptions);\n\n const pageloadSpan = getActiveIdleSpan(client);\n\n if (pageloadSpan) {\n client.emit('afterStartPageLoadSpan', pageloadSpan);\n }\n\n return pageloadSpan;\n}\n\n/**\n * Manually start a navigation span.\n * This will only do something if a browser tracing integration has been setup.\n */\nexport function startBrowserTracingNavigationSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n options?: { url?: string; isRedirect?: boolean },\n): Span | undefined {\n const { url, isRedirect } = options || {};\n client.emit('beforeStartNavigationSpan', spanOptions, { isRedirect, url });\n client.emit('startNavigationSpan', spanOptions, { isRedirect, url });\n\n const scope = getCurrentScope();\n // `Navigation` is a low-cardinality span name, not a description of the page. The scope's\n // transaction name is what error events are grouped by, so it keeps the URL instead. `url` is the\n // destination, while `location` still points at the previous page during a `pushState`.\n const isFallbackSpanName = spanOptions.name === NAVIGATION_SPAN_NAME_FALLBACK;\n scope.setTransactionName(\n isFallbackSpanName ? (url && parseStringToURLObject(url)?.pathname) || WINDOW.location?.pathname : spanOptions.name,\n );\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n if (url && !isRedirect) {\n scope.setSDKProcessingMetadata({\n normalizedRequest: {\n ...getHttpRequestData(),\n url,\n },\n });\n }\n\n return getActiveIdleSpan(client);\n}\n\n/** Returns the value of a meta tag */\nexport function getMetaContent(metaName: string): string | undefined {\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const metaTag = optionalWindowDocument?.querySelector(`meta[name=${metaName}]`);\n return metaTag?.getAttribute('content') || undefined;\n}\n\n/** Returns the description of a server timing entry */\nexport function getServerTiming(name: string): string | undefined {\n // The cast is required for the declaration build (`build:types`), which resolves\n // `getEntriesByType('navigation')` to `PerformanceEntry[]` (no `serverTiming`). It only reads as\n // \"unnecessary\" to the type-aware linter, which runs with web-vitals' global augmentation applied.\n const navigation = WINDOW.performance?.getEntriesByType?.('navigation')[0] as PerformanceNavigationTiming | undefined;\n const entry = navigation?.serverTiming?.find(entry => entry.name === name);\n return entry?.description;\n}\n\n// We store the active idle span on the client object, so we can access it from exported functions\nconst ACTIVE_IDLE_SPAN_PROPERTY = '_sentry_idleSpan';\nfunction getActiveIdleSpan(client: Client): Span | undefined {\n return (client as { [ACTIVE_IDLE_SPAN_PROPERTY]?: Span })[ACTIVE_IDLE_SPAN_PROPERTY];\n}\n\nfunction setActiveIdleSpan(client: Client, span: Span | undefined): void {\n addNonEnumerableProperty(client, ACTIVE_IDLE_SPAN_PROPERTY, span);\n}\n\n// The max. time in seconds between two pageload/navigation spans that makes us consider the second one a redirect\nconst REDIRECT_THRESHOLD = 1.5;\n\nfunction isRedirect(activeSpan: Span, lastInteractionTimestamp: number | undefined): boolean {\n const spanData = spanToJSON(activeSpan);\n\n const now = dateTimestampInSeconds();\n\n // More than REDIRECT_THRESHOLD seconds since last navigation/pageload span?\n // --> never consider this a redirect\n const startTimestamp = spanData.start_timestamp;\n if (now - startTimestamp > REDIRECT_THRESHOLD) {\n return false;\n }\n\n // A click happened in the last REDIRECT_THRESHOLD seconds?\n // --> never consider this a redirect\n if (lastInteractionTimestamp && now - lastInteractionTimestamp <= REDIRECT_THRESHOLD) {\n return false;\n }\n\n return true;\n}\n"],"names":["TRACING_DEFAULTS","defaultRequestInstrumentationOptions","consoleSandbox","WINDOW","webVitals","isBotUserAgent","parseStringToURLObject","getLocationHref","attributes","URL_PATH","isURLObjectRelative","URL_FULL","filterCollectedUrl","SENTRY_SEGMENT_NAME_SOURCE","dateTimestampInSeconds","startInactiveSpan","startIdleSpan","DEBUG_BUILD","debug","registerSpanErrorInstrumentation","GLOBAL_OBJ","startTrackingLongAnimationFrames","startTrackingLongTasks","timestampInSeconds","spanToJSON","SENTRY_OP","SENTRY_IDLE_SPAN_FINISH_REASON","addPerformanceEntries","hasSpanStreamingEnabled","getCurrentScope","spanIsSampled","getDynamicSamplingContextFromSpan","getClient","NAVIGATION_REDIRECT","generateTraceId","hasSpansEnabled","generateSpanId","NAVIGATION","propagationContextFromHeaders","getHttpRequestData","PAGELOAD","_INTERNAL_ensureBrowserSpanStreaming","WEB_VITALS_INTEGRATION_NAME","webVitalsIntegration","linkTraces","PAGELOAD_SPAN_NAME_FALLBACK","SENTRY_ORIGIN","addHistoryInstrumentationHandler","NAVIGATION_SPAN_NAME_FALLBACK","BROWSER_NAVIGATION_TYPE","registerBackgroundTabDetection","instrumentOutgoingRequests","browserPerformanceTimeOrigin","isRedirect","entry","addNonEnumerableProperty"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"browserTracingIntegration.js","sources":["../../../../../src/tracing/browserTracingIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type { Client, IntegrationFn, RequestHookInfo, ResponseHookInfo, Span, StartSpanOptions } from '@sentry/core';\nimport {\n addNonEnumerableProperty,\n consoleSandbox,\n dateTimestampInSeconds,\n debug,\n generateSpanId,\n generateTraceId,\n getClient,\n getCurrentScope,\n getDynamicSamplingContextFromSpan,\n GLOBAL_OBJ,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n NAVIGATION_SPAN_NAME_FALLBACK,\n PAGELOAD_SPAN_NAME_FALLBACK,\n isURLObjectRelative,\n parseStringToURLObject,\n propagationContextFromHeaders,\n registerSpanErrorInstrumentation,\n spanIsSampled,\n spanToJSON,\n timestampInSeconds,\n TRACING_DEFAULTS,\n browserPerformanceTimeOrigin,\n} from '@sentry/core';\nimport { _INTERNAL_ensureBrowserSpanStreaming, startIdleSpan, startInactiveSpan } from '@sentry/core/browser';\nimport {\n addHistoryInstrumentationHandler,\n addPerformanceEntries,\n getLocationHref,\n isBotUserAgent,\n startTrackingLongAnimationFrames,\n startTrackingLongTasks,\n} from '@sentry/browser-utils';\nimport { BROWSER_NAVIGATION_TYPE } from '@sentry/conventions/attributes';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { filterCollectedUrl } from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\nimport type { WebVitalsOptions } from '../integrations/webVitals';\nimport { WEB_VITALS_INTEGRATION_NAME, webVitalsIntegration } from '../integrations/webVitals';\nimport { registerBackgroundTabDetection } from './backgroundtab';\nimport { linkTraces } from './linkedTraces';\nimport { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request';\nimport {\n SENTRY_SEGMENT_NAME_SOURCE,\n SENTRY_OP,\n URL_FULL,\n URL_PATH,\n SENTRY_ORIGIN,\n SENTRY_IDLE_SPAN_FINISH_REASON,\n} from '@sentry/conventions/attributes';\nimport { NAVIGATION, NAVIGATION_REDIRECT, PAGELOAD } from '@sentry/conventions/op';\n\nexport const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';\n\n/** Options for Browser Tracing integration */\nexport interface BrowserTracingOptions {\n /**\n * The time that has to pass without any span being created.\n * If this time is exceeded, the idle span will finish.\n *\n * Default: 1000 (ms)\n */\n idleTimeout: number;\n\n /**\n * The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 30000 (ms)\n */\n finalTimeout: number;\n\n /**\n The max. time an idle span may run.\n * If this time is exceeded, the idle span will finish no matter what.\n *\n * Default: 15000 (ms)\n */\n childSpanTimeout: number;\n\n /**\n * If a span should be created on page load.\n * If this is set to `false`, this integration will not start the default page load span.\n * Default: true\n */\n instrumentPageLoad: boolean;\n\n /**\n * If a span should be created on navigation (history change).\n * If this is set to `false`, this integration will not start the default navigation spans.\n * Default: true\n */\n instrumentNavigation: boolean;\n\n /**\n * If a navigation span should be created when the page is restored from the back/forward cache.\n *\n * This is deliberately independent of {@link BrowserTracingOptions.instrumentNavigation}: a restore\n * is not a history change, and the framework integrations that own their own navigation spans turn\n * that option off without ever handling a restore. The point of this span is trace hygiene, keeping\n * everything after the restore off the trace the page had before it was frozen, so it is worth\n * having even where history instrumentation is not.\n *\n * Default: true\n */\n instrumentBfcacheRestore: boolean;\n\n /**\n * Flag spans where tabs moved to background with \"cancelled\". Browser background tab timing is\n * not suited towards doing precise measurements of operations. By default, we recommend that this option\n * be enabled as background transactions can mess up your statistics in nondeterministic ways.\n *\n * Default: true\n */\n markBackgroundSpan: boolean;\n\n /**\n * If true, Sentry will capture long tasks and add them to the corresponding transaction.\n *\n * Default: true\n */\n enableLongTask: boolean;\n\n /**\n * If true, Sentry will capture long animation frames and add them to the corresponding transaction.\n *\n * Default: false\n */\n enableLongAnimationFrame: boolean;\n\n /**\n * If true, Sentry will capture first input delay and add it to the corresponding transaction.\n *\n * Default: true\n *\n * @deprecated Use {@link BrowserTracingOptions.webVitals} instead: `webVitals: { ignore: ['inp'] }`.\n */\n enableInp: boolean;\n\n /**\n * Options for the `webVitalsIntegration` that is auto-registered when none is present.\n * Ignored if you register `webVitalsIntegration` yourself.\n */\n webVitals?: WebVitalsOptions;\n\n /**\n * @deprecated This option is no longer used. Element timing is now tracked via the standalone\n * `elementTimingIntegration`. Add it to your `integrations` array to collect element timing metrics.\n */\n enableElementTiming?: boolean;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * Resource spans with `op`s matching strings in the array will not be emitted.\n *\n * Default: []\n */\n ignoreResourceSpans: Array<'resource.script' | 'resource.css' | 'resource.img' | 'resource.other' | string>;\n\n /**\n * By default, the SDK will try to detect redirects and avoid creating separate spans for them.\n * If you want to opt-out of this behavior, you can set this option to `false`.\n *\n * Default: true\n */\n detectRedirects: boolean;\n\n /**\n * Link the currently started trace to a previous trace (e.g. a prior pageload, navigation or\n * manually started span). When enabled, this option will allow you to navigate between traces\n * in the Sentry UI.\n *\n * You can set this option to the following values:\n *\n * - `'in-memory'`: The previous trace data will be stored in memory.\n * This is useful for single-page applications and enabled by default.\n *\n * - `'session-storage'`: The previous trace data will be stored in the `sessionStorage`.\n * This is useful for multi-page applications or static sites but it means that the\n * Sentry SDK writes to the browser's `sessionStorage`.\n *\n * - `'off'`: The previous trace data will not be stored or linked.\n *\n * You can also use {@link BrowserTracingOptions.consistentTraceSampling} to get\n * consistent trace sampling of subsequent traces. Otherwise, by default, your\n * `tracesSampleRate` or `tracesSampler` config significantly influences how often\n * traces will be linked.\n *\n * @default 'in-memory' - see explanation above\n */\n linkPreviousTrace: 'in-memory' | 'session-storage' | 'off';\n\n /**\n * If true, Sentry will consistently sample subsequent traces based on the\n * sampling decision of the initial trace. For example, if the initial page\n * load trace was sampled positively, all subsequent traces (e.g. navigations)\n * are also sampled positively. In case the initial trace was sampled negatively,\n * all subsequent traces are also sampled negatively.\n *\n * This option allows you to get consistent, linked traces within a user journey\n * while maintaining an overall quota based on your trace sampling settings.\n *\n * This option is only effective if {@link BrowserTracingOptions.linkPreviousTrace}\n * is enabled (i.e. not set to `'off'`).\n *\n * @default `false` - this is an opt-in feature.\n */\n consistentTraceSampling: boolean;\n\n /**\n * If set to `true`, the pageload span will not end itself automatically, unless it\n * runs until the {@link BrowserTracingOptions.finalTimeout} (30 seconds by default) is reached.\n *\n * Set this option to `true`, if you want full control over the pageload span duration.\n * You can use `Sentry.reportPageLoaded()` to manually end the pageload span whenever convenient.\n * Be aware that you have to ensure that this is always called, regardless of the chosen route\n * or path in the application.\n *\n * @default `false`. By default, the pageload span will end itself automatically, based on\n * the {@link BrowserTracingOptions.finalTimeout}, {@link BrowserTracingOptions.idleTimeout}\n * and {@link BrowserTracingOptions.childSpanTimeout}. This is more convenient to use but means\n * that the pageload duration can be arbitrary and might not be fully representative of a perceived\n * page load time.\n */\n enableReportPageLoaded: boolean;\n\n /**\n * A callback which is called before a span for a pageload or navigation is started.\n * It receives the options passed to `startSpan`, and expects to return an updated options object.\n */\n beforeStartSpan?: (options: StartSpanOptions) => StartSpanOptions;\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 * This callback is invoked directly after a span is started for an outgoing fetch or XHR request.\n * You can use it to annotate the span with additional data or attributes, for example by setting\n * attributes based on the passed request headers.\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\nconst DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {\n ...TRACING_DEFAULTS,\n instrumentNavigation: true,\n instrumentBfcacheRestore: true,\n instrumentPageLoad: true,\n markBackgroundSpan: true,\n enableLongTask: true,\n enableLongAnimationFrame: true,\n // oxlint-disable-next-line typescript/no-deprecated -- still honoured until it is removed\n enableInp: true,\n ignoreResourceSpans: [],\n detectRedirects: true,\n linkPreviousTrace: 'in-memory',\n consistentTraceSampling: false,\n enableReportPageLoaded: false,\n ...defaultRequestInstrumentationOptions,\n};\n\n/**\n * The Browser Tracing integration automatically instruments browser pageload/navigation\n * actions as transactions, and captures requests, metrics and errors as spans.\n *\n * The integration can be configured with a variety of options, and can be extended to use\n * any routing library.\n *\n * We explicitly export the proper type here, as this has to be extended in some cases.\n */\nexport const browserTracingIntegration = ((options: Partial<BrowserTracingOptions> = {}) => {\n if ('enableElementTiming' in options) {\n consoleSandbox(() => {\n // oxlint-disable-next-line no-console\n console.warn(\n '[Sentry] `enableElementTiming` is deprecated and no longer has any effect. Use the standalone `elementTimingIntegration` instead.',\n );\n });\n }\n\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const {\n // oxlint-disable-next-line typescript/no-deprecated -- still honoured until it is removed\n enableInp,\n enableLongTask,\n enableLongAnimationFrame,\n webVitals,\n beforeStartSpan,\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n markBackgroundSpan,\n traceFetch,\n traceXHR,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n ignoreResourceSpans,\n instrumentPageLoad,\n instrumentNavigation,\n instrumentBfcacheRestore,\n detectRedirects,\n linkPreviousTrace,\n consistentTraceSampling,\n enableReportPageLoaded,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...DEFAULT_BROWSER_TRACING_OPTIONS,\n ...options,\n };\n\n const _isBot = isBotUserAgent();\n\n let lastInteractionTimestamp: number | undefined;\n\n let _pageloadSpan: Span | undefined;\n\n /** Create routing idle transaction. */\n function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions, makeActive = true, url?: string): void {\n const isPageloadSpan = startSpanOptions.op === 'pageload';\n\n const initialSpanName = startSpanOptions.name;\n const finalStartSpanOptions: StartSpanOptions = beforeStartSpan\n ? beforeStartSpan(startSpanOptions)\n : startSpanOptions;\n\n // For navigations, `url` is the destination URL, so we use it to reflect the post-navigation location.\n // For pageloads (and manual navigation spans without a URL) we fall back to the current location.\n const urlObject = parseStringToURLObject(url || getLocationHref());\n\n const attributes = {\n ...(urlObject?.pathname && { [URL_PATH]: urlObject.pathname }),\n ...(urlObject && !isURLObjectRelative(urlObject) && { [URL_FULL]: filterCollectedUrl(urlObject.href) }),\n ...finalStartSpanOptions.attributes,\n };\n\n // If `finalStartSpanOptions.name` is different than `startSpanOptions.name`\n // it is because `beforeStartSpan` set a custom name. Therefore we set the source to 'custom'.\n if (initialSpanName !== finalStartSpanOptions.name) {\n attributes[SENTRY_SEGMENT_NAME_SOURCE] = 'custom';\n }\n\n finalStartSpanOptions.attributes = attributes;\n\n if (!makeActive) {\n // We want to ensure this has 0s duration\n const now = dateTimestampInSeconds();\n startInactiveSpan({\n ...finalStartSpanOptions,\n startTime: now,\n }).end(now);\n return;\n }\n\n const idleSpan = startIdleSpan(finalStartSpanOptions, {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n // should wait for finish signal if it's a pageload transaction\n disableAutoFinish: isPageloadSpan,\n trimIdleSpanEndTimestamp: !enableReportPageLoaded,\n });\n\n if (isPageloadSpan && enableReportPageLoaded) {\n _pageloadSpan = idleSpan;\n }\n\n setActiveIdleSpan(client, idleSpan);\n\n function emitFinish(): void {\n if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {\n client.emit('idleSpanEnableAutoFinish', idleSpan);\n // Once the finish signal has been emitted, the listener is no longer needed. Removing it here (rather than\n // relying on `{ once: true }`) also covers the common case where the document is already loaded when the span\n // starts, so the listener never fires and would otherwise leak together with the `idleSpan` it closes over.\n optionalWindowDocument.removeEventListener('readystatechange', emitFinish);\n }\n }\n\n // Enable auto finish of the pageload span if users are not explicitly ending it\n if (isPageloadSpan && !enableReportPageLoaded && optionalWindowDocument) {\n optionalWindowDocument.addEventListener('readystatechange', emitFinish);\n\n emitFinish();\n }\n }\n\n return {\n name: BROWSER_TRACING_INTEGRATION_ID,\n setup(client) {\n if (_isBot) {\n DEBUG_BUILD && debug.log('[Tracing] Skipping browserTracingIntegration setup for bot user agent.');\n return;\n }\n\n registerSpanErrorInstrumentation();\n\n if (\n enableLongAnimationFrame &&\n GLOBAL_OBJ.PerformanceObserver &&\n PerformanceObserver.supportedEntryTypes?.includes('long-animation-frame')\n ) {\n startTrackingLongAnimationFrames();\n } else if (enableLongTask) {\n startTrackingLongTasks();\n }\n\n if (detectRedirects && optionalWindowDocument) {\n const interactionHandler = (): void => {\n lastInteractionTimestamp = timestampInSeconds();\n };\n addEventListener('click', interactionHandler, { capture: true });\n addEventListener('keydown', interactionHandler, { capture: true, passive: true });\n }\n\n function maybeEndActiveSpan(): void {\n const activeSpan = getActiveIdleSpan(client);\n\n if (activeSpan && !spanToJSON(activeSpan).end_timestamp) {\n DEBUG_BUILD &&\n debug.log(\n `[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).attributes[SENTRY_OP]}`,\n );\n // If there's an open active span, we need to finish it before creating an new one.\n activeSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'cancelled');\n activeSpan.end();\n }\n }\n\n client.on('beforeIdleSpanEnd', span => {\n // Interaction idle spans also flow through this hook, but the route bookkeeping below only\n // applies to the pageload/navigation span. We identify it by reference rather than by op:\n // only the route span is registered as the active idle span.\n if (getActiveIdleSpan(client) !== span) {\n return;\n }\n\n addPerformanceEntries(span, {\n ignoreResourceSpans,\n spanStreamingEnabled: hasSpanStreamingEnabled(client),\n });\n setActiveIdleSpan(client, undefined);\n\n // A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.\n // Only when another navigation happens, we want to create a new trace.\n // This way, e.g. errors that occur after the pageload span ended are still associated to the pageload trace.\n const scope = getCurrentScope();\n const oldPropagationContext = scope.getPropagationContext();\n\n scope.setPropagationContext({\n ...oldPropagationContext,\n traceId: span.spanContext().traceId,\n sampled: spanIsSampled(span),\n dsc: getDynamicSamplingContextFromSpan(span),\n });\n\n if (_pageloadSpan === span) {\n // clean up the stored pageload span on the integration.\n _pageloadSpan = undefined;\n }\n });\n\n client.on('startNavigationSpan', (startSpanOptions, navigationOptions) => {\n if (getClient() !== client) {\n return;\n }\n\n if (navigationOptions?.isRedirect) {\n DEBUG_BUILD &&\n debug.warn('[Tracing] Detected redirect, navigation span will not be the root span, but a child span.');\n _createRouteSpan(\n client,\n {\n op: NAVIGATION_REDIRECT,\n ...startSpanOptions,\n },\n false,\n navigationOptions.url,\n );\n return;\n }\n\n // Reset the last interaction timestamp since we now start a new navigation.\n // Any subsequent navigation span starts could again be a redirect, so we\n // should reset our heuristic detectors.\n lastInteractionTimestamp = undefined;\n\n maybeEndActiveSpan();\n\n const scope = getCurrentScope();\n scope.setPropagationContext({\n traceId: generateTraceId(),\n sampleRand: Math.random(),\n propagationSpanId: hasSpansEnabled() ? undefined : generateSpanId(),\n });\n\n // We reset this to ensure we do not have lingering incorrect data here\n // places that call this hook may set this where appropriate - else, the URL at span sending time is used\n scope.setSDKProcessingMetadata({\n normalizedRequest: undefined,\n });\n\n _createRouteSpan(\n client,\n {\n op: NAVIGATION,\n ...startSpanOptions,\n // Navigation starts a new trace and is NOT parented under any active interaction (e.g. ui.action.click)\n parentSpan: null,\n },\n true,\n navigationOptions?.url,\n );\n });\n\n client.on('startPageLoadSpan', (startSpanOptions, traceOptions = {}) => {\n if (getClient() !== client) {\n return;\n }\n maybeEndActiveSpan();\n\n const sentryTrace =\n traceOptions.sentryTrace || getMetaContent('sentry-trace') || getServerTiming('sentry-trace');\n const baggage = traceOptions.baggage || getMetaContent('baggage') || getServerTiming('baggage');\n\n const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);\n\n const scope = getCurrentScope();\n scope.setPropagationContext(propagationContext);\n if (!hasSpansEnabled()) {\n // for browser, we wanna keep the spanIds consistent during the entire lifetime of the trace\n // this works by setting the propagationSpanId to a random spanId so that we have a consistent\n // span id to propagate in TwP mode (!hasSpansEnabled())\n scope.getPropagationContext().propagationSpanId = generateSpanId();\n }\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n scope.setSDKProcessingMetadata({\n normalizedRequest: getHttpRequestData(),\n });\n\n _createRouteSpan(client, {\n op: PAGELOAD,\n ...startSpanOptions,\n });\n });\n\n client.on('endPageloadSpan', () => {\n if (enableReportPageLoaded && _pageloadSpan) {\n _pageloadSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'reportPageLoaded');\n _pageloadSpan.end();\n }\n });\n\n // `pagehide` is the last moment a document leaving the page can still send. We cannot rely on\n // `registerBackgroundTabDetection`, which ends the span on `visibilitychange`: the client's own\n // `visibilitychange` flush is registered first and its deferring microtask runs after that\n // listener but before background tab detection's, so the buffer is still empty when it drains.\n // The segment span is buffered right after with nothing left to flush it, and the children have\n // been streamed all along, which leaves a rootless trace. Ending and flushing together here\n // keeps this self-contained instead of depending on that ordering.\n WINDOW.addEventListener?.('pagehide', () => {\n const activeSpan = getActiveIdleSpan(client);\n if (activeSpan && !spanToJSON(activeSpan).end_timestamp) {\n activeSpan.setAttribute(SENTRY_IDLE_SPAN_FINISH_REASON, 'documentHidden');\n activeSpan.end();\n }\n void client.flush();\n });\n },\n\n afterAllSetup(client) {\n if (_isBot) {\n return;\n }\n\n // Technically, every startSpan call already ensures that `spanStreamingIntegration` is installed,\n // but we do it here anyway for the edge case that users disabled pageload and navigation spans and\n // purely rely on manual startSpan calls.\n _INTERNAL_ensureBrowserSpanStreaming(client);\n\n // Auto-register webVitalsIntegration if the user hasn't added one. We do this in\n // afterAllSetup so that a user-provided webVitalsIntegration - which may be ordered after\n // browserTracingIntegration in the integrations array - has already been installed.\n if (client.addIntegration && !client.getIntegrationByName?.(WEB_VITALS_INTEGRATION_NAME)) {\n const ignore = webVitals?.ignore ?? [];\n client.addIntegration(\n webVitalsIntegration({\n ...webVitals,\n ignore: enableInp || ignore.includes('inp') ? ignore : [...ignore, 'inp'],\n }),\n );\n }\n\n let startingUrl: string | undefined = getLocationHref();\n\n if (linkPreviousTrace !== 'off') {\n linkTraces(client, { linkPreviousTrace, consistentTraceSampling });\n }\n\n if (WINDOW.location) {\n if (instrumentPageLoad) {\n startBrowserTracingPageLoadSpan(client, {\n // With span streaming, span names have to be low cardinality, and there is no route\n // information available here.\n name: hasSpanStreamingEnabled(client) ? PAGELOAD_SPAN_NAME_FALLBACK : WINDOW.location.pathname,\n attributes: {\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SENTRY_ORIGIN]: 'auto.pageload.browser',\n },\n });\n }\n\n if (instrumentNavigation) {\n addHistoryInstrumentationHandler(({ to, from }) => {\n /**\n * This early return is there to account for some cases where a navigation transaction starts right after\n * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't\n * create an uneccessary navigation transaction.\n *\n * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also\n * only be caused in certain development environments where the usage of a hot module reloader is causing\n * errors.\n */\n if (from === undefined && startingUrl !== undefined && startingUrl.indexOf(to) !== -1) {\n startingUrl = undefined;\n return;\n }\n\n startingUrl = undefined;\n const parsed = parseStringToURLObject(to);\n const activeSpan = getActiveIdleSpan(client);\n const navigationIsRedirect =\n activeSpan && detectRedirects && isRedirect(activeSpan, lastInteractionTimestamp);\n\n startBrowserTracingNavigationSpan(\n client,\n {\n // With span streaming, span names have to be low cardinality, and there is no route\n // information available here.\n name: hasSpanStreamingEnabled(client)\n ? NAVIGATION_SPAN_NAME_FALLBACK\n : parsed?.pathname || WINDOW.location.pathname,\n attributes: {\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SENTRY_ORIGIN]: 'auto.navigation.browser',\n },\n },\n { url: to, isRedirect: navigationIsRedirect },\n );\n });\n }\n\n // A bfcache restore resurrects the frozen document, so there is no document load and no\n // usable history event: `popstate` either doesn't fire or is swallowed because the URL is\n // unchanged from when the page was frozen. Without a span of its own, everything after the\n // restore joins the trace the page had before it was frozen, separated by however long it\n // sat in the cache.\n if (instrumentBfcacheRestore) {\n WINDOW.addEventListener?.('pageshow', (event: PageTransitionEvent) => {\n if (!event.persisted) {\n return;\n }\n\n // A navigation has happened, so the pageload guard in the history handler above must not\n // suppress the next one.\n startingUrl = undefined;\n\n startBrowserTracingNavigationSpan(\n client,\n {\n // Deliberately no `startTime`: the span starts now, at the restore. The\n // `PerformanceNavigationTiming` entry still describes the original document load and\n // would date the span to before the page was frozen.\n //\n // TODO(routing): resolve the parameterized route via the route provider (#23551) and set\n // the source from it. No router event fires on a restore, so in a framework app this is\n // the only navigation span still named from a raw pathname.\n name: hasSpanStreamingEnabled(client)\n ? NAVIGATION_SPAN_NAME_FALLBACK\n : WINDOW.location?.pathname || '/',\n attributes: {\n [SENTRY_SEGMENT_NAME_SOURCE]: 'url',\n [SENTRY_ORIGIN]: 'auto.navigation.browser.bfcache',\n // A bfcache restore is near-instant, so these spans would otherwise drag\n // navigation duration percentiles down with no way to tell them apart.\n [BROWSER_NAVIGATION_TYPE]: 'back-forward-cache',\n },\n },\n { url: WINDOW.location?.href },\n );\n });\n }\n }\n\n if (markBackgroundSpan) {\n registerBackgroundTabDetection();\n }\n\n instrumentOutgoingRequests(client, {\n traceFetch,\n traceXHR,\n tracePropagationTargets: client.getOptions().tracePropagationTargets,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n onRequestSpanStart,\n onRequestSpanEnd,\n });\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Manually start a page load span.\n * This will only do something if a browser tracing integration integration has been setup.\n *\n * If you provide a custom `traceOptions` object, it will be used to continue the trace\n * instead of the default behavior, which is to look it up on the <meta> tags.\n */\nexport function startBrowserTracingPageLoadSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n traceOptions?: { sentryTrace?: string | undefined; baggage?: string | undefined },\n): Span | undefined {\n // `Pageload` is a low-cardinality span name, not a description of the page. The scope's\n // transaction name is what error events are grouped by, so it keeps the URL instead.\n const isFallbackSpanName = spanOptions.name === PAGELOAD_SPAN_NAME_FALLBACK;\n getCurrentScope().setTransactionName(isFallbackSpanName ? WINDOW.location?.pathname : spanOptions.name);\n // A pageload span always covers the entire page load, no matter how late the SDK or a routing\n // instrumentation gets around to starting it. Everything that happened before (DNS, TLS, TTFB,\n // HTML parsing, chunk loading) is part of the page load and the performance child spans we attach\n // later are anchored at the time origin anyway.\n const timeOrigin = browserPerformanceTimeOrigin();\n const pageloadSpanOptions: StartSpanOptions = {\n ...spanOptions,\n // startTime needs to be in seconds, not ms\n startTime: spanOptions.startTime ?? (timeOrigin ? timeOrigin / 1000 : undefined),\n };\n\n client.emit('startPageLoadSpan', pageloadSpanOptions, traceOptions);\n\n const pageloadSpan = getActiveIdleSpan(client);\n\n if (pageloadSpan) {\n client.emit('afterStartPageLoadSpan', pageloadSpan);\n }\n\n return pageloadSpan;\n}\n\n/**\n * Manually start a navigation span.\n * This will only do something if a browser tracing integration has been setup.\n */\nexport function startBrowserTracingNavigationSpan(\n client: Client,\n spanOptions: StartSpanOptions,\n options?: { url?: string; isRedirect?: boolean },\n): Span | undefined {\n const { url, isRedirect } = options || {};\n client.emit('beforeStartNavigationSpan', spanOptions, { isRedirect, url });\n client.emit('startNavigationSpan', spanOptions, { isRedirect, url });\n\n const scope = getCurrentScope();\n // `Navigation` is a low-cardinality span name, not a description of the page. The scope's\n // transaction name is what error events are grouped by, so it keeps the URL instead. `url` is the\n // destination, while `location` still points at the previous page during a `pushState`.\n const isFallbackSpanName = spanOptions.name === NAVIGATION_SPAN_NAME_FALLBACK;\n scope.setTransactionName(\n isFallbackSpanName ? (url && parseStringToURLObject(url)?.pathname) || WINDOW.location?.pathname : spanOptions.name,\n );\n\n // We store the normalized request data on the scope, so we get the request data at time of span creation\n // otherwise, the URL etc. may already be of the following navigation, and we'd report the wrong URL\n if (url && !isRedirect) {\n scope.setSDKProcessingMetadata({\n normalizedRequest: {\n ...getHttpRequestData(),\n url,\n },\n });\n }\n\n return getActiveIdleSpan(client);\n}\n\n/** Returns the value of a meta tag */\nexport function getMetaContent(metaName: string): string | undefined {\n /**\n * This is just a small wrapper that makes `document` optional.\n * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.\n */\n const optionalWindowDocument = WINDOW.document as (typeof WINDOW)['document'] | undefined;\n\n const metaTag = optionalWindowDocument?.querySelector(`meta[name=${metaName}]`);\n return metaTag?.getAttribute('content') || undefined;\n}\n\n/** Returns the description of a server timing entry */\nexport function getServerTiming(name: string): string | undefined {\n // The cast is required for the declaration build (`build:types`), which resolves\n // `getEntriesByType('navigation')` to `PerformanceEntry[]` (no `serverTiming`). It only reads as\n // \"unnecessary\" to the type-aware linter, which runs with web-vitals' global augmentation applied.\n const navigation = WINDOW.performance?.getEntriesByType?.('navigation')[0] as PerformanceNavigationTiming | undefined;\n const entry = navigation?.serverTiming?.find(entry => entry.name === name);\n return entry?.description;\n}\n\n// We store the active idle span on the client object, so we can access it from exported functions\nconst ACTIVE_IDLE_SPAN_PROPERTY = '_sentry_idleSpan';\nfunction getActiveIdleSpan(client: Client): Span | undefined {\n return (client as { [ACTIVE_IDLE_SPAN_PROPERTY]?: Span })[ACTIVE_IDLE_SPAN_PROPERTY];\n}\n\nfunction setActiveIdleSpan(client: Client, span: Span | undefined): void {\n addNonEnumerableProperty(client, ACTIVE_IDLE_SPAN_PROPERTY, span);\n}\n\n// The max. time in seconds between two pageload/navigation spans that makes us consider the second one a redirect\nconst REDIRECT_THRESHOLD = 1.5;\n\nfunction isRedirect(activeSpan: Span, lastInteractionTimestamp: number | undefined): boolean {\n const spanData = spanToJSON(activeSpan);\n\n const now = dateTimestampInSeconds();\n\n // More than REDIRECT_THRESHOLD seconds since last navigation/pageload span?\n // --> never consider this a redirect\n const startTimestamp = spanData.start_timestamp;\n if (now - startTimestamp > REDIRECT_THRESHOLD) {\n return false;\n }\n\n // A click happened in the last REDIRECT_THRESHOLD seconds?\n // --> never consider this a redirect\n if (lastInteractionTimestamp && now - lastInteractionTimestamp <= REDIRECT_THRESHOLD) {\n return false;\n }\n\n return true;\n}\n"],"names":["TRACING_DEFAULTS","defaultRequestInstrumentationOptions","consoleSandbox","WINDOW","webVitals","isBotUserAgent","parseStringToURLObject","getLocationHref","attributes","URL_PATH","isURLObjectRelative","URL_FULL","filterCollectedUrl","SENTRY_SEGMENT_NAME_SOURCE","dateTimestampInSeconds","startInactiveSpan","startIdleSpan","DEBUG_BUILD","debug","registerSpanErrorInstrumentation","GLOBAL_OBJ","startTrackingLongAnimationFrames","startTrackingLongTasks","timestampInSeconds","spanToJSON","SENTRY_OP","SENTRY_IDLE_SPAN_FINISH_REASON","addPerformanceEntries","hasSpanStreamingEnabled","getCurrentScope","spanIsSampled","getDynamicSamplingContextFromSpan","getClient","NAVIGATION_REDIRECT","generateTraceId","hasSpansEnabled","generateSpanId","NAVIGATION","propagationContextFromHeaders","getHttpRequestData","PAGELOAD","_INTERNAL_ensureBrowserSpanStreaming","WEB_VITALS_INTEGRATION_NAME","webVitalsIntegration","linkTraces","PAGELOAD_SPAN_NAME_FALLBACK","SENTRY_ORIGIN","addHistoryInstrumentationHandler","NAVIGATION_SPAN_NAME_FALLBACK","BROWSER_NAVIGATION_TYPE","registerBackgroundTabDetection","instrumentOutgoingRequests","browserPerformanceTimeOrigin","isRedirect","entry","addNonEnumerableProperty"],"mappings":";;;;;;;;;;;;;;AAuDO,MAAM,8BAAA,GAAiC;AA6N9C,MAAM,+BAAA,GAAyD;AAAA,EAC7D,GAAGA,qBAAA;AAAA,EACH,oBAAA,EAAsB,IAAA;AAAA,EACtB,wBAAA,EAA0B,IAAA;AAAA,EAC1B,kBAAA,EAAoB,IAAA;AAAA,EACpB,kBAAA,EAAoB,IAAA;AAAA,EACpB,cAAA,EAAgB,IAAA;AAAA,EAChB,wBAAA,EAA0B,IAAA;AAAA;AAAA,EAE1B,SAAA,EAAW,IAAA;AAAA,EACX,qBAAqB,EAAC;AAAA,EACtB,eAAA,EAAiB,IAAA;AAAA,EACjB,iBAAA,EAAmB,WAAA;AAAA,EACnB,uBAAA,EAAyB,KAAA;AAAA,EACzB,sBAAA,EAAwB,KAAA;AAAA,EACxB,GAAGC;AACL,CAAA;AAWO,MAAM,yBAAA,IAA6B,CAAC,OAAA,GAA0C,EAAC,KAAM;AAC1F,EAAA,IAAI,yBAAyB,OAAA,EAAS;AACpC,IAAAC,mBAAA,CAAe,MAAM;AAEnB,MAAA,OAAA,CAAQ,IAAA;AAAA,QACN;AAAA,OACF;AAAA,IACF,CAAC,CAAA;AAAA,EACH;AAMA,EAAA,MAAM,yBAAyBC,cAAA,CAAO,QAAA;AAEtC,EAAA,MAAM;AAAA;AAAA,IAEJ,SAAA;AAAA,IACA,cAAA;AAAA,IACA,wBAAA;AAAA,eACAC,WAAA;AAAA,IACA,eAAA;AAAA,IACA,WAAA;AAAA,IACA,YAAA;AAAA,IACA,gBAAA;AAAA,IACA,kBAAA;AAAA,IACA,UAAA;AAAA,IACA,QAAA;AAAA,IACA,0BAAA;AAAA,IACA,iBAAA;AAAA,IACA,mBAAA;AAAA,IACA,kBAAA;AAAA,IACA,oBAAA;AAAA,IACA,wBAAA;AAAA,IACA,eAAA;AAAA,IACA,iBAAA;AAAA,IACA,uBAAA;AAAA,IACA,sBAAA;AAAA,IACA,kBAAA;AAAA,IACA;AAAA,GACF,GAAI;AAAA,IACF,GAAG,+BAAA;AAAA,IACH,GAAG;AAAA,GACL;AAEA,EAAA,MAAM,SAASC,2BAAA,EAAe;AAE9B,EAAA,IAAI,wBAAA;AAEJ,EAAA,IAAI,aAAA;AAGJ,EAAA,SAAS,gBAAA,CAAiB,MAAA,EAAgB,gBAAA,EAAoC,UAAA,GAAa,MAAM,GAAA,EAAoB;AACnH,IAAA,MAAM,cAAA,GAAiB,iBAAiB,EAAA,KAAO,UAAA;AAE/C,IAAA,MAAM,kBAAkB,gBAAA,CAAiB,IAAA;AACzC,IAAA,MAAM,qBAAA,GAA0C,eAAA,GAC5C,eAAA,CAAgB,gBAAgB,CAAA,GAChC,gBAAA;AAIJ,IAAA,MAAM,SAAA,GAAYC,2BAAA,CAAuB,GAAA,IAAOC,4BAAA,EAAiB,CAAA;AAEjE,IAAA,MAAMC,YAAA,GAAa;AAAA,MACjB,GAAI,WAAW,QAAA,IAAY,EAAE,CAACC,mBAAQ,GAAG,UAAU,QAAA,EAAS;AAAA,MAC5D,GAAI,SAAA,IAAa,CAACC,wBAAA,CAAoB,SAAS,CAAA,IAAK,EAAE,CAACC,mBAAQ,GAAGC,uBAAA,CAAmB,SAAA,CAAU,IAAI,CAAA,EAAE;AAAA,MACrG,GAAG,qBAAA,CAAsB;AAAA,KAC3B;AAIA,IAAA,IAAI,eAAA,KAAoB,sBAAsB,IAAA,EAAM;AAClD,MAAAJ,YAAA,CAAWK,qCAA0B,CAAA,GAAI,QAAA;AAAA,IAC3C;AAEA,IAAA,qBAAA,CAAsB,UAAA,GAAaL,YAAA;AAEnC,IAAA,IAAI,CAAC,UAAA,EAAY;AAEf,MAAA,MAAM,MAAMM,2BAAA,EAAuB;AACnC,MAAAC,yBAAA,CAAkB;AAAA,QAChB,GAAG,qBAAA;AAAA,QACH,SAAA,EAAW;AAAA,OACZ,CAAA,CAAE,GAAA,CAAI,GAAG,CAAA;AACV,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,QAAA,GAAWC,sBAAc,qBAAA,EAAuB;AAAA,MACpD,WAAA;AAAA,MACA,YAAA;AAAA,MACA,gBAAA;AAAA;AAAA,MAEA,iBAAA,EAAmB,cAAA;AAAA,MACnB,0BAA0B,CAAC;AAAA,KAC5B,CAAA;AAED,IAAA,IAAI,kBAAkB,sBAAA,EAAwB;AAC5C,MAAA,aAAA,GAAgB,QAAA;AAAA,IAClB;AAEA,IAAA,iBAAA,CAAkB,QAAQ,QAAQ,CAAA;AAElC,IAAA,SAAS,UAAA,GAAmB;AAC1B,MAAA,IAAI,sBAAA,IAA0B,CAAC,aAAA,EAAe,UAAU,EAAE,QAAA,CAAS,sBAAA,CAAuB,UAAU,CAAA,EAAG;AACrG,QAAA,MAAA,CAAO,IAAA,CAAK,4BAA4B,QAAQ,CAAA;AAIhD,QAAA,sBAAA,CAAuB,mBAAA,CAAoB,oBAAoB,UAAU,CAAA;AAAA,MAC3E;AAAA,IACF;AAGA,IAAA,IAAI,cAAA,IAAkB,CAAC,sBAAA,IAA0B,sBAAA,EAAwB;AACvE,MAAA,sBAAA,CAAuB,gBAAA,CAAiB,oBAAoB,UAAU,CAAA;AAEtE,MAAA,UAAA,EAAW;AAAA,IACb;AAAA,EACF;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,8BAAA;AAAA,IACN,MAAM,MAAA,EAAQ;AACZ,MAAA,IAAI,MAAA,EAAQ;AACV,QAAAC,sBAAA,IAAeC,UAAA,CAAM,IAAI,wEAAwE,CAAA;AACjG,QAAA;AAAA,MACF;AAEA,MAAAC,qCAAA,EAAiC;AAEjC,MAAA,IACE,4BACAC,eAAA,CAAW,mBAAA,IACX,oBAAoB,mBAAA,EAAqB,QAAA,CAAS,sBAAsB,CAAA,EACxE;AACA,QAAAC,6CAAA,EAAiC;AAAA,MACnC,WAAW,cAAA,EAAgB;AACzB,QAAAC,mCAAA,EAAuB;AAAA,MACzB;AAEA,MAAA,IAAI,mBAAmB,sBAAA,EAAwB;AAC7C,QAAA,MAAM,qBAAqB,MAAY;AACrC,UAAA,wBAAA,GAA2BC,uBAAA,EAAmB;AAAA,QAChD,CAAA;AACA,QAAA,gBAAA,CAAiB,OAAA,EAAS,kBAAA,EAAoB,EAAE,OAAA,EAAS,MAAM,CAAA;AAC/D,QAAA,gBAAA,CAAiB,WAAW,kBAAA,EAAoB,EAAE,SAAS,IAAA,EAAM,OAAA,EAAS,MAAM,CAAA;AAAA,MAClF;AAEA,MAAA,SAAS,kBAAA,GAA2B;AAClC,QAAA,MAAM,UAAA,GAAa,kBAAkB,MAAM,CAAA;AAE3C,QAAA,IAAI,UAAA,IAAc,CAACC,eAAA,CAAW,UAAU,EAAE,aAAA,EAAe;AACvD,UAAAP,sBAAA,IACEC,UAAA,CAAM,GAAA;AAAA,YACJ,oDAAoDM,eAAA,CAAW,UAAU,CAAA,CAAE,UAAA,CAAWC,oBAAS,CAAC,CAAA;AAAA,WAClG;AAEF,UAAA,UAAA,CAAW,YAAA,CAAaC,2CAAgC,WAAW,CAAA;AACnE,UAAA,UAAA,CAAW,GAAA,EAAI;AAAA,QACjB;AAAA,MACF;AAEA,MAAA,MAAA,CAAO,EAAA,CAAG,qBAAqB,CAAA,IAAA,KAAQ;AAIrC,QAAA,IAAI,iBAAA,CAAkB,MAAM,CAAA,KAAM,IAAA,EAAM;AACtC,UAAA;AAAA,QACF;AAEA,QAAAC,kCAAA,CAAsB,IAAA,EAAM;AAAA,UAC1B,mBAAA;AAAA,UACA,oBAAA,EAAsBC,6BAAwB,MAAM;AAAA,SACrD,CAAA;AACD,QAAA,iBAAA,CAAkB,QAAQ,MAAS,CAAA;AAKnC,QAAA,MAAM,QAAQC,oBAAA,EAAgB;AAC9B,QAAA,MAAM,qBAAA,GAAwB,MAAM,qBAAA,EAAsB;AAE1D,QAAA,KAAA,CAAM,qBAAA,CAAsB;AAAA,UAC1B,GAAG,qBAAA;AAAA,UACH,OAAA,EAAS,IAAA,CAAK,WAAA,EAAY,CAAE,OAAA;AAAA,UAC5B,OAAA,EAASC,mBAAc,IAAI,CAAA;AAAA,UAC3B,GAAA,EAAKC,uCAAkC,IAAI;AAAA,SAC5C,CAAA;AAED,QAAA,IAAI,kBAAkB,IAAA,EAAM;AAE1B,UAAA,aAAA,GAAgB,MAAA;AAAA,QAClB;AAAA,MACF,CAAC,CAAA;AAED,MAAA,MAAA,CAAO,EAAA,CAAG,qBAAA,EAAuB,CAAC,gBAAA,EAAkB,iBAAA,KAAsB;AACxE,QAAA,IAAIC,cAAA,OAAgB,MAAA,EAAQ;AAC1B,UAAA;AAAA,QACF;AAEA,QAAA,IAAI,mBAAmB,UAAA,EAAY;AACjC,UAAAf,sBAAA,IACEC,UAAA,CAAM,KAAK,2FAA2F,CAAA;AACxG,UAAA,gBAAA;AAAA,YACE,MAAA;AAAA,YACA;AAAA,cACE,EAAA,EAAIe,sBAAA;AAAA,cACJ,GAAG;AAAA,aACL;AAAA,YACA,KAAA;AAAA,YACA,iBAAA,CAAkB;AAAA,WACpB;AACA,UAAA;AAAA,QACF;AAKA,QAAA,wBAAA,GAA2B,MAAA;AAE3B,QAAA,kBAAA,EAAmB;AAEnB,QAAA,MAAM,QAAQJ,oBAAA,EAAgB;AAC9B,QAAA,KAAA,CAAM,qBAAA,CAAsB;AAAA,UAC1B,SAASK,oBAAA,EAAgB;AAAA,UACzB,UAAA,EAAY,KAAK,MAAA,EAAO;AAAA,UACxB,iBAAA,EAAmBC,oBAAA,EAAgB,GAAI,MAAA,GAAYC,mBAAA;AAAe,SACnE,CAAA;AAID,QAAA,KAAA,CAAM,wBAAA,CAAyB;AAAA,UAC7B,iBAAA,EAAmB;AAAA,SACpB,CAAA;AAED,QAAA,gBAAA;AAAA,UACE,MAAA;AAAA,UACA;AAAA,YACE,EAAA,EAAIC,aAAA;AAAA,YACJ,GAAG,gBAAA;AAAA;AAAA,YAEH,UAAA,EAAY;AAAA,WACd;AAAA,UACA,IAAA;AAAA,UACA,iBAAA,EAAmB;AAAA,SACrB;AAAA,MACF,CAAC,CAAA;AAED,MAAA,MAAA,CAAO,GAAG,mBAAA,EAAqB,CAAC,gBAAA,EAAkB,YAAA,GAAe,EAAC,KAAM;AACtE,QAAA,IAAIL,cAAA,OAAgB,MAAA,EAAQ;AAC1B,UAAA;AAAA,QACF;AACA,QAAA,kBAAA,EAAmB;AAEnB,QAAA,MAAM,cACJ,YAAA,CAAa,WAAA,IAAe,eAAe,cAAc,CAAA,IAAK,gBAAgB,cAAc,CAAA;AAC9F,QAAA,MAAM,UAAU,YAAA,CAAa,OAAA,IAAW,eAAe,SAAS,CAAA,IAAK,gBAAgB,SAAS,CAAA;AAE9F,QAAA,MAAM,kBAAA,GAAqBM,kCAAA,CAA8B,WAAA,EAAa,OAAO,CAAA;AAE7E,QAAA,MAAM,QAAQT,oBAAA,EAAgB;AAC9B,QAAA,KAAA,CAAM,sBAAsB,kBAAkB,CAAA;AAC9C,QAAA,IAAI,CAACM,sBAAgB,EAAG;AAItB,UAAA,KAAA,CAAM,qBAAA,EAAsB,CAAE,iBAAA,GAAoBC,mBAAA,EAAe;AAAA,QACnE;AAIA,QAAA,KAAA,CAAM,wBAAA,CAAyB;AAAA,UAC7B,mBAAmBG,0BAAA;AAAmB,SACvC,CAAA;AAED,QAAA,gBAAA,CAAiB,MAAA,EAAQ;AAAA,UACvB,EAAA,EAAIC,WAAA;AAAA,UACJ,GAAG;AAAA,SACJ,CAAA;AAAA,MACH,CAAC,CAAA;AAED,MAAA,MAAA,CAAO,EAAA,CAAG,mBAAmB,MAAM;AACjC,QAAA,IAAI,0BAA0B,aAAA,EAAe;AAC3C,UAAA,aAAA,CAAc,YAAA,CAAad,2CAAgC,kBAAkB,CAAA;AAC7E,UAAA,aAAA,CAAc,GAAA,EAAI;AAAA,QACpB;AAAA,MACF,CAAC,CAAA;AASD,MAAAvB,cAAA,CAAO,gBAAA,GAAmB,YAAY,MAAM;AAC1C,QAAA,MAAM,UAAA,GAAa,kBAAkB,MAAM,CAAA;AAC3C,QAAA,IAAI,UAAA,IAAc,CAACqB,eAAA,CAAW,UAAU,EAAE,aAAA,EAAe;AACvD,UAAA,UAAA,CAAW,YAAA,CAAaE,2CAAgC,gBAAgB,CAAA;AACxE,UAAA,UAAA,CAAW,GAAA,EAAI;AAAA,QACjB;AACA,QAAA,KAAK,OAAO,KAAA,EAAM;AAAA,MACpB,CAAC,CAAA;AAAA,IACH,CAAA;AAAA,IAEA,cAAc,MAAA,EAAQ;AACpB,MAAA,IAAI,MAAA,EAAQ;AACV,QAAA;AAAA,MACF;AAKA,MAAAe,4CAAA,CAAqC,MAAM,CAAA;AAK3C,MAAA,IAAI,OAAO,cAAA,IAAkB,CAAC,MAAA,CAAO,oBAAA,GAAuBC,qCAA2B,CAAA,EAAG;AACxF,QAAA,MAAM,MAAA,GAAStC,WAAA,EAAW,MAAA,IAAU,EAAC;AACrC,QAAA,MAAA,CAAO,cAAA;AAAA,UACLuC,8BAAA,CAAqB;AAAA,YACnB,GAAGvC,WAAA;AAAA,YACH,MAAA,EAAQ,SAAA,IAAa,MAAA,CAAO,QAAA,CAAS,KAAK,IAAI,MAAA,GAAS,CAAC,GAAG,MAAA,EAAQ,KAAK;AAAA,WACzE;AAAA,SACH;AAAA,MACF;AAEA,MAAA,IAAI,cAAkCG,4BAAA,EAAgB;AAEtD,MAAA,IAAI,sBAAsB,KAAA,EAAO;AAC/B,QAAAqC,uBAAA,CAAW,MAAA,EAAQ,EAAE,iBAAA,EAAmB,uBAAA,EAAyB,CAAA;AAAA,MACnE;AAEA,MAAA,IAAIzC,eAAO,QAAA,EAAU;AACnB,QAAA,IAAI,kBAAA,EAAoB;AACtB,UAAA,+BAAA,CAAgC,MAAA,EAAQ;AAAA;AAAA;AAAA,YAGtC,MAAMyB,4BAAA,CAAwB,MAAM,CAAA,GAAIiB,gCAAA,GAA8B1C,eAAO,QAAA,CAAS,QAAA;AAAA,YACtF,UAAA,EAAY;AAAA,cACV,CAACU,qCAA0B,GAAG,KAAA;AAAA,cAC9B,CAACiC,wBAAa,GAAG;AAAA;AACnB,WACD,CAAA;AAAA,QACH;AAEA,QAAA,IAAI,oBAAA,EAAsB;AACxB,UAAAC,6CAAA,CAAiC,CAAC,EAAE,EAAA,EAAI,IAAA,EAAK,KAAM;AAUjD,YAAA,IAAI,IAAA,KAAS,UAAa,WAAA,KAAgB,MAAA,IAAa,YAAY,OAAA,CAAQ,EAAE,MAAM,EAAA,EAAI;AACrF,cAAA,WAAA,GAAc,MAAA;AACd,cAAA;AAAA,YACF;AAEA,YAAA,WAAA,GAAc,MAAA;AACd,YAAA,MAAM,MAAA,GAASzC,4BAAuB,EAAE,CAAA;AACxC,YAAA,MAAM,UAAA,GAAa,kBAAkB,MAAM,CAAA;AAC3C,YAAA,MAAM,oBAAA,GACJ,UAAA,IAAc,eAAA,IAAmB,UAAA,CAAW,YAAY,wBAAwB,CAAA;AAElF,YAAA,iCAAA;AAAA,cACE,MAAA;AAAA,cACA;AAAA;AAAA;AAAA,gBAGE,IAAA,EAAMsB,6BAAwB,MAAM,CAAA,GAChCoB,qCACA,MAAA,EAAQ,QAAA,IAAY7C,eAAO,QAAA,CAAS,QAAA;AAAA,gBACxC,UAAA,EAAY;AAAA,kBACV,CAACU,qCAA0B,GAAG,KAAA;AAAA,kBAC9B,CAACiC,wBAAa,GAAG;AAAA;AACnB,eACF;AAAA,cACA,EAAE,GAAA,EAAK,EAAA,EAAI,UAAA,EAAY,oBAAA;AAAqB,aAC9C;AAAA,UACF,CAAC,CAAA;AAAA,QACH;AAOA,QAAA,IAAI,wBAAA,EAA0B;AAC5B,UAAA3C,cAAA,CAAO,gBAAA,GAAmB,UAAA,EAAY,CAAC,KAAA,KAA+B;AACpE,YAAA,IAAI,CAAC,MAAM,SAAA,EAAW;AACpB,cAAA;AAAA,YACF;AAIA,YAAA,WAAA,GAAc,MAAA;AAEd,YAAA,iCAAA;AAAA,cACE,MAAA;AAAA,cACA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBAQE,MAAMyB,4BAAA,CAAwB,MAAM,IAChCoB,kCAAA,GACA7C,cAAA,CAAO,UAAU,QAAA,IAAY,GAAA;AAAA,gBACjC,UAAA,EAAY;AAAA,kBACV,CAACU,qCAA0B,GAAG,KAAA;AAAA,kBAC9B,CAACiC,wBAAa,GAAG,iCAAA;AAAA;AAAA;AAAA,kBAGjB,CAACG,kCAAuB,GAAG;AAAA;AAC7B,eACF;AAAA,cACA,EAAE,GAAA,EAAK9C,cAAA,CAAO,QAAA,EAAU,IAAA;AAAK,aAC/B;AAAA,UACF,CAAC,CAAA;AAAA,QACH;AAAA,MACF;AAEA,MAAA,IAAI,kBAAA,EAAoB;AACtB,QAAA+C,4CAAA,EAA+B;AAAA,MACjC;AAEA,MAAAC,kCAAA,CAA2B,MAAA,EAAQ;AAAA,QACjC,UAAA;AAAA,QACA,QAAA;AAAA,QACA,uBAAA,EAAyB,MAAA,CAAO,UAAA,EAAW,CAAE,uBAAA;AAAA,QAC7C,0BAAA;AAAA,QACA,iBAAA;AAAA,QACA,kBAAA;AAAA,QACA;AAAA,OACD,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAA;AASO,SAAS,+BAAA,CACd,MAAA,EACA,WAAA,EACA,YAAA,EACkB;AAGlB,EAAA,MAAM,kBAAA,GAAqB,YAAY,IAAA,KAASN,gCAAA;AAChD,EAAAhB,oBAAA,GAAkB,kBAAA,CAAmB,kBAAA,GAAqB1B,eAAO,QAAA,EAAU,QAAA,GAAW,YAAY,IAAI,CAAA;AAKtG,EAAA,MAAM,aAAaiD,iCAAA,EAA6B;AAChD,EAAA,MAAM,mBAAA,GAAwC;AAAA,IAC5C,GAAG,WAAA;AAAA;AAAA,IAEH,SAAA,EAAW,WAAA,CAAY,SAAA,KAAc,UAAA,GAAa,aAAa,GAAA,GAAO,MAAA;AAAA,GACxE;AAEA,EAAA,MAAA,CAAO,IAAA,CAAK,mBAAA,EAAqB,mBAAA,EAAqB,YAAY,CAAA;AAElE,EAAA,MAAM,YAAA,GAAe,kBAAkB,MAAM,CAAA;AAE7C,EAAA,IAAI,YAAA,EAAc;AAChB,IAAA,MAAA,CAAO,IAAA,CAAK,0BAA0B,YAAY,CAAA;AAAA,EACpD;AAEA,EAAA,OAAO,YAAA;AACT;AAMO,SAAS,iCAAA,CACd,MAAA,EACA,WAAA,EACA,OAAA,EACkB;AAClB,EAAA,MAAM,EAAE,GAAA,EAAK,UAAA,EAAAC,WAAAA,EAAW,GAAI,WAAW,EAAC;AACxC,EAAA,MAAA,CAAO,KAAK,2BAAA,EAA6B,WAAA,EAAa,EAAE,UAAA,EAAAA,WAAAA,EAAY,KAAK,CAAA;AACzE,EAAA,MAAA,CAAO,KAAK,qBAAA,EAAuB,WAAA,EAAa,EAAE,UAAA,EAAAA,WAAAA,EAAY,KAAK,CAAA;AAEnE,EAAA,MAAM,QAAQxB,oBAAA,EAAgB;AAI9B,EAAA,MAAM,kBAAA,GAAqB,YAAY,IAAA,KAASmB,kCAAA;AAChD,EAAA,KAAA,CAAM,kBAAA;AAAA,IACJ,kBAAA,GAAsB,OAAO1C,2BAAA,CAAuB,GAAG,GAAG,QAAA,IAAaH,cAAA,CAAO,QAAA,EAAU,QAAA,GAAW,WAAA,CAAY;AAAA,GACjH;AAIA,EAAA,IAAI,GAAA,IAAO,CAACkD,WAAAA,EAAY;AACtB,IAAA,KAAA,CAAM,wBAAA,CAAyB;AAAA,MAC7B,iBAAA,EAAmB;AAAA,QACjB,GAAGd,0BAAA,EAAmB;AAAA,QACtB;AAAA;AACF,KACD,CAAA;AAAA,EACH;AAEA,EAAA,OAAO,kBAAkB,MAAM,CAAA;AACjC;AAGO,SAAS,eAAe,QAAA,EAAsC;AAKnE,EAAA,MAAM,yBAAyBpC,cAAA,CAAO,QAAA;AAEtC,EAAA,MAAM,OAAA,GAAU,sBAAA,EAAwB,aAAA,CAAc,CAAA,UAAA,EAAa,QAAQ,CAAA,CAAA,CAAG,CAAA;AAC9E,EAAA,OAAO,OAAA,EAAS,YAAA,CAAa,SAAS,CAAA,IAAK,MAAA;AAC7C;AAGO,SAAS,gBAAgB,IAAA,EAAkC;AAIhE,EAAA,MAAM,aAAaA,cAAA,CAAO,WAAA,EAAa,gBAAA,GAAmB,YAAY,EAAE,CAAC,CAAA;AACzE,EAAA,MAAM,KAAA,GAAQ,YAAY,YAAA,EAAc,IAAA,CAAK,CAAAmD,MAAAA,KAASA,MAAAA,CAAM,SAAS,IAAI,CAAA;AACzE,EAAA,OAAO,KAAA,EAAO,WAAA;AAChB;AAGA,MAAM,yBAAA,GAA4B,kBAAA;AAClC,SAAS,kBAAkB,MAAA,EAAkC;AAC3D,EAAA,OAAQ,OAAkD,yBAAyB,CAAA;AACrF;AAEA,SAAS,iBAAA,CAAkB,QAAgB,IAAA,EAA8B;AACvE,EAAAC,6BAAA,CAAyB,MAAA,EAAQ,2BAA2B,IAAI,CAAA;AAClE;AAGA,MAAM,kBAAA,GAAqB,GAAA;AAE3B,SAAS,UAAA,CAAW,YAAkB,wBAAA,EAAuD;AAC3F,EAAA,MAAM,QAAA,GAAW/B,gBAAW,UAAU,CAAA;AAEtC,EAAA,MAAM,MAAMV,2BAAA,EAAuB;AAInC,EAAA,MAAM,iBAAiB,QAAA,CAAS,eAAA;AAChC,EAAA,IAAI,GAAA,GAAM,iBAAiB,kBAAA,EAAoB;AAC7C,IAAA,OAAO,KAAA;AAAA,EACT;AAIA,EAAA,IAAI,wBAAA,IAA4B,GAAA,GAAM,wBAAA,IAA4B,kBAAA,EAAoB;AACpF,IAAA,OAAO,KAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAA;AACT;;;;;;;;;"}
|
|
@@ -3,8 +3,29 @@ import { getLocationHref } from '@sentry/browser-utils';
|
|
|
3
3
|
|
|
4
4
|
const WINDOW = GLOBAL_OBJ;
|
|
5
5
|
let ignoreOnError = 0;
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const ignoredErrorReports = [];
|
|
7
|
+
function shouldIgnoreOnError(data) {
|
|
8
|
+
if (ignoreOnError > 0) {
|
|
9
|
+
return true;
|
|
10
|
+
}
|
|
11
|
+
const index = data ? ignoredErrorReports.findIndex((report) => isSameErrorReport(report, data)) : -1;
|
|
12
|
+
if (index === -1) {
|
|
13
|
+
return false;
|
|
14
|
+
}
|
|
15
|
+
ignoredErrorReports.splice(index, 1);
|
|
16
|
+
return true;
|
|
17
|
+
}
|
|
18
|
+
function ignoreNextOnErrorMatching(report) {
|
|
19
|
+
ignoredErrorReports.push(report);
|
|
20
|
+
setTimeout(() => {
|
|
21
|
+
const index = ignoredErrorReports.indexOf(report);
|
|
22
|
+
if (index !== -1) {
|
|
23
|
+
ignoredErrorReports.splice(index, 1);
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function isSameErrorReport(a, b) {
|
|
28
|
+
return a.msg === b.msg && a.url === b.url && a.line === b.line && a.column === b.column;
|
|
8
29
|
}
|
|
9
30
|
function ignoreNextOnError() {
|
|
10
31
|
ignoreOnError++;
|
|
@@ -99,5 +120,5 @@ function getHttpRequestData() {
|
|
|
99
120
|
return request;
|
|
100
121
|
}
|
|
101
122
|
|
|
102
|
-
export { WINDOW, getHttpRequestData, ignoreNextOnError, shouldIgnoreOnError, wrap };
|
|
123
|
+
export { WINDOW, getHttpRequestData, ignoreNextOnError, ignoreNextOnErrorMatching, shouldIgnoreOnError, wrap };
|
|
103
124
|
//# sourceMappingURL=helpers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"helpers.js","sources":["../../../../src/helpers.ts"],"sourcesContent":["import type { Mechanism, WrappedFunction } from '@sentry/core';\nimport {\n addExceptionMechanism,\n addExceptionTypeValue,\n addNonEnumerableProperty,\n captureException,\n getOriginalFunction,\n GLOBAL_OBJ,\n markFunctionWrapped,\n withScope,\n} from '@sentry/core';\nimport { getLocationHref } from '@sentry/browser-utils';\n\nexport const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nlet ignoreOnError: number = 0;\n\n/**\n * @hidden\n */\nexport function shouldIgnoreOnError(): boolean {\n return ignoreOnError > 0;\n}\n\n/**\n * @hidden\n */\nexport function ignoreNextOnError(): void {\n // onerror should trigger before setTimeout\n ignoreOnError++;\n setTimeout(() => {\n ignoreOnError--;\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype WrappableFunction = Function;\n\nexport function wrap<T extends WrappableFunction>(\n fn: T,\n options?: {\n mechanism?: Mechanism;\n },\n): WrappedFunction<T>;\nexport function wrap<NonFunction>(\n fn: NonFunction,\n options?: {\n mechanism?: Mechanism;\n },\n): NonFunction;\n/**\n * Instruments the given function and sends an event to Sentry every time the\n * function throws an exception.\n *\n * @param fn A function to wrap. It is generally safe to pass an unbound function, because the returned wrapper always\n * has a correct `this` context.\n * @returns The wrapped function.\n * @hidden\n */\nexport function wrap<T extends WrappableFunction, NonFunction>(\n fn: T | NonFunction,\n options: {\n mechanism?: Mechanism;\n } = {},\n): NonFunction | WrappedFunction<T> {\n // for future readers what this does is wrap a function and then create\n // a bi-directional wrapping between them.\n //\n // example: wrapped = wrap(original);\n // original.__sentry_wrapped__ -> wrapped\n // wrapped.__sentry_original__ -> original\n\n function isFunction(fn: T | NonFunction): fn is T {\n return typeof fn === 'function';\n }\n\n if (!isFunction(fn)) {\n return fn;\n }\n\n try {\n // If we're dealing with a function that was previously wrapped, return the original wrapper.\n // Check via hasOwnProperty so a `__sentry_wrapped__` inherited from a wrapped `Function.prototype`\n // is not mistaken for a real wrapper.\n const hasOwnWrapper = Object.prototype.hasOwnProperty.call(fn, '__sentry_wrapped__');\n if (hasOwnWrapper) {\n const wrapper = (fn as WrappedFunction<T>).__sentry_wrapped__;\n if (typeof wrapper === 'function') {\n return wrapper;\n } else {\n // If we find that the `__sentry_wrapped__` function is not a function at the time of accessing it, it means\n // that something messed with it. In that case we want to return the originally passed function.\n return fn;\n }\n }\n\n // We don't wanna wrap it twice\n if (getOriginalFunction(fn)) {\n return fn;\n }\n } catch {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return fn;\n }\n\n // Wrap the function itself\n // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`\n const sentryWrapped = function (this: unknown, ...args: unknown[]): unknown {\n // Track depth on GLOBAL_OBJ so the thirdPartyErrorFilterIntegration (in @sentry/core) can detect\n // that processEvent is running inside a sentryWrapped call, even with minified/bundled code.\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) + 1;\n try {\n // Also wrap arguments that are themselves functions\n const wrappedArguments = args.map(arg => wrap(arg, options));\n\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means the sentry.javascript SDK caught an error invoking your application code. This\n // is expected behavior and NOT indicative of a bug with sentry.javascript.\n return fn.apply(this, wrappedArguments);\n } catch (ex) {\n ignoreNextOnError();\n\n withScope(scope => {\n scope.addEventProcessor(event => {\n if (options.mechanism) {\n addExceptionTypeValue(event, undefined, undefined);\n addExceptionMechanism(event, options.mechanism);\n }\n\n event.extra = {\n ...event.extra,\n arguments: args,\n };\n\n return event;\n });\n\n // no need to add a mechanism here, we already add it via an event processor above\n captureException(ex);\n });\n\n throw ex;\n } finally {\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) - 1;\n }\n } as unknown as WrappedFunction<T>;\n\n // Wrap the wrapped function in a proxy, to ensure any other properties of the original function remain available\n try {\n for (const property in fn) {\n if (Object.prototype.hasOwnProperty.call(fn, property)) {\n sentryWrapped[property as keyof T] = fn[property as keyof T];\n }\n }\n } catch {\n // Accessing some objects may throw\n // ref: https://github.com/getsentry/sentry-javascript/issues/1168\n }\n\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n markFunctionWrapped(sentryWrapped, fn);\n\n addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);\n\n // Restore original function name (not all browsers allow that)\n try {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name')!;\n if (descriptor.configurable) {\n Object.defineProperty(sentryWrapped, 'name', {\n get(): string {\n return fn.name;\n },\n });\n }\n } catch {\n // This may throw if e.g. the descriptor does not exist, or a browser does not allow redefining `name`.\n // to save some bytes we simply try-catch this\n }\n\n return sentryWrapped;\n}\n\n/**\n * Get HTTP request data from the current page.\n */\nexport function getHttpRequestData(): { url: string; headers: Record<string, string> } {\n // grab as much info as exists and add it to the event\n const url = getLocationHref();\n const { referrer } = WINDOW.document || {};\n const { userAgent } = WINDOW.navigator || {};\n\n const headers = {\n ...(referrer && { Referer: referrer }),\n ...(userAgent && { 'User-Agent': userAgent }),\n };\n const request = {\n url,\n headers,\n };\n\n return request;\n}\n"],"names":["fn"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"helpers.js","sources":["../../../../src/helpers.ts"],"sourcesContent":["import type { HandlerDataError, Mechanism, WrappedFunction } from '@sentry/core';\nimport {\n addExceptionMechanism,\n addExceptionTypeValue,\n addNonEnumerableProperty,\n captureException,\n getOriginalFunction,\n GLOBAL_OBJ,\n markFunctionWrapped,\n withScope,\n} from '@sentry/core';\nimport { getLocationHref } from '@sentry/browser-utils';\n\nexport const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window;\n\nlet ignoreOnError: number = 0;\n\ntype ErrorReport = Pick<HandlerDataError, 'msg' | 'url' | 'line' | 'column'>;\n\nconst ignoredErrorReports: ErrorReport[] = [];\n\n/**\n * @hidden\n */\nexport function shouldIgnoreOnError(data?: HandlerDataError): boolean {\n if (ignoreOnError > 0) {\n return true;\n }\n\n const index = data ? ignoredErrorReports.findIndex(report => isSameErrorReport(report, data)) : -1;\n if (index === -1) {\n return false;\n }\n\n ignoredErrorReports.splice(index, 1);\n return true;\n}\n\n/**\n * Skips the next `onerror` report that matches `report`, once. A report that\n * never arrives is forgotten after the current task.\n *\n * @hidden\n */\nexport function ignoreNextOnErrorMatching(report: ErrorReport): void {\n ignoredErrorReports.push(report);\n setTimeout(() => {\n const index = ignoredErrorReports.indexOf(report);\n if (index !== -1) {\n ignoredErrorReports.splice(index, 1);\n }\n });\n}\n\nfunction isSameErrorReport(a: ErrorReport, b: ErrorReport): boolean {\n return a.msg === b.msg && a.url === b.url && a.line === b.line && a.column === b.column;\n}\n\n/**\n * @hidden\n */\nexport function ignoreNextOnError(): void {\n // onerror should trigger before setTimeout\n ignoreOnError++;\n setTimeout(() => {\n ignoreOnError--;\n });\n}\n\n// eslint-disable-next-line @typescript-eslint/ban-types\ntype WrappableFunction = Function;\n\nexport function wrap<T extends WrappableFunction>(\n fn: T,\n options?: {\n mechanism?: Mechanism;\n },\n): WrappedFunction<T>;\nexport function wrap<NonFunction>(\n fn: NonFunction,\n options?: {\n mechanism?: Mechanism;\n },\n): NonFunction;\n/**\n * Instruments the given function and sends an event to Sentry every time the\n * function throws an exception.\n *\n * @param fn A function to wrap. It is generally safe to pass an unbound function, because the returned wrapper always\n * has a correct `this` context.\n * @returns The wrapped function.\n * @hidden\n */\nexport function wrap<T extends WrappableFunction, NonFunction>(\n fn: T | NonFunction,\n options: {\n mechanism?: Mechanism;\n } = {},\n): NonFunction | WrappedFunction<T> {\n // for future readers what this does is wrap a function and then create\n // a bi-directional wrapping between them.\n //\n // example: wrapped = wrap(original);\n // original.__sentry_wrapped__ -> wrapped\n // wrapped.__sentry_original__ -> original\n\n function isFunction(fn: T | NonFunction): fn is T {\n return typeof fn === 'function';\n }\n\n if (!isFunction(fn)) {\n return fn;\n }\n\n try {\n // If we're dealing with a function that was previously wrapped, return the original wrapper.\n // Check via hasOwnProperty so a `__sentry_wrapped__` inherited from a wrapped `Function.prototype`\n // is not mistaken for a real wrapper.\n const hasOwnWrapper = Object.prototype.hasOwnProperty.call(fn, '__sentry_wrapped__');\n if (hasOwnWrapper) {\n const wrapper = (fn as WrappedFunction<T>).__sentry_wrapped__;\n if (typeof wrapper === 'function') {\n return wrapper;\n } else {\n // If we find that the `__sentry_wrapped__` function is not a function at the time of accessing it, it means\n // that something messed with it. In that case we want to return the originally passed function.\n return fn;\n }\n }\n\n // We don't wanna wrap it twice\n if (getOriginalFunction(fn)) {\n return fn;\n }\n } catch {\n // Just accessing custom props in some Selenium environments\n // can cause a \"Permission denied\" exception (see raven-js#495).\n // Bail on wrapping and return the function as-is (defers to window.onerror).\n return fn;\n }\n\n // Wrap the function itself\n // It is important that `sentryWrapped` is not an arrow function to preserve the context of `this`\n const sentryWrapped = function (this: unknown, ...args: unknown[]): unknown {\n // Track depth on GLOBAL_OBJ so the thirdPartyErrorFilterIntegration (in @sentry/core) can detect\n // that processEvent is running inside a sentryWrapped call, even with minified/bundled code.\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) + 1;\n try {\n // Also wrap arguments that are themselves functions\n const wrappedArguments = args.map(arg => wrap(arg, options));\n\n // Attempt to invoke user-land function\n // NOTE: If you are a Sentry user, and you are seeing this stack frame, it\n // means the sentry.javascript SDK caught an error invoking your application code. This\n // is expected behavior and NOT indicative of a bug with sentry.javascript.\n return fn.apply(this, wrappedArguments);\n } catch (ex) {\n ignoreNextOnError();\n\n withScope(scope => {\n scope.addEventProcessor(event => {\n if (options.mechanism) {\n addExceptionTypeValue(event, undefined, undefined);\n addExceptionMechanism(event, options.mechanism);\n }\n\n event.extra = {\n ...event.extra,\n arguments: args,\n };\n\n return event;\n });\n\n // no need to add a mechanism here, we already add it via an event processor above\n captureException(ex);\n });\n\n throw ex;\n } finally {\n GLOBAL_OBJ._sentryWrappedDepth = (GLOBAL_OBJ._sentryWrappedDepth || 0) - 1;\n }\n } as unknown as WrappedFunction<T>;\n\n // Wrap the wrapped function in a proxy, to ensure any other properties of the original function remain available\n try {\n for (const property in fn) {\n if (Object.prototype.hasOwnProperty.call(fn, property)) {\n sentryWrapped[property as keyof T] = fn[property as keyof T];\n }\n }\n } catch {\n // Accessing some objects may throw\n // ref: https://github.com/getsentry/sentry-javascript/issues/1168\n }\n\n // Signal that this function has been wrapped/filled already\n // for both debugging and to prevent it to being wrapped/filled twice\n markFunctionWrapped(sentryWrapped, fn);\n\n addNonEnumerableProperty(fn, '__sentry_wrapped__', sentryWrapped);\n\n // Restore original function name (not all browsers allow that)\n try {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n const descriptor = Object.getOwnPropertyDescriptor(sentryWrapped, 'name')!;\n if (descriptor.configurable) {\n Object.defineProperty(sentryWrapped, 'name', {\n get(): string {\n return fn.name;\n },\n });\n }\n } catch {\n // This may throw if e.g. the descriptor does not exist, or a browser does not allow redefining `name`.\n // to save some bytes we simply try-catch this\n }\n\n return sentryWrapped;\n}\n\n/**\n * Get HTTP request data from the current page.\n */\nexport function getHttpRequestData(): { url: string; headers: Record<string, string> } {\n // grab as much info as exists and add it to the event\n const url = getLocationHref();\n const { referrer } = WINDOW.document || {};\n const { userAgent } = WINDOW.navigator || {};\n\n const headers = {\n ...(referrer && { Referer: referrer }),\n ...(userAgent && { 'User-Agent': userAgent }),\n };\n const request = {\n url,\n headers,\n };\n\n return request;\n}\n"],"names":["fn"],"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,
|
|
3
|
+
export { MULTIPLEXED_TRANSPORT_EXTRA_KEY, SDK_VERSION, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Scope, addBreadcrumb, addEventProcessor, addIntegration, bindScopeToEmitter, captureConsoleIntegration, captureEvent, captureException, captureFeedback, captureMessage, captureSession, close, consoleIntegration, consoleLoggingIntegration, continueTrace, createConsolaReporter, createTransport, dedupeIntegration, endSession, eventFiltersIntegration, extraErrorDataIntegration, featureFlagsIntegration, flush, functionToStringIntegration, getActiveSpan, getClient, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, getSpanDescendants, getSpanStatusFromHttpCode, getTraceData, instrumentSupabaseClient, isEnabled, isInitialized, lastEventId, logger, makeMultiplexedTransport, metrics, moduleMetadataIntegration, parameterize, registerSpanErrorInstrumentation, rewriteFramesIntegration, setAttribute, setAttributes, setContext, setConversationId, setCurrentClient, setExtra, setExtras, setHttpStatus, setMeasurement, setTag, setTags, setUser, spanStreamingIntegration, spanToBaggageHeader, spanToJSON, spanToStaticSpanJSON, spanToTraceHeader, startNewTrace, startSession, supabaseIntegration, suppressTracing, thirdPartyErrorFilterIntegration, updateSpanName, withActiveSpan, withIsolationScope, withScope, withStaticSpan, withStreamedSpan, zodErrorsIntegration } from '@sentry/core';
|
|
4
4
|
export { WINDOW } from './helpers.js';
|
|
5
5
|
export { BrowserClient } from './client.js';
|
|
6
6
|
export { makeFetchTransport } from './transports/fetch.js';
|
|
@@ -32,7 +32,7 @@ const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);
|
|
|
32
32
|
function _installGlobalOnErrorHandler(client) {
|
|
33
33
|
addGlobalErrorInstrumentationHandler((data) => {
|
|
34
34
|
const { stackParser, attachStacktrace } = getOptions();
|
|
35
|
-
if (getClient() !== client || shouldIgnoreOnError()) {
|
|
35
|
+
if (getClient() !== client || shouldIgnoreOnError(data)) {
|
|
36
36
|
return;
|
|
37
37
|
}
|
|
38
38
|
const { msg, url, line, column, error } = data;
|
|
@@ -136,5 +136,5 @@ function getFilenameFromUrl(url) {
|
|
|
136
136
|
return url;
|
|
137
137
|
}
|
|
138
138
|
|
|
139
|
-
export { _eventFromRejectionWithPrimitive, _getUnhandledRejectionError, globalHandlersIntegration };
|
|
139
|
+
export { _enhanceEventWithInitialFrame, _eventFromRejectionWithPrimitive, _getUnhandledRejectionError, globalHandlersIntegration };
|
|
140
140
|
//# sourceMappingURL=globalhandlers.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"globalhandlers.js","sources":["../../../../../src/integrations/globalhandlers.ts"],"sourcesContent":["import type { Client, Event, IntegrationFn, Primitive, StackParser } from '@sentry/core';\nimport {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n isPrimitive,\n isString,\n stripDataUrlContent,\n UNKNOWN_FUNCTION,\n} from '@sentry/core';\nimport type { BrowserClient } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getLocationHref } from '@sentry/browser-utils';\nimport { eventFromUnknownInput } from '../eventbuilder';\nimport { shouldIgnoreOnError } from '../helpers';\n\ntype GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection';\n\ntype GlobalHandlersIntegrations = Record<GlobalHandlersIntegrationsOptionKeys, boolean>;\n\nconst INTEGRATION_NAME = 'GlobalHandlers' as const;\n\nconst _globalHandlersIntegration = ((options: Partial<GlobalHandlersIntegrations> = {}) => {\n const _options = {\n onerror: true,\n onunhandledrejection: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n Error.stackTraceLimit = 50;\n },\n setup(client) {\n if (_options.onerror) {\n _installGlobalOnErrorHandler(client);\n globalHandlerLog('onerror');\n }\n if (_options.onunhandledrejection) {\n _installGlobalOnUnhandledRejectionHandler(client);\n globalHandlerLog('onunhandledrejection');\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);\n\nfunction _installGlobalOnErrorHandler(client: Client): void {\n addGlobalErrorInstrumentationHandler(data => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const { msg, url, line, column, error } = data;\n\n const event = _enhanceEventWithInitialFrame(\n eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),\n url,\n line,\n column,\n );\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onerror',\n },\n });\n });\n}\n\nfunction _installGlobalOnUnhandledRejectionHandler(client: Client): void {\n addGlobalUnhandledRejectionInstrumentationHandler(e => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const error = _getUnhandledRejectionError(e);\n\n const event = isPrimitive(error)\n ? _eventFromRejectionWithPrimitive(error)\n : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onunhandledrejection',\n },\n });\n });\n}\n\n/**\n *\n */\nexport function _getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error;\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown };\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason;\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } };\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason;\n }\n } catch {} // eslint-disable-line no-empty\n\n return error;\n}\n\n/**\n * Create an event from a promise rejection where the `reason` is a primitive.\n *\n * @param reason: The `reason` property of the promise rejection\n * @returns An Event object with an appropriate `exception` value\n */\nexport function _eventFromRejectionWithPrimitive(reason: Primitive): Event {\n return {\n exception: {\n values: [\n {\n type: 'UnhandledRejection',\n // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)\n value: `Non-Error promise rejection captured with value: ${String(reason)}`,\n },\n ],\n },\n };\n}\n\nfunction _enhanceEventWithInitialFrame(\n event: Event,\n url: string | undefined,\n lineno: number | undefined,\n colno: number | undefined,\n): Event {\n // event.exception\n const e = (event.exception = event.exception || {});\n // event.exception.values\n const ev = (e.values = e.values || []);\n // event.exception.values[0]\n const ev0 = (ev[0] = ev[0] || {});\n // event.exception.values[0].stacktrace\n const ev0s = (ev0.stacktrace = ev0.stacktrace || {});\n // event.exception.values[0].stacktrace.frames\n const ev0sf = (ev0s.frames = ev0s.frames || []);\n\n if (ev0sf.length === 0) {\n ev0sf.push({\n colno,\n lineno,\n filename: getFilenameFromUrl(url) ?? getLocationHref(),\n function: UNKNOWN_FUNCTION,\n in_app: true,\n });\n }\n\n return event;\n}\n\nfunction globalHandlerLog(type: string): void {\n DEBUG_BUILD && debug.log(`Global Handler attached: ${type}`);\n}\n\nfunction getOptions(): { stackParser: StackParser; attachStacktrace?: boolean } {\n const client = getClient<BrowserClient>();\n const options = client?.getOptions() || {\n stackParser: () => [],\n attachStacktrace: false,\n };\n return options;\n}\n\nfunction getFilenameFromUrl(url: string | undefined): string | undefined {\n if (!isString(url) || url.length === 0) {\n return undefined;\n }\n\n // Strip data URL content to avoid long base64 strings in stack frames\n // (e.g. when initializing a Worker with a base64 encoded script)\n // Don't include data prefix for filenames as it's not useful for stack traces\n // Wrap with < > to indicate it's a placeholder\n if (url.startsWith('data:')) {\n return `<${stripDataUrlContent(url, false)}>`;\n }\n\n return url;\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"globalhandlers.js","sources":["../../../../../src/integrations/globalhandlers.ts"],"sourcesContent":["import type { Client, Event, IntegrationFn, Primitive, StackParser } from '@sentry/core';\nimport {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n captureEvent,\n debug,\n defineIntegration,\n getClient,\n isPrimitive,\n isString,\n stripDataUrlContent,\n UNKNOWN_FUNCTION,\n} from '@sentry/core';\nimport type { BrowserClient } from '../client';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { getLocationHref } from '@sentry/browser-utils';\nimport { eventFromUnknownInput } from '../eventbuilder';\nimport { shouldIgnoreOnError } from '../helpers';\n\ntype GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection';\n\ntype GlobalHandlersIntegrations = Record<GlobalHandlersIntegrationsOptionKeys, boolean>;\n\nconst INTEGRATION_NAME = 'GlobalHandlers' as const;\n\nconst _globalHandlersIntegration = ((options: Partial<GlobalHandlersIntegrations> = {}) => {\n const _options = {\n onerror: true,\n onunhandledrejection: true,\n ...options,\n };\n\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n Error.stackTraceLimit = 50;\n },\n setup(client) {\n if (_options.onerror) {\n _installGlobalOnErrorHandler(client);\n globalHandlerLog('onerror');\n }\n if (_options.onunhandledrejection) {\n _installGlobalOnUnhandledRejectionHandler(client);\n globalHandlerLog('onunhandledrejection');\n }\n },\n };\n}) satisfies IntegrationFn;\n\nexport const globalHandlersIntegration = defineIntegration(_globalHandlersIntegration);\n\nfunction _installGlobalOnErrorHandler(client: Client): void {\n addGlobalErrorInstrumentationHandler(data => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError(data)) {\n return;\n }\n\n const { msg, url, line, column, error } = data;\n\n const event = _enhanceEventWithInitialFrame(\n eventFromUnknownInput(stackParser, error || msg, undefined, attachStacktrace, false),\n url,\n line,\n column,\n );\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onerror',\n },\n });\n });\n}\n\nfunction _installGlobalOnUnhandledRejectionHandler(client: Client): void {\n addGlobalUnhandledRejectionInstrumentationHandler(e => {\n const { stackParser, attachStacktrace } = getOptions();\n\n if (getClient() !== client || shouldIgnoreOnError()) {\n return;\n }\n\n const error = _getUnhandledRejectionError(e);\n\n const event = isPrimitive(error)\n ? _eventFromRejectionWithPrimitive(error)\n : eventFromUnknownInput(stackParser, error, undefined, attachStacktrace, true);\n\n event.level = 'error';\n\n captureEvent(event, {\n originalException: error,\n mechanism: {\n handled: false,\n type: 'auto.browser.global_handlers.onunhandledrejection',\n },\n });\n });\n}\n\n/**\n *\n */\nexport function _getUnhandledRejectionError(error: unknown): unknown {\n if (isPrimitive(error)) {\n return error;\n }\n\n // dig the object of the rejection out of known event types\n try {\n type ErrorWithReason = { reason: unknown };\n // PromiseRejectionEvents store the object of the rejection under 'reason'\n // see https://developer.mozilla.org/en-US/docs/Web/API/PromiseRejectionEvent\n if ('reason' in (error as ErrorWithReason)) {\n return (error as ErrorWithReason).reason;\n }\n\n type CustomEventWithDetail = { detail: { reason: unknown } };\n // something, somewhere, (likely a browser extension) effectively casts PromiseRejectionEvents\n // to CustomEvents, moving the `promise` and `reason` attributes of the PRE into\n // the CustomEvent's `detail` attribute, since they're not part of CustomEvent's spec\n // see https://developer.mozilla.org/en-US/docs/Web/API/CustomEvent and\n // https://github.com/getsentry/sentry-javascript/issues/2380\n if ('detail' in (error as CustomEventWithDetail) && 'reason' in (error as CustomEventWithDetail).detail) {\n return (error as CustomEventWithDetail).detail.reason;\n }\n } catch {} // eslint-disable-line no-empty\n\n return error;\n}\n\n/**\n * Create an event from a promise rejection where the `reason` is a primitive.\n *\n * @param reason: The `reason` property of the promise rejection\n * @returns An Event object with an appropriate `exception` value\n */\nexport function _eventFromRejectionWithPrimitive(reason: Primitive): Event {\n return {\n exception: {\n values: [\n {\n type: 'UnhandledRejection',\n // String() is needed because the Primitive type includes symbols (which can't be automatically stringified)\n value: `Non-Error promise rejection captured with value: ${String(reason)}`,\n },\n ],\n },\n };\n}\n\n/**\n * Adds a frame built from the error location when the event has none.\n */\nexport function _enhanceEventWithInitialFrame(\n event: Event,\n url: string | undefined,\n lineno: number | undefined,\n colno: number | undefined,\n): Event {\n // event.exception\n const e = (event.exception = event.exception || {});\n // event.exception.values\n const ev = (e.values = e.values || []);\n // event.exception.values[0]\n const ev0 = (ev[0] = ev[0] || {});\n // event.exception.values[0].stacktrace\n const ev0s = (ev0.stacktrace = ev0.stacktrace || {});\n // event.exception.values[0].stacktrace.frames\n const ev0sf = (ev0s.frames = ev0s.frames || []);\n\n if (ev0sf.length === 0) {\n ev0sf.push({\n colno,\n lineno,\n filename: getFilenameFromUrl(url) ?? getLocationHref(),\n function: UNKNOWN_FUNCTION,\n in_app: true,\n });\n }\n\n return event;\n}\n\nfunction globalHandlerLog(type: string): void {\n DEBUG_BUILD && debug.log(`Global Handler attached: ${type}`);\n}\n\nfunction getOptions(): { stackParser: StackParser; attachStacktrace?: boolean } {\n const client = getClient<BrowserClient>();\n const options = client?.getOptions() || {\n stackParser: () => [],\n attachStacktrace: false,\n };\n return options;\n}\n\nfunction getFilenameFromUrl(url: string | undefined): string | undefined {\n if (!isString(url) || url.length === 0) {\n return undefined;\n }\n\n // Strip data URL content to avoid long base64 strings in stack frames\n // (e.g. when initializing a Worker with a base64 encoded script)\n // Don't include data prefix for filenames as it's not useful for stack traces\n // Wrap with < > to indicate it's a placeholder\n if (url.startsWith('data:')) {\n return `<${stripDataUrlContent(url, false)}>`;\n }\n\n return url;\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -32,17 +32,11 @@ function _fetchResponseHandler(options, requestInfo, response, requestInit, erro
|
|
|
32
32
|
if (dc.cookies !== false) {
|
|
33
33
|
const reqCookieStr = request.headers.get("Cookie") || void 0;
|
|
34
34
|
if (reqCookieStr) {
|
|
35
|
-
|
|
36
|
-
if (typeof filtered === "object") {
|
|
37
|
-
requestCookies = filtered;
|
|
38
|
-
}
|
|
35
|
+
requestCookies = _INTERNAL_filterCookies(reqCookieStr, dc.cookies, "cookie");
|
|
39
36
|
}
|
|
40
37
|
const resCookieStr = response.headers.get("Set-Cookie") || void 0;
|
|
41
38
|
if (resCookieStr) {
|
|
42
|
-
|
|
43
|
-
if (typeof filtered === "object") {
|
|
44
|
-
responseCookies = filtered;
|
|
45
|
-
}
|
|
39
|
+
responseCookies = _INTERNAL_filterCookies(resCookieStr, dc.cookies, "set-cookie");
|
|
46
40
|
}
|
|
47
41
|
}
|
|
48
42
|
const event = _createEvent({
|
|
@@ -67,10 +61,7 @@ function _xhrResponseHandler(options, xhr, method, headers, error) {
|
|
|
67
61
|
try {
|
|
68
62
|
const cookieString = xhr.getResponseHeader("Set-Cookie") || xhr.getResponseHeader("set-cookie") || void 0;
|
|
69
63
|
if (cookieString) {
|
|
70
|
-
|
|
71
|
-
if (typeof filtered === "object") {
|
|
72
|
-
responseCookies = filtered;
|
|
73
|
-
}
|
|
64
|
+
responseCookies = _INTERNAL_filterCookies(cookieString, dc.cookies, "set-cookie");
|
|
74
65
|
}
|
|
75
66
|
} catch {
|
|
76
67
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpclient.js","sources":["../../../../../src/integrations/httpclient.ts"],"sourcesContent":["import type { Client, Event as SentryEvent, IntegrationFn } from '@sentry/core';\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} from '@sentry/core';\nimport type { SentryWrappedXMLHttpRequest } from '@sentry/browser-utils';\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' as const;\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 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 });\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 const { cookies, httpHeaders } = client.getDataCollectionOptions();\n return { cookies, requestHeaders: httpHeaders.request, responseHeaders: httpHeaders.response };\n}\n"],"names":[],"mappings":";;;;AAoBA,MAAM,gBAAA,GAAmB,YAAA;AAuBzB,MAAM,sBAAA,IAA0B,CAAC,OAAA,GAAsC,EAAC,KAAM;AAC5E,EAAA,MAAM,QAAA,GAA8B;AAAA,IAClC,wBAAA,EAA0B,CAAC,CAAC,GAAA,EAAK,GAAG,CAAC,CAAA;AAAA,IACrC,oBAAA,EAAsB,CAAC,IAAI,CAAA;AAAA,IAC3B,GAAG;AAAA,GACL;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,MAAM,MAAA,EAAc;AAClB,MAAA,UAAA,CAAW,QAAQ,QAAQ,CAAA;AAC3B,MAAA,QAAA,CAAS,QAAQ,QAAQ,CAAA;AAAA,IAC3B;AAAA,GACF;AACF,CAAA,CAAA;AAKO,MAAM,qBAAA,GAAwB,kBAAkB,sBAAsB;AAS7E,SAAS,qBAAA,CACP,OAAA,EACA,WAAA,EACA,QAAA,EACA,aACA,KAAA,EACM;AACN,EAAA,IAAI,uBAAuB,OAAA,EAAS,QAAA,CAAS,MAAA,EAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAClE,IAAA,MAAM,OAAA,GAAU,WAAA,CAAY,WAAA,EAAa,WAAW,CAAA;AAEpD,IAAA,IAAI,cAAA,EAAgB,iBAAiB,cAAA,EAAgB,eAAA;AAErD,IAAA,MAAM,KAAK,0BAAA,EAA2B;AAEtC,IAAA,IAAI,EAAA,CAAG,mBAAmB,KAAA,EAAO;AAC/B,MAAA,cAAA,GAAiB,6BAA6B,oBAAA,CAAqB,OAAA,CAAQ,OAAO,CAAA,EAAG,GAAG,cAAc,CAAA;AAAA,IACxG;AACA,IAAA,IAAI,EAAA,CAAG,oBAAoB,KAAA,EAAO;AAChC,MAAA,eAAA,GAAkB,6BAA6B,oBAAA,CAAqB,QAAA,CAAS,OAAO,CAAA,EAAG,GAAG,eAAe,CAAA;AAAA,IAC3G;AACA,IAAA,IAAI,EAAA,CAAG,YAAY,KAAA,EAAO;AACxB,MAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,IAAK,MAAA;AACtD,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,MAAM,QAAA,GAAW,uBAAA,CAAwB,YAAA,EAAc,EAAA,CAAG,OAAO,CAAA;AACjE,QAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAChC,UAAA,cAAA,GAAiB,QAAA;AAAA,QACnB;AAAA,MACF;AACA,MAAA,MAAM,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,IAAK,MAAA;AAC3D,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,MAAM,QAAA,GAAW,uBAAA,CAAwB,YAAA,EAAc,EAAA,CAAG,OAAO,CAAA;AACjE,QAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAChC,UAAA,eAAA,GAAkB,QAAA;AAAA,QACpB;AAAA,MACF;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,YAAA,CAAa;AAAA,MACzB,KAAK,OAAA,CAAQ,GAAA;AAAA,MACb,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,cAAA;AAAA,MACA,eAAA;AAAA,MACA,cAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA;AAED,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AASA,SAAS,mBAAA,CACP,OAAA,EACA,GAAA,EACA,MAAA,EACA,SACA,KAAA,EACM;AACN,EAAA,IAAI,uBAAuB,OAAA,EAAS,GAAA,CAAI,MAAA,EAAQ,GAAA,CAAI,WAAW,CAAA,EAAG;AAChE,IAAA,IAAI,gBAAgB,eAAA,EAAiB,eAAA;AAErC,IAAA,MAAM,KAAK,0BAAA,EAA2B;AAEtC,IAAA,IAAI,EAAA,CAAG,YAAY,KAAA,EAAO;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,YAAA,GAAe,IAAI,iBAAA,CAAkB,YAAY,KAAK,GAAA,CAAI,iBAAA,CAAkB,YAAY,CAAA,IAAK,KAAA,CAAA;AACnG,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,MAAM,QAAA,GAAW,uBAAA,CAAwB,YAAA,EAAc,EAAA,CAAG,OAAO,CAAA;AACjE,UAAA,IAAI,OAAO,aAAa,QAAA,EAAU;AAChC,YAAA,eAAA,GAAkB,QAAA;AAAA,UACpB;AAAA,QACF;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAEA,IAAA,IAAI,EAAA,CAAG,oBAAoB,KAAA,EAAO;AAChC,MAAA,IAAI;AACF,QAAA,eAAA,GAAkB,4BAAA,CAA6B,sBAAA,CAAuB,GAAG,CAAA,EAAG,GAAG,eAAe,CAAA;AAAA,MAChG,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAEA,IAAA,IAAI,EAAA,CAAG,mBAAmB,KAAA,EAAO;AAC/B,MAAA,cAAA,GAAiB,4BAAA,CAA6B,OAAA,EAAS,EAAA,CAAG,cAAc,CAAA;AAAA,IAC1E;AAEA,IAAA,MAAM,QAAQ,YAAA,CAAa;AAAA,MACzB,KAAK,GAAA,CAAI,WAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,cAAA;AAAA;AAAA,MAEA,eAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA;AAED,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AAQA,SAAS,4BAA4B,OAAA,EAAsD;AACzF,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,gBAAgB,CAAA,IAAK,QAAQ,gBAAgB,CAAA;AAE3E,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,OAAO,QAAA,CAAS,eAAe,EAAE,CAAA;AAAA,IACnC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAQA,SAAS,qBAAqB,OAAA,EAA0C;AACtE,EAAA,MAAM,SAAiC,EAAC;AAExC,EAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC9B,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,EAChB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAQA,SAAS,uBAAuB,GAAA,EAA6C;AAC3E,EAAA,MAAM,OAAA,GAAU,IAAI,qBAAA,EAAsB;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,OAAO,QAAQ,KAAA,CAAM,MAAM,EAAE,MAAA,CAAO,CAAC,KAA6B,IAAA,KAAiB;AACjF,IAAA,MAAM,CAAC,GAAA,EAAK,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,IAAI,CAAA;AACpC,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,IACb;AACA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AACP;AAQA,SAAS,wBAAA,CACP,sBACA,MAAA,EACS;AACT,EAAA,OAAO,oBAAA,CAAqB,IAAA,CAAK,CAAC,kBAAA,KAA0C;AAC1E,IAAA,IAAI,OAAO,uBAAuB,QAAA,EAAU;AAC1C,MAAA,OAAO,MAAA,CAAO,SAAS,kBAAkB,CAAA;AAAA,IAC3C;AAEA,IAAA,OAAO,kBAAA,CAAmB,KAAK,MAAM,CAAA;AAAA,EACvC,CAAC,CAAA;AACH;AAQA,SAAS,sBAAA,CACP,0BACA,MAAA,EACS;AACT,EAAA,OAAO,wBAAA,CAAyB,IAAA,CAAK,CAAC,KAAA,KAA+B;AACnE,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,OAAO,KAAA,KAAU,MAAA;AAAA,IACnB;AAEA,IAAA,OAAO,UAAU,KAAA,CAAM,CAAC,CAAA,IAAK,MAAA,IAAU,MAAM,CAAC,CAAA;AAAA,EAChD,CAAC,CAAA;AACH;AAKA,SAAS,UAAA,CAAW,QAAgB,OAAA,EAAkC;AACpE,EAAA,8BAAA,CAA+B,CAAA,WAAA,KAAe;AAC5C,IAAA,IAAI,SAAA,OAAgB,MAAA,EAAQ;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,cAAa,GAAI,WAAA;AAChD,IAAA,MAAM,CAAC,WAAA,EAAa,WAAW,CAAA,GAAI,IAAA;AAEnC,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA;AAAA,IACF;AAEA,IAAA,qBAAA,CAAsB,OAAA,EAAS,WAAA,EAAa,QAAA,EAAsB,WAAA,EAAa,SAAS,YAAY,CAAA;AAAA,EACtG,CAAC,CAAA;AACH;AAKA,SAAS,QAAA,CAAS,QAAgB,OAAA,EAAkC;AAClE,EAAA,IAAI,EAAE,oBAAoB,UAAA,CAAA,EAAa;AACrC,IAAA;AAAA,EACF;AAEA,EAAA,4BAAA,CAA6B,CAAA,WAAA,KAAe;AAC1C,IAAA,IAAI,SAAA,OAAgB,MAAA,EAAQ;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAa,GAAI,WAAA;AAEhC,IAAA,MAAM,MAAM,WAAA,CAAY,GAAA;AAExB,IAAA,MAAM,aAAA,GAAgB,IAAI,mBAAmB,CAAA;AAE7C,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,MAAA,EAAQ,eAAA,EAAiB,OAAA,EAAQ,GAAI,aAAA;AAE7C,IAAA,IAAI;AACF,MAAA,mBAAA,CAAoB,OAAA,EAAS,GAAA,EAAK,MAAA,EAAQ,OAAA,EAAS,SAAS,YAAY,CAAA;AAAA,IAC1E,SAAS,CAAA,EAAG;AACV,MAAA,WAAA,IAAe,KAAA,CAAM,IAAA,CAAK,yDAAA,EAA2D,CAAC,CAAA;AAAA,IACxF;AAAA,EACF,CAAC,CAAA;AACH;AAQA,SAAS,sBAAA,CAAuB,OAAA,EAA4B,MAAA,EAAgB,GAAA,EAAsB;AAChG,EAAA,OACE,sBAAA,CAAuB,OAAA,CAAQ,wBAAA,EAA0B,MAAM,KAC/D,wBAAA,CAAyB,OAAA,CAAQ,oBAAA,EAAsB,GAAG,CAAA,IAC1D,CAAC,kBAAA,CAAmB,GAAA,EAAK,WAAW,CAAA;AAExC;AAQA,SAAS,aAAa,IAAA,EAUN;AACd,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,iBAAA,GAAoB,UAAU,IAAA,CAAK,KAAA,IAAS,KAAK,KAAA,YAAiB,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,MAAA;AAEnG,EAAA,MAAM,KAAA,GAAQ,iBAAA,IAAqB,MAAA,GAAS,MAAA,CAAO,UAAA,GAAa,WAAA,CAAY,iBAAA,EAAmB,CAAA,EAAG,CAAC,CAAA,GAAI,MAAA;AACvG,EAAA,MAAM,OAAA,GAAU,CAAA,oCAAA,EAAuC,IAAA,CAAK,MAAM,CAAA,CAAA;AAElE,EAAA,MAAM,KAAA,GAAqB;AAAA,IACzB,OAAA;AAAA,IACA,SAAA,EAAW;AAAA,MACT,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,IAAA,EAAM,OAAA;AAAA,UACN,KAAA,EAAO,OAAA;AAAA,UACP,UAAA,EAAY,KAAA,GAAQ,EAAE,MAAA,EAAQ,OAAM,GAAI;AAAA;AAC1C;AACF,KACF;AAAA,IACA,OAAA,EAAS;AAAA,MACP,KAAK,IAAA,CAAK,GAAA;AAAA,MACV,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,cAAA;AAAA,MACd,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,IACA,QAAA,EAAU;AAAA,MACR,QAAA,EAAU;AAAA,QACR,aAAa,IAAA,CAAK,MAAA;AAAA,QAClB,SAAS,IAAA,CAAK,eAAA;AAAA,QACd,SAAS,IAAA,CAAK,eAAA;AAAA,QACd,SAAA,EAAW,2BAAA,CAA4B,IAAA,CAAK,eAAe;AAAA;AAC7D;AACF,GACF;AAEA,EAAA,qBAAA,CAAsB,KAAA,EAAO;AAAA,IAC3B,IAAA,EAAM,CAAA,iBAAA,EAAoB,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,IACnC,OAAA,EAAS;AAAA,GACV,CAAA;AAED,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,WAAA,CAAY,aAA0B,WAAA,EAAoC;AACjF,EAAA,IAAI,CAAC,WAAA,IAAe,WAAA,YAAuB,OAAA,EAAS;AAClD,IAAA,OAAO,WAAA;AAAA,EACT;AAKA,EAAA,IAAI,WAAA,YAAuB,OAAA,IAAW,WAAA,CAAY,QAAA,EAAU;AAC1D,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAI,OAAA,CAAQ,WAAA,EAAa,WAAW,CAAA;AAC7C;AAEA,SAAS,0BAAA,GAA6B;AACpC,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,cAAA,EAAgB,KAAA,EAAO,iBAAiB,KAAA,EAAM;AAAA,EACzE;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,WAAA,EAAY,GAAI,OAAO,wBAAA,EAAyB;AACjE,EAAA,OAAO,EAAE,OAAA,EAAS,cAAA,EAAgB,YAAY,OAAA,EAAS,eAAA,EAAiB,YAAY,QAAA,EAAS;AAC/F;;;;"}
|
|
1
|
+
{"version":3,"file":"httpclient.js","sources":["../../../../../src/integrations/httpclient.ts"],"sourcesContent":["import type { Client, Event as SentryEvent, IntegrationFn } from '@sentry/core';\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} from '@sentry/core';\nimport type { SentryWrappedXMLHttpRequest } from '@sentry/browser-utils';\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' as const;\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 requestCookies = _INTERNAL_filterCookies(reqCookieStr, dc.cookies, 'cookie');\n }\n const resCookieStr = response.headers.get('Set-Cookie') || undefined;\n if (resCookieStr) {\n responseCookies = _INTERNAL_filterCookies(resCookieStr, dc.cookies, 'set-cookie');\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 responseCookies = _INTERNAL_filterCookies(cookieString, dc.cookies, 'set-cookie');\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 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 });\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 const { cookies, httpHeaders } = client.getDataCollectionOptions();\n return { cookies, requestHeaders: httpHeaders.request, responseHeaders: httpHeaders.response };\n}\n"],"names":[],"mappings":";;;;AAoBA,MAAM,gBAAA,GAAmB,YAAA;AAuBzB,MAAM,sBAAA,IAA0B,CAAC,OAAA,GAAsC,EAAC,KAAM;AAC5E,EAAA,MAAM,QAAA,GAA8B;AAAA,IAClC,wBAAA,EAA0B,CAAC,CAAC,GAAA,EAAK,GAAG,CAAC,CAAA;AAAA,IACrC,oBAAA,EAAsB,CAAC,IAAI,CAAA;AAAA,IAC3B,GAAG;AAAA,GACL;AAEA,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,gBAAA;AAAA,IACN,MAAM,MAAA,EAAc;AAClB,MAAA,UAAA,CAAW,QAAQ,QAAQ,CAAA;AAC3B,MAAA,QAAA,CAAS,QAAQ,QAAQ,CAAA;AAAA,IAC3B;AAAA,GACF;AACF,CAAA,CAAA;AAKO,MAAM,qBAAA,GAAwB,kBAAkB,sBAAsB;AAS7E,SAAS,qBAAA,CACP,OAAA,EACA,WAAA,EACA,QAAA,EACA,aACA,KAAA,EACM;AACN,EAAA,IAAI,uBAAuB,OAAA,EAAS,QAAA,CAAS,MAAA,EAAQ,QAAA,CAAS,GAAG,CAAA,EAAG;AAClE,IAAA,MAAM,OAAA,GAAU,WAAA,CAAY,WAAA,EAAa,WAAW,CAAA;AAEpD,IAAA,IAAI,cAAA,EAAgB,iBAAiB,cAAA,EAAgB,eAAA;AAErD,IAAA,MAAM,KAAK,0BAAA,EAA2B;AAEtC,IAAA,IAAI,EAAA,CAAG,mBAAmB,KAAA,EAAO;AAC/B,MAAA,cAAA,GAAiB,6BAA6B,oBAAA,CAAqB,OAAA,CAAQ,OAAO,CAAA,EAAG,GAAG,cAAc,CAAA;AAAA,IACxG;AACA,IAAA,IAAI,EAAA,CAAG,oBAAoB,KAAA,EAAO;AAChC,MAAA,eAAA,GAAkB,6BAA6B,oBAAA,CAAqB,QAAA,CAAS,OAAO,CAAA,EAAG,GAAG,eAAe,CAAA;AAAA,IAC3G;AACA,IAAA,IAAI,EAAA,CAAG,YAAY,KAAA,EAAO;AACxB,MAAA,MAAM,YAAA,GAAe,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,QAAQ,CAAA,IAAK,MAAA;AACtD,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,cAAA,GAAiB,uBAAA,CAAwB,YAAA,EAAc,EAAA,CAAG,OAAA,EAAS,QAAQ,CAAA;AAAA,MAC7E;AACA,MAAA,MAAM,YAAA,GAAe,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,YAAY,CAAA,IAAK,MAAA;AAC3D,MAAA,IAAI,YAAA,EAAc;AAChB,QAAA,eAAA,GAAkB,uBAAA,CAAwB,YAAA,EAAc,EAAA,CAAG,OAAA,EAAS,YAAY,CAAA;AAAA,MAClF;AAAA,IACF;AAEA,IAAA,MAAM,QAAQ,YAAA,CAAa;AAAA,MACzB,KAAK,OAAA,CAAQ,GAAA;AAAA,MACb,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,QAAQ,QAAA,CAAS,MAAA;AAAA,MACjB,cAAA;AAAA,MACA,eAAA;AAAA,MACA,cAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA;AAED,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AASA,SAAS,mBAAA,CACP,OAAA,EACA,GAAA,EACA,MAAA,EACA,SACA,KAAA,EACM;AACN,EAAA,IAAI,uBAAuB,OAAA,EAAS,GAAA,CAAI,MAAA,EAAQ,GAAA,CAAI,WAAW,CAAA,EAAG;AAChE,IAAA,IAAI,gBAAgB,eAAA,EAAiB,eAAA;AAErC,IAAA,MAAM,KAAK,0BAAA,EAA2B;AAEtC,IAAA,IAAI,EAAA,CAAG,YAAY,KAAA,EAAO;AACxB,MAAA,IAAI;AACF,QAAA,MAAM,YAAA,GAAe,IAAI,iBAAA,CAAkB,YAAY,KAAK,GAAA,CAAI,iBAAA,CAAkB,YAAY,CAAA,IAAK,KAAA,CAAA;AACnG,QAAA,IAAI,YAAA,EAAc;AAChB,UAAA,eAAA,GAAkB,uBAAA,CAAwB,YAAA,EAAc,EAAA,CAAG,OAAA,EAAS,YAAY,CAAA;AAAA,QAClF;AAAA,MACF,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAEA,IAAA,IAAI,EAAA,CAAG,oBAAoB,KAAA,EAAO;AAChC,MAAA,IAAI;AACF,QAAA,eAAA,GAAkB,4BAAA,CAA6B,sBAAA,CAAuB,GAAG,CAAA,EAAG,GAAG,eAAe,CAAA;AAAA,MAChG,CAAA,CAAA,MAAQ;AAAA,MAER;AAAA,IACF;AAEA,IAAA,IAAI,EAAA,CAAG,mBAAmB,KAAA,EAAO;AAC/B,MAAA,cAAA,GAAiB,4BAAA,CAA6B,OAAA,EAAS,EAAA,CAAG,cAAc,CAAA;AAAA,IAC1E;AAEA,IAAA,MAAM,QAAQ,YAAA,CAAa;AAAA,MACzB,KAAK,GAAA,CAAI,WAAA;AAAA,MACT,MAAA;AAAA,MACA,QAAQ,GAAA,CAAI,MAAA;AAAA,MACZ,cAAA;AAAA;AAAA,MAEA,eAAA;AAAA,MACA,eAAA;AAAA,MACA,KAAA;AAAA,MACA,IAAA,EAAM;AAAA,KACP,CAAA;AAED,IAAA,YAAA,CAAa,KAAK,CAAA;AAAA,EACpB;AACF;AAQA,SAAS,4BAA4B,OAAA,EAAsD;AACzF,EAAA,IAAI,OAAA,EAAS;AACX,IAAA,MAAM,aAAA,GAAgB,OAAA,CAAQ,gBAAgB,CAAA,IAAK,QAAQ,gBAAgB,CAAA;AAE3E,IAAA,IAAI,aAAA,EAAe;AACjB,MAAA,OAAO,QAAA,CAAS,eAAe,EAAE,CAAA;AAAA,IACnC;AAAA,EACF;AAEA,EAAA,OAAO,MAAA;AACT;AAQA,SAAS,qBAAqB,OAAA,EAA0C;AACtE,EAAA,MAAM,SAAiC,EAAC;AAExC,EAAA,OAAA,CAAQ,OAAA,CAAQ,CAAC,KAAA,EAAO,GAAA,KAAQ;AAC9B,IAAA,MAAA,CAAO,GAAG,CAAA,GAAI,KAAA;AAAA,EAChB,CAAC,CAAA;AAED,EAAA,OAAO,MAAA;AACT;AAQA,SAAS,uBAAuB,GAAA,EAA6C;AAC3E,EAAA,MAAM,OAAA,GAAU,IAAI,qBAAA,EAAsB;AAE1C,EAAA,IAAI,CAAC,OAAA,EAAS;AACZ,IAAA,OAAO,EAAC;AAAA,EACV;AAEA,EAAA,OAAO,QAAQ,KAAA,CAAM,MAAM,EAAE,MAAA,CAAO,CAAC,KAA6B,IAAA,KAAiB;AACjF,IAAA,MAAM,CAAC,GAAA,EAAK,KAAK,CAAA,GAAI,IAAA,CAAK,MAAM,IAAI,CAAA;AACpC,IAAA,IAAI,OAAO,KAAA,EAAO;AAChB,MAAA,GAAA,CAAI,GAAG,CAAA,GAAI,KAAA;AAAA,IACb;AACA,IAAA,OAAO,GAAA;AAAA,EACT,CAAA,EAAG,EAAE,CAAA;AACP;AAQA,SAAS,wBAAA,CACP,sBACA,MAAA,EACS;AACT,EAAA,OAAO,oBAAA,CAAqB,IAAA,CAAK,CAAC,kBAAA,KAA0C;AAC1E,IAAA,IAAI,OAAO,uBAAuB,QAAA,EAAU;AAC1C,MAAA,OAAO,MAAA,CAAO,SAAS,kBAAkB,CAAA;AAAA,IAC3C;AAEA,IAAA,OAAO,kBAAA,CAAmB,KAAK,MAAM,CAAA;AAAA,EACvC,CAAC,CAAA;AACH;AAQA,SAAS,sBAAA,CACP,0BACA,MAAA,EACS;AACT,EAAA,OAAO,wBAAA,CAAyB,IAAA,CAAK,CAAC,KAAA,KAA+B;AACnE,IAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC7B,MAAA,OAAO,KAAA,KAAU,MAAA;AAAA,IACnB;AAEA,IAAA,OAAO,UAAU,KAAA,CAAM,CAAC,CAAA,IAAK,MAAA,IAAU,MAAM,CAAC,CAAA;AAAA,EAChD,CAAC,CAAA;AACH;AAKA,SAAS,UAAA,CAAW,QAAgB,OAAA,EAAkC;AACpE,EAAA,8BAAA,CAA+B,CAAA,WAAA,KAAe;AAC5C,IAAA,IAAI,SAAA,OAAgB,MAAA,EAAQ;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,QAAA,EAAU,IAAA,EAAM,KAAA,EAAO,cAAa,GAAI,WAAA;AAChD,IAAA,MAAM,CAAC,WAAA,EAAa,WAAW,CAAA,GAAI,IAAA;AAEnC,IAAA,IAAI,CAAC,QAAA,EAAU;AACb,MAAA;AAAA,IACF;AAEA,IAAA,qBAAA,CAAsB,OAAA,EAAS,WAAA,EAAa,QAAA,EAAsB,WAAA,EAAa,SAAS,YAAY,CAAA;AAAA,EACtG,CAAC,CAAA;AACH;AAKA,SAAS,QAAA,CAAS,QAAgB,OAAA,EAAkC;AAClE,EAAA,IAAI,EAAE,oBAAoB,UAAA,CAAA,EAAa;AACrC,IAAA;AAAA,EACF;AAEA,EAAA,4BAAA,CAA6B,CAAA,WAAA,KAAe;AAC1C,IAAA,IAAI,SAAA,OAAgB,MAAA,EAAQ;AAC1B,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,KAAA,EAAO,YAAA,EAAa,GAAI,WAAA;AAEhC,IAAA,MAAM,MAAM,WAAA,CAAY,GAAA;AAExB,IAAA,MAAM,aAAA,GAAgB,IAAI,mBAAmB,CAAA;AAE7C,IAAA,IAAI,CAAC,aAAA,EAAe;AAClB,MAAA;AAAA,IACF;AAEA,IAAA,MAAM,EAAE,MAAA,EAAQ,eAAA,EAAiB,OAAA,EAAQ,GAAI,aAAA;AAE7C,IAAA,IAAI;AACF,MAAA,mBAAA,CAAoB,OAAA,EAAS,GAAA,EAAK,MAAA,EAAQ,OAAA,EAAS,SAAS,YAAY,CAAA;AAAA,IAC1E,SAAS,CAAA,EAAG;AACV,MAAA,WAAA,IAAe,KAAA,CAAM,IAAA,CAAK,yDAAA,EAA2D,CAAC,CAAA;AAAA,IACxF;AAAA,EACF,CAAC,CAAA;AACH;AAQA,SAAS,sBAAA,CAAuB,OAAA,EAA4B,MAAA,EAAgB,GAAA,EAAsB;AAChG,EAAA,OACE,sBAAA,CAAuB,OAAA,CAAQ,wBAAA,EAA0B,MAAM,KAC/D,wBAAA,CAAyB,OAAA,CAAQ,oBAAA,EAAsB,GAAG,CAAA,IAC1D,CAAC,kBAAA,CAAmB,GAAA,EAAK,WAAW,CAAA;AAExC;AAQA,SAAS,aAAa,IAAA,EAUN;AACd,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,MAAM,iBAAA,GAAoB,UAAU,IAAA,CAAK,KAAA,IAAS,KAAK,KAAA,YAAiB,KAAA,GAAQ,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,MAAA;AAEnG,EAAA,MAAM,KAAA,GAAQ,iBAAA,IAAqB,MAAA,GAAS,MAAA,CAAO,UAAA,GAAa,WAAA,CAAY,iBAAA,EAAmB,CAAA,EAAG,CAAC,CAAA,GAAI,MAAA;AACvG,EAAA,MAAM,OAAA,GAAU,CAAA,oCAAA,EAAuC,IAAA,CAAK,MAAM,CAAA,CAAA;AAElE,EAAA,MAAM,KAAA,GAAqB;AAAA,IACzB,OAAA;AAAA,IACA,SAAA,EAAW;AAAA,MACT,MAAA,EAAQ;AAAA,QACN;AAAA,UACE,IAAA,EAAM,OAAA;AAAA,UACN,KAAA,EAAO,OAAA;AAAA,UACP,UAAA,EAAY,KAAA,GAAQ,EAAE,MAAA,EAAQ,OAAM,GAAI;AAAA;AAC1C;AACF,KACF;AAAA,IACA,OAAA,EAAS;AAAA,MACP,KAAK,IAAA,CAAK,GAAA;AAAA,MACV,QAAQ,IAAA,CAAK,MAAA;AAAA,MACb,SAAS,IAAA,CAAK,cAAA;AAAA,MACd,SAAS,IAAA,CAAK;AAAA,KAChB;AAAA,IACA,QAAA,EAAU;AAAA,MACR,QAAA,EAAU;AAAA,QACR,aAAa,IAAA,CAAK,MAAA;AAAA,QAClB,SAAS,IAAA,CAAK,eAAA;AAAA,QACd,SAAS,IAAA,CAAK,eAAA;AAAA,QACd,SAAA,EAAW,2BAAA,CAA4B,IAAA,CAAK,eAAe;AAAA;AAC7D;AACF,GACF;AAEA,EAAA,qBAAA,CAAsB,KAAA,EAAO;AAAA,IAC3B,IAAA,EAAM,CAAA,iBAAA,EAAoB,IAAA,CAAK,IAAI,CAAA,CAAA;AAAA,IACnC,OAAA,EAAS;AAAA,GACV,CAAA;AAED,EAAA,OAAO,KAAA;AACT;AAEA,SAAS,WAAA,CAAY,aAA0B,WAAA,EAAoC;AACjF,EAAA,IAAI,CAAC,WAAA,IAAe,WAAA,YAAuB,OAAA,EAAS;AAClD,IAAA,OAAO,WAAA;AAAA,EACT;AAKA,EAAA,IAAI,WAAA,YAAuB,OAAA,IAAW,WAAA,CAAY,QAAA,EAAU;AAC1D,IAAA,OAAO,WAAA;AAAA,EACT;AAEA,EAAA,OAAO,IAAI,OAAA,CAAQ,WAAA,EAAa,WAAW,CAAA;AAC7C;AAEA,SAAS,0BAAA,GAA6B;AACpC,EAAA,MAAM,SAAS,SAAA,EAAU;AACzB,EAAA,IAAI,CAAC,MAAA,EAAQ;AACX,IAAA,OAAO,EAAE,OAAA,EAAS,KAAA,EAAO,cAAA,EAAgB,KAAA,EAAO,iBAAiB,KAAA,EAAM;AAAA,EACzE;AAEA,EAAA,MAAM,EAAE,OAAA,EAAS,WAAA,EAAY,GAAI,OAAO,wBAAA,EAAyB;AACjE,EAAA,OAAO,EAAE,OAAA,EAAS,cAAA,EAAgB,YAAY,OAAA,EAAS,eAAA,EAAiB,YAAY,QAAA,EAAS;AAC/F;;;;"}
|
|
@@ -33,10 +33,16 @@ const httpContextIntegration = defineIntegration(() => {
|
|
|
33
33
|
client.getDataCollectionOptions().httpHeaders.request
|
|
34
34
|
);
|
|
35
35
|
const referer = headers["Referer"];
|
|
36
|
+
const { hostname, protocol } = WINDOW.location || {};
|
|
36
37
|
safeSetSpanJSONAttributes(span, {
|
|
37
38
|
// This attribute is used by the "Filter out events from legacy browsers and crawlers" features on the Sentry backend.
|
|
38
39
|
// Therefore, it's set on every span.
|
|
39
40
|
[USER_AGENT_ORIGINAL]: headers["User-Agent"],
|
|
41
|
+
// Likewise for the "Filter out localhost events" feature. Deliberately inlined rather than
|
|
42
|
+
// sharing the server-side helper, which costs bundle size for request headers and IPs that
|
|
43
|
+
// don't exist here. Mirrors Relay's localhost filter (relay-filter/src/localhost.rs).
|
|
44
|
+
"sentry.is_localhost": protocol === "file:" || hostname === "localhost" || hostname === "127.0.0.1" || // `location.hostname` keeps the brackets for IPv6 hosts, so this is `[::1]`, not `::1`.
|
|
45
|
+
hostname === "[::1]" || !!hostname?.endsWith(".localhost"),
|
|
40
46
|
// These attributes, we only need on the segment span (analogous to the `request` context for events)
|
|
41
47
|
...span.is_segment && {
|
|
42
48
|
// Coerce empty string to undefined so the helper's nullish check drops it,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"httpcontext.js","sources":["../../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import { _INTERNAL_filterKeyValueData, defineIntegration, safeSetSpanJSONAttributes } from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\nimport { filterCollectedUrl } from '@sentry/core';\nimport { HTTP_REQUEST_HEADER_KEY_BASE, SENTRY_OP, URL_FULL, USER_AGENT_ORIGINAL } from '@sentry/conventions/attributes';\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' as const,\n preprocessEvent(event, _hint, client) {\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 { url, headers: collectedHeaders } = getHttpRequestData();\n\n // We only filter the headers we collected ourselves, so headers the user set are left alone. Going by key\n // means we also catch these headers when `browserTracingIntegration` already put them on the event.\n const behavior = client.getDataCollectionOptions().httpHeaders.request;\n const userHeaders = Object.entries(event.request?.headers ?? {}).filter(([key]) => !(key in collectedHeaders));\n\n const headers = {\n ..._INTERNAL_filterKeyValueData(collectedHeaders, behavior),\n ...Object.fromEntries(userHeaders),\n };\n\n event.request = {\n // The URL isn't gated by `dataCollection`, same as on the server.\n url,\n ...event.request,\n ...(Object.keys(headers).length > 0 ? { headers } : { headers: undefined }),\n };\n },\n\n processSpan(span, client) {\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 // `httpHeadersToSpanAttributes` would also work here, but its cookie and array handling never runs for these\n // two headers and costs every browser bundle ~400B gzip.\n const headers = _INTERNAL_filterKeyValueData(\n reqData.headers,\n client.getDataCollectionOptions().httpHeaders.request,\n );\n const referer = headers['Referer'];\n\n safeSetSpanJSONAttributes(span, {\n // This attribute is used by the \"Filter out events from legacy browsers and crawlers\" features on the Sentry backend.\n // Therefore, it's set on every span.\n [USER_AGENT_ORIGINAL]: headers['User-Agent'],\n\n // These attributes, we only need on the segment span (analogous to the `request` context for events)\n ...(span.is_segment && {\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]: span.attributes?.[SENTRY_OP] !== 'http.client' ? filterCollectedUrl(reqData.url) : undefined,\n [`${HTTP_REQUEST_HEADER_KEY_BASE}.referer`]: referer ? [referer] : undefined,\n }),\n });\n },\n };\n});\n"],"names":[],"mappings":";;;;AASO,MAAM,sBAAA,GAAyB,kBAAkB,MAAM;AAC5D,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,eAAA,CAAgB,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ;AAEpC,MAAA,IAAI,CAAC,OAAO,SAAA,IAAa,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,EAAU;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,EAAE,GAAA,EAAK,OAAA,EAAS,gBAAA,KAAqB,kBAAA,EAAmB;AAI9D,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,wBAAA,EAAyB,CAAE,WAAA,CAAY,OAAA;AAC/D,MAAA,MAAM,cAAc,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,WAAW,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,CAAC,GAAG,CAAA,KAAM,EAAE,OAAO,gBAAA,CAAiB,CAAA;AAE7G,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,GAAG,4BAAA,CAA6B,gBAAA,EAAkB,QAAQ,CAAA;AAAA,QAC1D,GAAG,MAAA,CAAO,WAAA,CAAY,WAAW;AAAA,OACnC;AAEA,MAAA,KAAA,CAAM,OAAA,GAAU;AAAA;AAAA,QAEd,GAAA;AAAA,QACA,GAAG,KAAA,CAAM,OAAA;AAAA,QACT,GAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,EAAE,OAAA,EAAQ,GAAI,EAAE,OAAA,EAAS,MAAA;AAAU,OAC3E;AAAA,IACF,CAAA;AAAA,IAEA,WAAA,CAAY,MAAM,MAAA,EAAQ;AAExB,MAAA,IAAI,CAAC,OAAO,SAAA,IAAa,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,EAAU;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAU,kBAAA,EAAmB;AAInC,MAAA,MAAM,OAAA,GAAU,4BAAA;AAAA,QACd,OAAA,CAAQ,OAAA;AAAA,QACR,MAAA,CAAO,wBAAA,EAAyB,CAAE,WAAA,CAAY;AAAA,OAChD;AACA,MAAA,MAAM,OAAA,GAAU,QAAQ,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"httpcontext.js","sources":["../../../../../src/integrations/httpcontext.ts"],"sourcesContent":["import { _INTERNAL_filterKeyValueData, defineIntegration, safeSetSpanJSONAttributes } from '@sentry/core';\nimport { getHttpRequestData, WINDOW } from '../helpers';\nimport { filterCollectedUrl } from '@sentry/core';\nimport { HTTP_REQUEST_HEADER_KEY_BASE, SENTRY_OP, URL_FULL, USER_AGENT_ORIGINAL } from '@sentry/conventions/attributes';\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' as const,\n preprocessEvent(event, _hint, client) {\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 { url, headers: collectedHeaders } = getHttpRequestData();\n\n // We only filter the headers we collected ourselves, so headers the user set are left alone. Going by key\n // means we also catch these headers when `browserTracingIntegration` already put them on the event.\n const behavior = client.getDataCollectionOptions().httpHeaders.request;\n const userHeaders = Object.entries(event.request?.headers ?? {}).filter(([key]) => !(key in collectedHeaders));\n\n const headers = {\n ..._INTERNAL_filterKeyValueData(collectedHeaders, behavior),\n ...Object.fromEntries(userHeaders),\n };\n\n event.request = {\n // The URL isn't gated by `dataCollection`, same as on the server.\n url,\n ...event.request,\n ...(Object.keys(headers).length > 0 ? { headers } : { headers: undefined }),\n };\n },\n\n processSpan(span, client) {\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 // `httpHeadersToSpanAttributes` would also work here, but its cookie and array handling never runs for these\n // two headers and costs every browser bundle ~400B gzip.\n const headers = _INTERNAL_filterKeyValueData(\n reqData.headers,\n client.getDataCollectionOptions().httpHeaders.request,\n );\n const referer = headers['Referer'];\n const { hostname, protocol } = WINDOW.location || {};\n\n safeSetSpanJSONAttributes(span, {\n // This attribute is used by the \"Filter out events from legacy browsers and crawlers\" features on the Sentry backend.\n // Therefore, it's set on every span.\n [USER_AGENT_ORIGINAL]: headers['User-Agent'],\n\n // Likewise for the \"Filter out localhost events\" feature. Deliberately inlined rather than\n // sharing the server-side helper, which costs bundle size for request headers and IPs that\n // don't exist here. Mirrors Relay's localhost filter (relay-filter/src/localhost.rs).\n 'sentry.is_localhost':\n protocol === 'file:' ||\n hostname === 'localhost' ||\n hostname === '127.0.0.1' ||\n // `location.hostname` keeps the brackets for IPv6 hosts, so this is `[::1]`, not `::1`.\n hostname === '[::1]' ||\n !!hostname?.endsWith('.localhost'),\n\n // These attributes, we only need on the segment span (analogous to the `request` context for events)\n ...(span.is_segment && {\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]: span.attributes?.[SENTRY_OP] !== 'http.client' ? filterCollectedUrl(reqData.url) : undefined,\n [`${HTTP_REQUEST_HEADER_KEY_BASE}.referer`]: referer ? [referer] : undefined,\n }),\n });\n },\n };\n});\n"],"names":[],"mappings":";;;;AASO,MAAM,sBAAA,GAAyB,kBAAkB,MAAM;AAC5D,EAAA,OAAO;AAAA,IACL,IAAA,EAAM,aAAA;AAAA,IACN,eAAA,CAAgB,KAAA,EAAO,KAAA,EAAO,MAAA,EAAQ;AAEpC,MAAA,IAAI,CAAC,OAAO,SAAA,IAAa,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,EAAU;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,EAAE,GAAA,EAAK,OAAA,EAAS,gBAAA,KAAqB,kBAAA,EAAmB;AAI9D,MAAA,MAAM,QAAA,GAAW,MAAA,CAAO,wBAAA,EAAyB,CAAE,WAAA,CAAY,OAAA;AAC/D,MAAA,MAAM,cAAc,MAAA,CAAO,OAAA,CAAQ,KAAA,CAAM,OAAA,EAAS,WAAW,EAAE,CAAA,CAAE,MAAA,CAAO,CAAC,CAAC,GAAG,CAAA,KAAM,EAAE,OAAO,gBAAA,CAAiB,CAAA;AAE7G,MAAA,MAAM,OAAA,GAAU;AAAA,QACd,GAAG,4BAAA,CAA6B,gBAAA,EAAkB,QAAQ,CAAA;AAAA,QAC1D,GAAG,MAAA,CAAO,WAAA,CAAY,WAAW;AAAA,OACnC;AAEA,MAAA,KAAA,CAAM,OAAA,GAAU;AAAA;AAAA,QAEd,GAAA;AAAA,QACA,GAAG,KAAA,CAAM,OAAA;AAAA,QACT,GAAI,MAAA,CAAO,IAAA,CAAK,OAAO,CAAA,CAAE,MAAA,GAAS,CAAA,GAAI,EAAE,OAAA,EAAQ,GAAI,EAAE,OAAA,EAAS,MAAA;AAAU,OAC3E;AAAA,IACF,CAAA;AAAA,IAEA,WAAA,CAAY,MAAM,MAAA,EAAQ;AAExB,MAAA,IAAI,CAAC,OAAO,SAAA,IAAa,CAAC,OAAO,QAAA,IAAY,CAAC,OAAO,QAAA,EAAU;AAC7D,QAAA;AAAA,MACF;AAEA,MAAA,MAAM,UAAU,kBAAA,EAAmB;AAInC,MAAA,MAAM,OAAA,GAAU,4BAAA;AAAA,QACd,OAAA,CAAQ,OAAA;AAAA,QACR,MAAA,CAAO,wBAAA,EAAyB,CAAE,WAAA,CAAY;AAAA,OAChD;AACA,MAAA,MAAM,OAAA,GAAU,QAAQ,SAAS,CAAA;AACjC,MAAA,MAAM,EAAE,QAAA,EAAU,QAAA,EAAS,GAAI,MAAA,CAAO,YAAY,EAAC;AAEnD,MAAA,yBAAA,CAA0B,IAAA,EAAM;AAAA;AAAA;AAAA,QAG9B,CAAC,mBAAmB,GAAG,OAAA,CAAQ,YAAY,CAAA;AAAA;AAAA;AAAA;AAAA,QAK3C,qBAAA,EACE,QAAA,KAAa,OAAA,IACb,QAAA,KAAa,eACb,QAAA,KAAa,WAAA;AAAA,QAEb,aAAa,OAAA,IACb,CAAC,CAAC,QAAA,EAAU,SAAS,YAAY,CAAA;AAAA;AAAA,QAGnC,GAAI,KAAK,UAAA,IAAc;AAAA;AAAA;AAAA,UAGrB,CAAC,QAAQ,GAAG,IAAA,CAAK,UAAA,GAAa,SAAS,CAAA,KAAM,aAAA,GAAgB,kBAAA,CAAmB,OAAA,CAAQ,GAAG,CAAA,GAAI,MAAA;AAAA,UAC/F,CAAC,GAAG,4BAA4B,CAAA,QAAA,CAAU,GAAG,OAAA,GAAU,CAAC,OAAO,CAAA,GAAI;AAAA;AACrE,OACD,CAAA;AAAA,IACH;AAAA,GACF;AACF,CAAC;;;;"}
|