@sentry/browser 10.47.0 → 10.49.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.
Files changed (91) hide show
  1. package/build/npm/cjs/dev/index.js +7 -0
  2. package/build/npm/cjs/dev/index.js.map +1 -1
  3. package/build/npm/cjs/dev/integrations/spanstreaming.js +67 -0
  4. package/build/npm/cjs/dev/integrations/spanstreaming.js.map +1 -0
  5. package/build/npm/cjs/dev/integrations/view-hierarchy.js +101 -0
  6. package/build/npm/cjs/dev/integrations/view-hierarchy.js.map +1 -0
  7. package/build/npm/cjs/dev/tracing/browserTracingIntegration.js +18 -7
  8. package/build/npm/cjs/dev/tracing/browserTracingIntegration.js.map +1 -1
  9. package/build/npm/cjs/dev/tracing/request.js +45 -7
  10. package/build/npm/cjs/dev/tracing/request.js.map +1 -1
  11. package/build/npm/cjs/dev/utils/lazyLoadIntegration.js +1 -0
  12. package/build/npm/cjs/dev/utils/lazyLoadIntegration.js.map +1 -1
  13. package/build/npm/cjs/prod/index.js +7 -0
  14. package/build/npm/cjs/prod/index.js.map +1 -1
  15. package/build/npm/cjs/prod/integrations/spanstreaming.js +67 -0
  16. package/build/npm/cjs/prod/integrations/spanstreaming.js.map +1 -0
  17. package/build/npm/cjs/prod/integrations/view-hierarchy.js +101 -0
  18. package/build/npm/cjs/prod/integrations/view-hierarchy.js.map +1 -0
  19. package/build/npm/cjs/prod/tracing/browserTracingIntegration.js +18 -7
  20. package/build/npm/cjs/prod/tracing/browserTracingIntegration.js.map +1 -1
  21. package/build/npm/cjs/prod/tracing/request.js +45 -7
  22. package/build/npm/cjs/prod/tracing/request.js.map +1 -1
  23. package/build/npm/cjs/prod/utils/lazyLoadIntegration.js +1 -0
  24. package/build/npm/cjs/prod/utils/lazyLoadIntegration.js.map +1 -1
  25. package/build/npm/esm/dev/index.js +4 -2
  26. package/build/npm/esm/dev/index.js.map +1 -1
  27. package/build/npm/esm/dev/integrations/spanstreaming.js +65 -0
  28. package/build/npm/esm/dev/integrations/spanstreaming.js.map +1 -0
  29. package/build/npm/esm/dev/integrations/view-hierarchy.js +99 -0
  30. package/build/npm/esm/dev/integrations/view-hierarchy.js.map +1 -0
  31. package/build/npm/esm/dev/package.json +1 -1
  32. package/build/npm/esm/dev/tracing/browserTracingIntegration.js +20 -10
  33. package/build/npm/esm/dev/tracing/browserTracingIntegration.js.map +1 -1
  34. package/build/npm/esm/dev/tracing/request.js +46 -8
  35. package/build/npm/esm/dev/tracing/request.js.map +1 -1
  36. package/build/npm/esm/dev/utils/lazyLoadIntegration.js +1 -0
  37. package/build/npm/esm/dev/utils/lazyLoadIntegration.js.map +1 -1
  38. package/build/npm/esm/prod/index.js +4 -2
  39. package/build/npm/esm/prod/index.js.map +1 -1
  40. package/build/npm/esm/prod/integrations/spanstreaming.js +65 -0
  41. package/build/npm/esm/prod/integrations/spanstreaming.js.map +1 -0
  42. package/build/npm/esm/prod/integrations/view-hierarchy.js +99 -0
  43. package/build/npm/esm/prod/integrations/view-hierarchy.js.map +1 -0
  44. package/build/npm/esm/prod/package.json +1 -1
  45. package/build/npm/esm/prod/tracing/browserTracingIntegration.js +20 -10
  46. package/build/npm/esm/prod/tracing/browserTracingIntegration.js.map +1 -1
  47. package/build/npm/esm/prod/tracing/request.js +46 -8
  48. package/build/npm/esm/prod/tracing/request.js.map +1 -1
  49. package/build/npm/esm/prod/utils/lazyLoadIntegration.js +1 -0
  50. package/build/npm/esm/prod/utils/lazyLoadIntegration.js.map +1 -1
  51. package/build/npm/types/exports.d.ts +1 -1
  52. package/build/npm/types/exports.d.ts.map +1 -1
  53. package/build/npm/types/index.bundle.tracing.d.ts +1 -1
  54. package/build/npm/types/index.bundle.tracing.d.ts.map +1 -1
  55. package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts +1 -1
  56. package/build/npm/types/index.bundle.tracing.logs.metrics.d.ts.map +1 -1
  57. package/build/npm/types/index.bundle.tracing.replay.d.ts +1 -1
  58. package/build/npm/types/index.bundle.tracing.replay.d.ts.map +1 -1
  59. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts +1 -1
  60. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts.map +1 -1
  61. package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts +1 -1
  62. package/build/npm/types/index.bundle.tracing.replay.feedback.logs.metrics.d.ts.map +1 -1
  63. package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts +1 -1
  64. package/build/npm/types/index.bundle.tracing.replay.logs.metrics.d.ts.map +1 -1
  65. package/build/npm/types/index.d.ts +4 -2
  66. package/build/npm/types/index.d.ts.map +1 -1
  67. package/build/npm/types/integrations/spanstreaming.d.ts +2 -0
  68. package/build/npm/types/integrations/spanstreaming.d.ts.map +1 -0
  69. package/build/npm/types/integrations/view-hierarchy.d.ts +49 -0
  70. package/build/npm/types/integrations/view-hierarchy.d.ts.map +1 -0
  71. package/build/npm/types/integrations-bundle/index.instrumentlangchainembeddings.d.ts +2 -0
  72. package/build/npm/types/integrations-bundle/index.instrumentlangchainembeddings.d.ts.map +1 -0
  73. package/build/npm/types/tracing/browserTracingIntegration.d.ts +1 -0
  74. package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
  75. package/build/npm/types/tracing/request.d.ts.map +1 -1
  76. package/build/npm/types/utils/lazyLoadIntegration.d.ts +1 -1
  77. package/build/npm/types/utils/lazyLoadIntegration.d.ts.map +1 -1
  78. package/build/npm/types-ts3.8/exports.d.ts +1 -1
  79. package/build/npm/types-ts3.8/index.bundle.tracing.d.ts +1 -1
  80. package/build/npm/types-ts3.8/index.bundle.tracing.logs.metrics.d.ts +1 -1
  81. package/build/npm/types-ts3.8/index.bundle.tracing.replay.d.ts +1 -1
  82. package/build/npm/types-ts3.8/index.bundle.tracing.replay.feedback.d.ts +1 -1
  83. package/build/npm/types-ts3.8/index.bundle.tracing.replay.feedback.logs.metrics.d.ts +1 -1
  84. package/build/npm/types-ts3.8/index.bundle.tracing.replay.logs.metrics.d.ts +1 -1
  85. package/build/npm/types-ts3.8/index.d.ts +4 -2
  86. package/build/npm/types-ts3.8/integrations/spanstreaming.d.ts +2 -0
  87. package/build/npm/types-ts3.8/integrations/view-hierarchy.d.ts +49 -0
  88. package/build/npm/types-ts3.8/integrations-bundle/index.instrumentlangchainembeddings.d.ts +2 -0
  89. package/build/npm/types-ts3.8/tracing/browserTracingIntegration.d.ts +1 -0
  90. package/build/npm/types-ts3.8/utils/lazyLoadIntegration.d.ts +2 -1
  91. package/package.json +7 -7
@@ -92,7 +92,7 @@ function instrumentOutgoingRequests(client, _options) {
92
92
  });
93
93
 
94
94
  if (enableHTTPTimings) {
95
- addHTTPTimings(createdSpan);
95
+ addHTTPTimings(createdSpan, client);
96
96
  }
97
97
 
98
98
  onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });
@@ -113,7 +113,7 @@ function instrumentOutgoingRequests(client, _options) {
113
113
 
114
114
  if (createdSpan) {
115
115
  if (enableHTTPTimings) {
116
- addHTTPTimings(createdSpan);
116
+ addHTTPTimings(createdSpan, client);
117
117
  }
118
118
 
119
119
  onRequestSpanStart?.(createdSpan, {
@@ -124,26 +124,64 @@ function instrumentOutgoingRequests(client, _options) {
124
124
  }
125
125
  }
126
126
 
127
+ /**
128
+ * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.
129
+ * Same approach is used by OTel's browser fetch instrumentation:
130
+ * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}
131
+ */
132
+ const HTTP_TIMING_WAIT_MS = 300;
133
+
127
134
  /**
128
135
  * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,
129
136
  * so that when timings hit their per-browser limit they don't need to be removed.
130
137
  *
131
138
  * @param span A span that has yet to be finished, must contain `url` on data.
132
139
  */
133
- function addHTTPTimings(span) {
140
+ function addHTTPTimings(span, client) {
134
141
  const { url } = core.spanToJSON(span).data;
135
142
 
136
143
  if (!url || typeof url !== 'string') {
137
144
  return;
138
145
  }
139
146
 
140
- const cleanup = browserUtils.addPerformanceInstrumentationHandler('resource', ({ entries }) => {
147
+ // Clean up the performance observer and other resources
148
+ // We have to wait here because otherwise this cleans itself up before it is fully done.
149
+ // Default (non-streaming): just deregister the observer.
150
+ let onEntryFound = () => void setTimeout(unsubscribePerformanceObsever);
151
+
152
+ // For streamed spans, we have to artificially delay the ending of the span until we
153
+ // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.
154
+ if (core.hasSpanStreamingEnabled(client)) {
155
+ const originalEnd = span.end.bind(span);
156
+
157
+ span.end = (endTimestamp) => {
158
+ const capturedEndTimestamp = endTimestamp ?? core.timestampInSeconds();
159
+ let isEnded = false;
160
+
161
+ const endSpanAndCleanup = () => {
162
+ if (isEnded) {
163
+ return;
164
+ }
165
+ isEnded = true;
166
+ setTimeout(unsubscribePerformanceObsever);
167
+ originalEnd(capturedEndTimestamp);
168
+ clearTimeout(fallbackTimeout);
169
+ };
170
+
171
+ onEntryFound = endSpanAndCleanup;
172
+
173
+ // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no
174
+ // PerformanceResourceTiming entry arrives (e.g. cross-origin without
175
+ // Timing-Allow-Origin, or the browser didn't fire the observer in time).
176
+ const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);
177
+ };
178
+ }
179
+
180
+ const unsubscribePerformanceObsever = browserUtils.addPerformanceInstrumentationHandler('resource', ({ entries }) => {
141
181
  entries.forEach(entry => {
142
182
  if (utils.isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {
143
183
  span.setAttributes(browserUtils.resourceTimingToSpanAttributes(entry));
144
- // In the next tick, clean this handler up
145
- // We have to wait here because otherwise this cleans itself up before it is fully done
146
- setTimeout(cleanup);
184
+ onEntryFound();
147
185
  }
148
186
  });
149
187
  });
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["import type {\n Client,\n HandlerDataXhr,\n RequestHookInfo,\n ResponseHookInfo,\n SentryWrappedXMLHttpRequest,\n Span,\n} from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getLocationHref,\n getTraceData,\n hasSpansEnabled,\n instrumentFetchRequest,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanToJSON,\n startInactiveSpan,\n stringMatchesSomePattern,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n} from '@sentry/core';\nimport type { XhrHint } from '@sentry-internal/browser-utils';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry-internal/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * Flag to disable tracking of long-lived streams, like server-sent events (SSE) via fetch.\n * Do not enable this in case you have live streams or very long running streams.\n *\n * Disabled by default since it can lead to issues with streams using the `cancel()` api\n * (https://github.com/getsentry/sentry-javascript/issues/13950)\n *\n * Default: false\n */\n trackFetchStreamPerformance: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nconst responseToSpanId = new WeakMap<object, string>();\nconst spanIdToEndTimestamp = new Map<string, number>();\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n trackFetchStreamPerformance: false,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n // Keeping track of http requests, whose body payloads resolved later than the initial resolved request\n // e.g. streaming using server sent events (SSE)\n client.addEventProcessor(event => {\n if (event.type === 'transaction' && event.spans) {\n event.spans.forEach(span => {\n if (span.op === 'http.client') {\n const updatedTimestamp = spanIdToEndTimestamp.get(span.span_id);\n if (updatedTimestamp) {\n span.timestamp = updatedTimestamp / 1000;\n spanIdToEndTimestamp.delete(span.span_id);\n }\n }\n });\n }\n return event;\n });\n\n if (trackFetchStreamPerformance) {\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const span = responseToSpanId.get(handlerData.response);\n if (span && handlerData.endTimestamp) {\n spanIdToEndTimestamp.set(span, handlerData.endTimestamp);\n }\n }\n });\n }\n\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n });\n\n if (handlerData.response && handlerData.fetchData.__span) {\n responseToSpanId.set(handlerData.response, handlerData.fetchData.__span);\n }\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n const host = fullUrl ? parseUrl(fullUrl).host : undefined;\n createdSpan.setAttributes({\n 'http.url': fullUrl ? stripDataUrlContent(fullUrl) : undefined,\n 'server.address': host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url` on data.\n */\nfunction addHTTPTimings(span: Span): void {\n const { url } = spanToJSON(span).data;\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n const cleanup = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n // In the next tick, clean this handler up\n // We have to wait here because otherwise this cleans itself up before it is fully done\n setTimeout(cleanup);\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return stringMatchesSomePattern(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n stringMatchesSomePattern(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && stringMatchesSomePattern(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const hasParent = !!getActiveSpan();\n\n const span =\n shouldCreateSpanResult && hasParent\n ? startInactiveSpan({\n name: `${method} ${urlForSpanName}`,\n attributes: {\n url: stripDataUrlContent(url),\n type: 'xhr',\n 'http.method': method,\n 'http.url': fullUrl ? stripDataUrlContent(fullUrl) : undefined,\n 'server.address': parsedUrl?.host,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\n ...(parsedUrl?.search && { 'http.query': parsedUrl?.search }),\n ...(parsedUrl?.hash && { 'http.fragment': parsedUrl?.hash }),\n },\n })\n : new SentryNonRecordingSpan();\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && hasParent ? span : undefined,\n propagateTraceparent,\n );\n }\n\n const client = getClient();\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["addFetchEndInstrumentationHandler","addFetchInstrumentationHandler","instrumentFetchRequest","getFullURL","parseUrl","stripDataUrlContent","addXhrInstrumentationHandler","createHeadersSafely","spanToJSON","addPerformanceInstrumentationHandler","isPerformanceResourceTiming","resourceTimingToSpanAttributes","getLocationHref","stringMatchesSomePattern","SENTRY_XHR_DATA_KEY","hasSpansEnabled","setHttpStatus","parseXhrResponseHeaders","stripUrlQueryAndFragment","getActiveSpan","startInactiveSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","SentryNonRecordingSpan","getClient","getTraceData","baggageHeaderHasSentryValues"],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../../../../src/tracing/request.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport type {\n Client,\n HandlerDataXhr,\n RequestHookInfo,\n ResponseHookInfo,\n SentryWrappedXMLHttpRequest,\n Span,\n SpanTimeInput,\n} from '@sentry/core';\nimport {\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n getActiveSpan,\n getClient,\n getLocationHref,\n getTraceData,\n hasSpansEnabled,\n hasSpanStreamingEnabled,\n instrumentFetchRequest,\n parseUrl,\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n setHttpStatus,\n spanToJSON,\n startInactiveSpan,\n stringMatchesSomePattern,\n stripDataUrlContent,\n stripUrlQueryAndFragment,\n timestampInSeconds,\n} from '@sentry/core';\nimport type { XhrHint } from '@sentry-internal/browser-utils';\nimport {\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n parseXhrResponseHeaders,\n resourceTimingToSpanAttributes,\n SENTRY_XHR_DATA_KEY,\n} from '@sentry-internal/browser-utils';\nimport type { BrowserClient } from '../client';\nimport { baggageHeaderHasSentryValues, createHeadersSafely, getFullURL, isPerformanceResourceTiming } from './utils';\n\n/** Options for Request Instrumentation */\nexport interface RequestInstrumentationOptions {\n /**\n * List of strings and/or Regular Expressions used to determine which outgoing requests will have `sentry-trace` and `baggage`\n * headers attached.\n *\n * **Default:** If this option is not provided, tracing headers will be attached to all outgoing requests.\n * If you are using a browser SDK, by default, tracing headers will only be attached to outgoing requests to the same origin.\n *\n * **Disclaimer:** Carelessly setting this option in browser environments may result into CORS errors!\n * Only attach tracing headers to requests to the same origin, or to requests to services you can control CORS headers of.\n * Cross-origin requests, meaning requests to a different domain, for example a request to `https://api.example.com/` while you're on `https://example.com/`, take special care.\n * If you are attaching headers to cross-origin requests, make sure the backend handling the request returns a `\"Access-Control-Allow-Headers: sentry-trace, baggage\"` header to ensure your requests aren't blocked.\n *\n * If you provide a `tracePropagationTargets` array, the entries you provide will be matched against the entire URL of the outgoing request.\n * If you are using a browser SDK, the entries will also be matched against the pathname of the outgoing requests.\n * This is so you can have matchers for relative requests, for example, `/^\\/api/` if you want to trace requests to your `/api` routes on the same domain.\n *\n * If any of the two match any of the provided values, tracing headers will be attached to the outgoing request.\n * Both, the string values, and the RegExes you provide in the array will match if they partially match the URL or pathname.\n *\n * Examples:\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://same-origin.com/api/posts`:\n * - Tracing headers will be attached because the request is sent to the same origin and the regex matches the pathname \"/api/posts\".\n * - `tracePropagationTargets: [/^\\/api/]` and request to `https://different-origin.com/api/posts`:\n * - Tracing headers will not be attached because the pathname will only be compared when the request target lives on the same origin.\n * - `tracePropagationTargets: [/^\\/api/, 'https://external-api.com']` and request to `https://external-api.com/v1/data`:\n * - Tracing headers will be attached because the request URL matches the string `'https://external-api.com'`.\n */\n tracePropagationTargets?: Array<string | RegExp>;\n\n /**\n * Flag to disable patching all together for fetch requests.\n *\n * Default: true\n */\n traceFetch: boolean;\n\n /**\n * Flag to disable patching all together for xhr requests.\n *\n * Default: true\n */\n traceXHR: boolean;\n\n /**\n * Flag to disable tracking of long-lived streams, like server-sent events (SSE) via fetch.\n * Do not enable this in case you have live streams or very long running streams.\n *\n * Disabled by default since it can lead to issues with streams using the `cancel()` api\n * (https://github.com/getsentry/sentry-javascript/issues/13950)\n *\n * Default: false\n */\n trackFetchStreamPerformance: boolean;\n\n /**\n * If true, Sentry will capture http timings and add them to the corresponding http spans.\n *\n * Default: true\n */\n enableHTTPTimings: boolean;\n\n /**\n * This function will be called before creating a span for a request with the given url.\n * Return false if you don't want a span for the given url.\n *\n * Default: (url: string) => true\n */\n shouldCreateSpanForRequest?(this: void, url: string): boolean;\n\n /**\n * Is called when spans are started for outgoing requests.\n */\n onRequestSpanStart?(span: Span, requestInformation: RequestHookInfo): void;\n\n /**\n * Is called when spans end for outgoing requests, providing access to response headers.\n */\n onRequestSpanEnd?(span: Span, responseInformation: ResponseHookInfo): void;\n}\n\nconst responseToSpanId = new WeakMap<object, string>();\nconst spanIdToEndTimestamp = new Map<string, number>();\n\nexport const defaultRequestInstrumentationOptions: RequestInstrumentationOptions = {\n traceFetch: true,\n traceXHR: true,\n enableHTTPTimings: true,\n trackFetchStreamPerformance: false,\n};\n\n/** Registers span creators for xhr and fetch requests */\nexport function instrumentOutgoingRequests(client: Client, _options?: Partial<RequestInstrumentationOptions>): void {\n const {\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n tracePropagationTargets,\n onRequestSpanStart,\n onRequestSpanEnd,\n } = {\n ...defaultRequestInstrumentationOptions,\n ..._options,\n };\n\n const shouldCreateSpan =\n typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_: string) => true;\n\n const shouldAttachHeadersWithTargets = (url: string): boolean => shouldAttachHeaders(url, tracePropagationTargets);\n\n const spans: Record<string, Span> = {};\n\n const propagateTraceparent = (client as BrowserClient).getOptions().propagateTraceparent;\n\n if (traceFetch) {\n // Keeping track of http requests, whose body payloads resolved later than the initial resolved request\n // e.g. streaming using server sent events (SSE)\n client.addEventProcessor(event => {\n if (event.type === 'transaction' && event.spans) {\n event.spans.forEach(span => {\n if (span.op === 'http.client') {\n const updatedTimestamp = spanIdToEndTimestamp.get(span.span_id);\n if (updatedTimestamp) {\n span.timestamp = updatedTimestamp / 1000;\n spanIdToEndTimestamp.delete(span.span_id);\n }\n }\n });\n }\n return event;\n });\n\n if (trackFetchStreamPerformance) {\n addFetchEndInstrumentationHandler(handlerData => {\n if (handlerData.response) {\n const span = responseToSpanId.get(handlerData.response);\n if (span && handlerData.endTimestamp) {\n spanIdToEndTimestamp.set(span, handlerData.endTimestamp);\n }\n }\n });\n }\n\n addFetchInstrumentationHandler(handlerData => {\n const createdSpan = instrumentFetchRequest(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans, {\n propagateTraceparent,\n onRequestSpanEnd,\n });\n\n if (handlerData.response && handlerData.fetchData.__span) {\n responseToSpanId.set(handlerData.response, handlerData.fetchData.__span);\n }\n\n // We cannot use `window.location` in the generic fetch instrumentation,\n // but we need it for reliable `server.address` attribute.\n // so we extend this in here\n if (createdSpan) {\n const fullUrl = getFullURL(handlerData.fetchData.url);\n const host = fullUrl ? parseUrl(fullUrl).host : undefined;\n createdSpan.setAttributes({\n 'http.url': fullUrl ? stripDataUrlContent(fullUrl) : undefined,\n 'server.address': host,\n });\n\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, { headers: handlerData.headers });\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(\n handlerData,\n shouldCreateSpan,\n shouldAttachHeadersWithTargets,\n spans,\n propagateTraceparent,\n onRequestSpanEnd,\n );\n\n if (createdSpan) {\n if (enableHTTPTimings) {\n addHTTPTimings(createdSpan, client);\n }\n\n onRequestSpanStart?.(createdSpan, {\n headers: createHeadersSafely(handlerData.xhr.__sentry_xhr_v3__?.request_headers),\n });\n }\n });\n }\n}\n\n/**\n * The maximum time (ms) to wait for PerformanceResourceTiming data before ending the span.\n * Same approach is used by OTel's browser fetch instrumentation:\n * See {@link https://github.com/open-telemetry/opentelemetry-js/blob/30f94fe99339287b1e4d3c8bb90172c2523f06f4/experimental/packages/opentelemetry-instrumentation-fetch/src/fetch.ts#L352-L372}\n */\nconst HTTP_TIMING_WAIT_MS = 300;\n\n/**\n * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,\n * so that when timings hit their per-browser limit they don't need to be removed.\n *\n * @param span A span that has yet to be finished, must contain `url` on data.\n */\nfunction addHTTPTimings(span: Span, client: Client): void {\n const { url } = spanToJSON(span).data;\n\n if (!url || typeof url !== 'string') {\n return;\n }\n\n // Clean up the performance observer and other resources\n // We have to wait here because otherwise this cleans itself up before it is fully done.\n // Default (non-streaming): just deregister the observer.\n let onEntryFound = (): void => void setTimeout(unsubscribePerformanceObsever);\n\n // For streamed spans, we have to artificially delay the ending of the span until we\n // either receive the timing data, or HTTP_TIMING_WAIT_MS elapses.\n if (hasSpanStreamingEnabled(client)) {\n const originalEnd = span.end.bind(span);\n\n span.end = (endTimestamp?: SpanTimeInput) => {\n const capturedEndTimestamp = endTimestamp ?? timestampInSeconds();\n let isEnded = false;\n\n const endSpanAndCleanup = (): void => {\n if (isEnded) {\n return;\n }\n isEnded = true;\n setTimeout(unsubscribePerformanceObsever);\n originalEnd(capturedEndTimestamp);\n clearTimeout(fallbackTimeout);\n };\n\n onEntryFound = endSpanAndCleanup;\n\n // Fallback: always end the span after HTTP_TIMING_WAIT_MS even if no\n // PerformanceResourceTiming entry arrives (e.g. cross-origin without\n // Timing-Allow-Origin, or the browser didn't fire the observer in time).\n const fallbackTimeout = setTimeout(endSpanAndCleanup, HTTP_TIMING_WAIT_MS);\n };\n }\n\n const unsubscribePerformanceObsever = addPerformanceInstrumentationHandler('resource', ({ entries }) => {\n entries.forEach(entry => {\n if (isPerformanceResourceTiming(entry) && entry.name.endsWith(url)) {\n span.setAttributes(resourceTimingToSpanAttributes(entry));\n onEntryFound();\n }\n });\n });\n}\n\n/**\n * A function that determines whether to attach tracing headers to a request.\n * We only export this function for testing purposes.\n */\nexport function shouldAttachHeaders(\n targetUrl: string,\n tracePropagationTargets: (string | RegExp)[] | undefined,\n): boolean {\n // window.location.href not being defined is an edge case in the browser but we need to handle it.\n // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj\n const href = getLocationHref();\n\n if (!href) {\n // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`\n // BIG DISCLAIMER: Users can call URLs with a double slash (fetch(\"//example.com/api\")), this is a shorthand for \"send to the same protocol\",\n // so we need a to exclude those requests, because they might be cross origin.\n const isRelativeSameOriginRequest = !!targetUrl.match(/^\\/(?!\\/)/);\n if (!tracePropagationTargets) {\n return isRelativeSameOriginRequest;\n } else {\n return stringMatchesSomePattern(targetUrl, tracePropagationTargets);\n }\n } else {\n let resolvedUrl;\n let currentOrigin;\n\n // URL parsing may fail, we default to not attaching trace headers in that case.\n try {\n resolvedUrl = new URL(targetUrl, href);\n currentOrigin = new URL(href).origin;\n } catch {\n return false;\n }\n\n const isSameOriginRequest = resolvedUrl.origin === currentOrigin;\n if (!tracePropagationTargets) {\n return isSameOriginRequest;\n } else {\n return (\n stringMatchesSomePattern(resolvedUrl.toString(), tracePropagationTargets) ||\n (isSameOriginRequest && stringMatchesSomePattern(resolvedUrl.pathname, tracePropagationTargets))\n );\n }\n }\n}\n\n/**\n * Create and track xhr request spans\n *\n * @returns Span if a span was created, otherwise void.\n */\nfunction xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n propagateTraceparent?: boolean,\n onRequestSpanEnd?: RequestInstrumentationOptions['onRequestSpanEnd'],\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const { url, method } = sentryXhrData;\n\n const shouldCreateSpanResult = hasSpansEnabled() && shouldCreateSpan(url);\n\n // Handle XHR completion - clean up spans from the record\n if (handlerData.endTimestamp) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n\n if (span) {\n if (shouldCreateSpanResult && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n onRequestSpanEnd?.(span, {\n headers: createHeadersSafely(parseXhrResponseHeaders(xhr as XMLHttpRequest & SentryWrappedXMLHttpRequest)),\n error: handlerData.error,\n });\n }\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n\n return undefined;\n }\n\n const fullUrl = getFullURL(url);\n const parsedUrl = fullUrl ? parseUrl(fullUrl) : parseUrl(url);\n\n const urlForSpanName = stripDataUrlContent(stripUrlQueryAndFragment(url));\n\n const hasParent = !!getActiveSpan();\n\n const span =\n shouldCreateSpanResult && hasParent\n ? startInactiveSpan({\n name: `${method} ${urlForSpanName}`,\n attributes: {\n url: stripDataUrlContent(url),\n type: 'xhr',\n 'http.method': method,\n 'http.url': fullUrl ? stripDataUrlContent(fullUrl) : undefined,\n 'server.address': parsedUrl?.host,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\n ...(parsedUrl?.search && { 'http.query': parsedUrl?.search }),\n ...(parsedUrl?.hash && { 'http.fragment': parsedUrl?.hash }),\n },\n })\n : new SentryNonRecordingSpan();\n\n xhr.__sentry_xhr_span_id__ = span.spanContext().spanId;\n spans[xhr.__sentry_xhr_span_id__] = span;\n\n if (shouldAttachHeaders(url)) {\n addTracingHeadersToXhrRequest(\n xhr,\n // If performance is disabled (TWP) or there's no active root span (pageload/navigation/interaction),\n // we do not want to use the span as base for the trace headers,\n // which means that the headers will be generated from the scope and the sampling decision is deferred\n hasSpansEnabled() && hasParent ? span : undefined,\n propagateTraceparent,\n );\n }\n\n const client = getClient();\n if (client) {\n client.emit('beforeOutgoingRequestSpan', span, handlerData as XhrHint);\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(\n xhr: SentryWrappedXMLHttpRequest,\n span?: Span,\n propagateTraceparent?: boolean,\n): void {\n const { 'sentry-trace': sentryTrace, baggage, traceparent } = getTraceData({ span, propagateTraceparent });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage, traceparent);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n traceparentHeader: string | undefined,\n): void {\n const originalHeaders = xhr.__sentry_xhr_v3__?.request_headers;\n\n if (originalHeaders?.['sentry-trace'] || !xhr.setRequestHeader) {\n // bail if a sentry-trace header is already set\n return;\n }\n\n try {\n xhr.setRequestHeader('sentry-trace', sentryTraceHeader);\n\n if (traceparentHeader && !originalHeaders?.['traceparent']) {\n xhr.setRequestHeader('traceparent', traceparentHeader);\n }\n\n if (sentryBaggageHeader) {\n // only add our headers if\n // - no pre-existing baggage header exists\n // - or it is set and doesn't yet contain sentry values\n const originalBaggageHeader = originalHeaders?.['baggage'];\n if (!originalBaggageHeader || !baggageHeaderHasSentryValues(originalBaggageHeader)) {\n // From MDN: \"If this method is called several times with the same header, the values are merged into one single request header.\"\n // We can therefore simply set a baggage header without checking what was there before\n // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader\n xhr.setRequestHeader('baggage', sentryBaggageHeader);\n }\n }\n } catch {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n"],"names":["addFetchEndInstrumentationHandler","addFetchInstrumentationHandler","instrumentFetchRequest","getFullURL","parseUrl","stripDataUrlContent","addXhrInstrumentationHandler","createHeadersSafely","spanToJSON","hasSpanStreamingEnabled","timestampInSeconds","addPerformanceInstrumentationHandler","isPerformanceResourceTiming","resourceTimingToSpanAttributes","getLocationHref","stringMatchesSomePattern","SENTRY_XHR_DATA_KEY","hasSpansEnabled","setHttpStatus","parseXhrResponseHeaders","stripUrlQueryAndFragment","getActiveSpan","startInactiveSpan","SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN","SEMANTIC_ATTRIBUTE_SENTRY_OP","SentryNonRecordingSpan","getClient","getTraceData","baggageHeaderHasSentryValues"],"mappings":"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"}
@@ -28,6 +28,7 @@ const LAZY_LOADABLE_NAMES = [
28
28
  'instrumentGoogleGenAIClient',
29
29
  'instrumentLangGraph',
30
30
  'createLangChainCallbackHandler',
31
+ 'instrumentLangChainEmbeddings',
31
32
  ] ;
32
33
 
33
34
  const HYPHENATED_BUNDLES = {
@@ -1 +1 @@
1
- {"version":3,"file":"lazyLoadIntegration.js","sources":["../../../../../src/utils/lazyLoadIntegration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { getClient, SDK_VERSION } from '@sentry/core';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\n\n// Single source of truth: as const array provides both the runtime list and the type.\n// Bundle file names are derived: strip 'Integration' suffix, lowercase.\n// Exceptions (hyphenated bundle names) are listed in HYPHENATED_BUNDLES.\nconst LAZY_LOADABLE_NAMES = [\n 'replayIntegration',\n 'replayCanvasIntegration',\n 'feedbackIntegration',\n 'feedbackModalIntegration',\n 'feedbackScreenshotIntegration',\n 'captureConsoleIntegration',\n 'contextLinesIntegration',\n 'linkedErrorsIntegration',\n 'dedupeIntegration',\n 'extraErrorDataIntegration',\n 'graphqlClientIntegration',\n 'httpClientIntegration',\n 'reportingObserverIntegration',\n 'rewriteFramesIntegration',\n 'browserProfilingIntegration',\n 'moduleMetadataIntegration',\n 'instrumentAnthropicAiClient',\n 'instrumentOpenAiClient',\n 'instrumentGoogleGenAIClient',\n 'instrumentLangGraph',\n 'createLangChainCallbackHandler',\n] as const;\n\ntype ElementOf<T extends readonly unknown[]> = T[number];\ntype LazyLoadableIntegrationName = ElementOf<typeof LAZY_LOADABLE_NAMES>;\n\nconst HYPHENATED_BUNDLES: Partial<Record<LazyLoadableIntegrationName, string>> = {\n replayCanvasIntegration: 'replay-canvas',\n feedbackModalIntegration: 'feedback-modal',\n feedbackScreenshotIntegration: 'feedback-screenshot',\n};\n\nfunction getBundleName(name: string): string {\n return HYPHENATED_BUNDLES[name as LazyLoadableIntegrationName] || name.replace('Integration', '').toLowerCase();\n}\n\nconst WindowWithMaybeIntegration = WINDOW as {\n Sentry?: Partial<Record<LazyLoadableIntegrationName, IntegrationFn>>;\n};\n\n/**\n * Lazy load an integration from the CDN.\n * Rejects if the integration cannot be loaded.\n */\nexport async function lazyLoadIntegration(\n name: LazyLoadableIntegrationName,\n scriptNonce?: string,\n): Promise<IntegrationFn> {\n const bundle = LAZY_LOADABLE_NAMES.includes(name) ? getBundleName(name) : undefined;\n\n // `window.Sentry` is only set when using a CDN bundle, but this method can also be used via the NPM package\n const sentryOnWindow = (WindowWithMaybeIntegration.Sentry = WindowWithMaybeIntegration.Sentry || {});\n\n if (!bundle) {\n throw new Error(`Cannot lazy load integration: ${name}`);\n }\n\n // Bail if the integration already exists\n const existing = sentryOnWindow[name];\n // The `feedbackIntegration` is loaded by default in the CDN bundles,\n // so we need to differentiate between the real integration and the shim.\n // if only the shim exists, we still want to lazy load the real integration.\n if (typeof existing === 'function' && !('_isShim' in existing)) {\n return existing;\n }\n\n const url = getScriptURL(bundle);\n const script = WINDOW.document.createElement('script');\n script.src = url;\n script.crossOrigin = 'anonymous';\n script.referrerPolicy = 'strict-origin';\n\n if (scriptNonce) {\n script.setAttribute('nonce', scriptNonce);\n }\n\n const waitForLoad = new Promise<void>((resolve, reject) => {\n script.addEventListener('load', () => resolve());\n script.addEventListener('error', reject);\n });\n\n const currentScript = WINDOW.document.currentScript;\n const parent = WINDOW.document.body || WINDOW.document.head || currentScript?.parentElement;\n\n if (parent) {\n parent.appendChild(script);\n } else {\n throw new Error(`Could not find parent element to insert lazy-loaded ${name} script`);\n }\n\n try {\n await waitForLoad;\n } catch {\n throw new Error(`Error when loading integration: ${name}`);\n }\n\n const integrationFn = sentryOnWindow[name];\n\n if (typeof integrationFn !== 'function') {\n throw new Error(`Could not load integration: ${name}`);\n }\n\n return integrationFn;\n}\n\nfunction getScriptURL(bundle: string): string {\n const client = getClient<BrowserClient>();\n const baseURL = client?.getOptions()?.cdnBaseUrl || 'https://browser.sentry-cdn.com';\n\n return new URL(`/${SDK_VERSION}/${bundle}.min.js`, baseURL).toString();\n}\n"],"names":["WINDOW","getClient","SDK_VERSION"],"mappings":"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"}
1
+ {"version":3,"file":"lazyLoadIntegration.js","sources":["../../../../../src/utils/lazyLoadIntegration.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport { getClient, SDK_VERSION } from '@sentry/core';\nimport type { BrowserClient } from '../client';\nimport { WINDOW } from '../helpers';\n\n// Single source of truth: as const array provides both the runtime list and the type.\n// Bundle file names are derived: strip 'Integration' suffix, lowercase.\n// Exceptions (hyphenated bundle names) are listed in HYPHENATED_BUNDLES.\nconst LAZY_LOADABLE_NAMES = [\n 'replayIntegration',\n 'replayCanvasIntegration',\n 'feedbackIntegration',\n 'feedbackModalIntegration',\n 'feedbackScreenshotIntegration',\n 'captureConsoleIntegration',\n 'contextLinesIntegration',\n 'linkedErrorsIntegration',\n 'dedupeIntegration',\n 'extraErrorDataIntegration',\n 'graphqlClientIntegration',\n 'httpClientIntegration',\n 'reportingObserverIntegration',\n 'rewriteFramesIntegration',\n 'browserProfilingIntegration',\n 'moduleMetadataIntegration',\n 'instrumentAnthropicAiClient',\n 'instrumentOpenAiClient',\n 'instrumentGoogleGenAIClient',\n 'instrumentLangGraph',\n 'createLangChainCallbackHandler',\n 'instrumentLangChainEmbeddings',\n] as const;\n\ntype ElementOf<T extends readonly unknown[]> = T[number];\ntype LazyLoadableIntegrationName = ElementOf<typeof LAZY_LOADABLE_NAMES>;\n\nconst HYPHENATED_BUNDLES: Partial<Record<LazyLoadableIntegrationName, string>> = {\n replayCanvasIntegration: 'replay-canvas',\n feedbackModalIntegration: 'feedback-modal',\n feedbackScreenshotIntegration: 'feedback-screenshot',\n};\n\nfunction getBundleName(name: string): string {\n return HYPHENATED_BUNDLES[name as LazyLoadableIntegrationName] || name.replace('Integration', '').toLowerCase();\n}\n\nconst WindowWithMaybeIntegration = WINDOW as {\n Sentry?: Partial<Record<LazyLoadableIntegrationName, IntegrationFn>>;\n};\n\n/**\n * Lazy load an integration from the CDN.\n * Rejects if the integration cannot be loaded.\n */\nexport async function lazyLoadIntegration(\n name: LazyLoadableIntegrationName,\n scriptNonce?: string,\n): Promise<IntegrationFn> {\n const bundle = LAZY_LOADABLE_NAMES.includes(name) ? getBundleName(name) : undefined;\n\n // `window.Sentry` is only set when using a CDN bundle, but this method can also be used via the NPM package\n const sentryOnWindow = (WindowWithMaybeIntegration.Sentry = WindowWithMaybeIntegration.Sentry || {});\n\n if (!bundle) {\n throw new Error(`Cannot lazy load integration: ${name}`);\n }\n\n // Bail if the integration already exists\n const existing = sentryOnWindow[name];\n // The `feedbackIntegration` is loaded by default in the CDN bundles,\n // so we need to differentiate between the real integration and the shim.\n // if only the shim exists, we still want to lazy load the real integration.\n if (typeof existing === 'function' && !('_isShim' in existing)) {\n return existing;\n }\n\n const url = getScriptURL(bundle);\n const script = WINDOW.document.createElement('script');\n script.src = url;\n script.crossOrigin = 'anonymous';\n script.referrerPolicy = 'strict-origin';\n\n if (scriptNonce) {\n script.setAttribute('nonce', scriptNonce);\n }\n\n const waitForLoad = new Promise<void>((resolve, reject) => {\n script.addEventListener('load', () => resolve());\n script.addEventListener('error', reject);\n });\n\n const currentScript = WINDOW.document.currentScript;\n const parent = WINDOW.document.body || WINDOW.document.head || currentScript?.parentElement;\n\n if (parent) {\n parent.appendChild(script);\n } else {\n throw new Error(`Could not find parent element to insert lazy-loaded ${name} script`);\n }\n\n try {\n await waitForLoad;\n } catch {\n throw new Error(`Error when loading integration: ${name}`);\n }\n\n const integrationFn = sentryOnWindow[name];\n\n if (typeof integrationFn !== 'function') {\n throw new Error(`Could not load integration: ${name}`);\n }\n\n return integrationFn;\n}\n\nfunction getScriptURL(bundle: string): string {\n const client = getClient<BrowserClient>();\n const baseURL = client?.getOptions()?.cdnBaseUrl || 'https://browser.sentry-cdn.com';\n\n return new URL(`/${SDK_VERSION}/${bundle}.min.js`, baseURL).toString();\n}\n"],"names":["WINDOW","getClient","SDK_VERSION"],"mappings":"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"}
@@ -23,6 +23,7 @@ const reportingobserver = require('./integrations/reportingobserver.js');
23
23
  const httpclient = require('./integrations/httpclient.js');
24
24
  const contextlines = require('./integrations/contextlines.js');
25
25
  const graphqlClient = require('./integrations/graphqlClient.js');
26
+ const viewHierarchy = require('./integrations/view-hierarchy.js');
26
27
  const replay = require('@sentry-internal/replay');
27
28
  const replayCanvas = require('@sentry-internal/replay-canvas');
28
29
  const feedback = require('@sentry-internal/feedback');
@@ -31,6 +32,7 @@ const browserTracingIntegration = require('./tracing/browserTracingIntegration.j
31
32
  const browserUtils = require('@sentry-internal/browser-utils');
32
33
  const reportPageLoaded = require('./tracing/reportPageLoaded.js');
33
34
  const setActiveSpan = require('./tracing/setActiveSpan.js');
35
+ const spanstreaming = require('./integrations/spanstreaming.js');
34
36
  const offline = require('./transports/offline.js');
35
37
  const integration$1 = require('./profiling/integration.js');
36
38
  const spotlight = require('./integrations/spotlight.js');
@@ -89,6 +91,7 @@ exports.getTraceData = core.getTraceData;
89
91
  exports.inboundFiltersIntegration = core.inboundFiltersIntegration;
90
92
  exports.instrumentAnthropicAiClient = core.instrumentAnthropicAiClient;
91
93
  exports.instrumentGoogleGenAIClient = core.instrumentGoogleGenAIClient;
94
+ exports.instrumentLangChainEmbeddings = core.instrumentLangChainEmbeddings;
92
95
  exports.instrumentLangGraph = core.instrumentLangGraph;
93
96
  exports.instrumentOpenAiClient = core.instrumentOpenAiClient;
94
97
  exports.instrumentSupabaseClient = core.instrumentSupabaseClient;
@@ -127,6 +130,7 @@ exports.updateSpanName = core.updateSpanName;
127
130
  exports.withActiveSpan = core.withActiveSpan;
128
131
  exports.withIsolationScope = core.withIsolationScope;
129
132
  exports.withScope = core.withScope;
133
+ exports.withStreamedSpan = core.withStreamedSpan;
130
134
  exports.zodErrorsIntegration = core.zodErrorsIntegration;
131
135
  exports.WINDOW = helpers.WINDOW;
132
136
  exports.BrowserClient = client.BrowserClient;
@@ -159,6 +163,7 @@ exports.reportingObserverIntegration = reportingobserver.reportingObserverIntegr
159
163
  exports.httpClientIntegration = httpclient.httpClientIntegration;
160
164
  exports.contextLinesIntegration = contextlines.contextLinesIntegration;
161
165
  exports.graphqlClientIntegration = graphqlClient.graphqlClientIntegration;
166
+ exports.viewHierarchyIntegration = viewHierarchy.viewHierarchyIntegration;
162
167
  exports.getReplay = replay.getReplay;
163
168
  exports.replayIntegration = replay.replayIntegration;
164
169
  exports.replayCanvasIntegration = replayCanvas.replayCanvasIntegration;
@@ -167,11 +172,13 @@ exports.sendFeedback = feedback.sendFeedback;
167
172
  exports.defaultRequestInstrumentationOptions = request.defaultRequestInstrumentationOptions;
168
173
  exports.instrumentOutgoingRequests = request.instrumentOutgoingRequests;
169
174
  exports.browserTracingIntegration = browserTracingIntegration.browserTracingIntegration;
175
+ exports.isBotUserAgent = browserTracingIntegration.isBotUserAgent;
170
176
  exports.startBrowserTracingNavigationSpan = browserTracingIntegration.startBrowserTracingNavigationSpan;
171
177
  exports.startBrowserTracingPageLoadSpan = browserTracingIntegration.startBrowserTracingPageLoadSpan;
172
178
  exports.elementTimingIntegration = browserUtils.elementTimingIntegration;
173
179
  exports.reportPageLoaded = reportPageLoaded.reportPageLoaded;
174
180
  exports.setActiveSpanInBrowser = setActiveSpan.setActiveSpanInBrowser;
181
+ exports.spanStreamingIntegration = spanstreaming.spanStreamingIntegration;
175
182
  exports.makeBrowserOfflineTransport = offline.makeBrowserOfflineTransport;
176
183
  exports.browserProfilingIntegration = integration$1.browserProfilingIntegration;
177
184
  exports.spotlightBrowserIntegration = spotlight.spotlightBrowserIntegration;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
1
+ {"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
@@ -0,0 +1,67 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const debugBuild = require('../debug-build.js');
5
+
6
+ const spanStreamingIntegration = core.defineIntegration(() => {
7
+ return {
8
+ name: 'SpanStreaming',
9
+
10
+ beforeSetup(client) {
11
+ // If users only set spanStreamingIntegration, without traceLifecycle, we set it to "stream" for them.
12
+ // This avoids the classic double-opt-in problem we'd otherwise have in the browser SDK.
13
+ const clientOptions = client.getOptions();
14
+ if (!clientOptions.traceLifecycle) {
15
+ debugBuild.DEBUG_BUILD && core.debug.log('[SpanStreaming] setting `traceLifecycle` to "stream"');
16
+ clientOptions.traceLifecycle = 'stream';
17
+ }
18
+ },
19
+
20
+ setup(client) {
21
+ const initialMessage = 'SpanStreaming integration requires';
22
+ const fallbackMsg = 'Falling back to static trace lifecycle.';
23
+ const clientOptions = client.getOptions();
24
+
25
+ if (!core.hasSpanStreamingEnabled(client)) {
26
+ clientOptions.traceLifecycle = 'static';
27
+ debugBuild.DEBUG_BUILD && core.debug.warn(`${initialMessage} \`traceLifecycle\` to be set to "stream"! ${fallbackMsg}`);
28
+ return;
29
+ }
30
+
31
+ const beforeSendSpan = clientOptions.beforeSendSpan;
32
+ // If users misconfigure their SDK by opting into span streaming but
33
+ // using an incompatible beforeSendSpan callback, we fall back to the static trace lifecycle.
34
+ if (beforeSendSpan && !core.isStreamedBeforeSendSpanCallback(beforeSendSpan)) {
35
+ clientOptions.traceLifecycle = 'static';
36
+ debugBuild.DEBUG_BUILD &&
37
+ core.debug.warn(`${initialMessage} a beforeSendSpan callback using \`withStreamedSpan\`! ${fallbackMsg}`);
38
+ return;
39
+ }
40
+
41
+ const buffer = new core.SpanBuffer(client);
42
+
43
+ client.on('afterSpanEnd', span => {
44
+ // Negatively sampled spans must not be captured.
45
+ // This happens because OTel and we create non-recording spans for negatively sampled spans
46
+ // that go through the same life cycle as recording spans.
47
+ if (!core.spanIsSampled(span)) {
48
+ return;
49
+ }
50
+ buffer.add(core.captureSpan(span, client));
51
+ });
52
+
53
+ // In addition to capturing the span, we also flush the trace when the segment
54
+ // span ends to ensure things are sent timely. We never know when the browser
55
+ // is closed, users navigate away, etc.
56
+ client.on('afterSegmentSpanEnd', segmentSpan => {
57
+ const traceId = segmentSpan.spanContext().traceId;
58
+ setTimeout(() => {
59
+ buffer.flush(traceId);
60
+ }, 500);
61
+ });
62
+ },
63
+ };
64
+ }) ;
65
+
66
+ exports.spanStreamingIntegration = spanStreamingIntegration;
67
+ //# sourceMappingURL=spanstreaming.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spanstreaming.js","sources":["../../../../../src/integrations/spanstreaming.ts"],"sourcesContent":["import type { IntegrationFn } from '@sentry/core';\nimport {\n captureSpan,\n debug,\n defineIntegration,\n hasSpanStreamingEnabled,\n isStreamedBeforeSendSpanCallback,\n SpanBuffer,\n spanIsSampled,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\n\nexport const spanStreamingIntegration = defineIntegration(() => {\n return {\n name: 'SpanStreaming',\n\n beforeSetup(client) {\n // If users only set spanStreamingIntegration, without traceLifecycle, we set it to \"stream\" for them.\n // This avoids the classic double-opt-in problem we'd otherwise have in the browser SDK.\n const clientOptions = client.getOptions();\n if (!clientOptions.traceLifecycle) {\n DEBUG_BUILD && debug.log('[SpanStreaming] setting `traceLifecycle` to \"stream\"');\n clientOptions.traceLifecycle = 'stream';\n }\n },\n\n setup(client) {\n const initialMessage = 'SpanStreaming integration requires';\n const fallbackMsg = 'Falling back to static trace lifecycle.';\n const clientOptions = client.getOptions();\n\n if (!hasSpanStreamingEnabled(client)) {\n clientOptions.traceLifecycle = 'static';\n DEBUG_BUILD && debug.warn(`${initialMessage} \\`traceLifecycle\\` to be set to \"stream\"! ${fallbackMsg}`);\n return;\n }\n\n const beforeSendSpan = clientOptions.beforeSendSpan;\n // If users misconfigure their SDK by opting into span streaming but\n // using an incompatible beforeSendSpan callback, we fall back to the static trace lifecycle.\n if (beforeSendSpan && !isStreamedBeforeSendSpanCallback(beforeSendSpan)) {\n clientOptions.traceLifecycle = 'static';\n DEBUG_BUILD &&\n debug.warn(`${initialMessage} a beforeSendSpan callback using \\`withStreamedSpan\\`! ${fallbackMsg}`);\n return;\n }\n\n const buffer = new SpanBuffer(client);\n\n client.on('afterSpanEnd', span => {\n // Negatively sampled spans must not be captured.\n // This happens because OTel and we create non-recording spans for negatively sampled spans\n // that go through the same life cycle as recording spans.\n if (!spanIsSampled(span)) {\n return;\n }\n buffer.add(captureSpan(span, client));\n });\n\n // In addition to capturing the span, we also flush the trace when the segment\n // span ends to ensure things are sent timely. We never know when the browser\n // is closed, users navigate away, etc.\n client.on('afterSegmentSpanEnd', segmentSpan => {\n const traceId = segmentSpan.spanContext().traceId;\n setTimeout(() => {\n buffer.flush(traceId);\n }, 500);\n });\n },\n };\n}) satisfies IntegrationFn;\n"],"names":["defineIntegration","DEBUG_BUILD","debug","hasSpanStreamingEnabled","isStreamedBeforeSendSpanCallback","SpanBuffer","spanIsSampled","captureSpan"],"mappings":";;;;;MAYa,wBAAA,GAA2BA,sBAAiB,CAAC,MAAM;AAChE,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,eAAe;;AAEzB,IAAI,WAAW,CAAC,MAAM,EAAE;AACxB;AACA;AACA,MAAM,MAAM,aAAA,GAAgB,MAAM,CAAC,UAAU,EAAE;AAC/C,MAAM,IAAI,CAAC,aAAa,CAAC,cAAc,EAAE;AACzC,QAAQC,0BAAeC,UAAK,CAAC,GAAG,CAAC,sDAAsD,CAAC;AACxF,QAAQ,aAAa,CAAC,cAAA,GAAiB,QAAQ;AAC/C,MAAM;AACN,IAAI,CAAC;;AAEL,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,MAAM,cAAA,GAAiB,oCAAoC;AACjE,MAAM,MAAM,WAAA,GAAc,yCAAyC;AACnE,MAAM,MAAM,aAAA,GAAgB,MAAM,CAAC,UAAU,EAAE;;AAE/C,MAAM,IAAI,CAACC,4BAAuB,CAAC,MAAM,CAAC,EAAE;AAC5C,QAAQ,aAAa,CAAC,cAAA,GAAiB,QAAQ;AAC/C,QAAQF,0BAAeC,UAAK,CAAC,IAAI,CAAC,CAAC,EAAA,cAAA,CAAA,2CAAA,EAAA,WAAA,CAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,MAAA,cAAA,GAAA,aAAA,CAAA,cAAA;AACA;AACA;AACA,MAAA,IAAA,cAAA,IAAA,CAAAE,qCAAA,CAAA,cAAA,CAAA,EAAA;AACA,QAAA,aAAA,CAAA,cAAA,GAAA,QAAA;AACA,QAAAH,sBAAA;AACA,UAAAC,UAAA,CAAA,IAAA,CAAA,CAAA,EAAA,cAAA,CAAA,uDAAA,EAAA,WAAA,CAAA,CAAA,CAAA;AACA,QAAA;AACA,MAAA;;AAEA,MAAA,MAAA,MAAA,GAAA,IAAAG,eAAA,CAAA,MAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,cAAA,EAAA,IAAA,IAAA;AACA;AACA;AACA;AACA,QAAA,IAAA,CAAAC,kBAAA,CAAA,IAAA,CAAA,EAAA;AACA,UAAA;AACA,QAAA;AACA,QAAA,MAAA,CAAA,GAAA,CAAAC,gBAAA,CAAA,IAAA,EAAA,MAAA,CAAA,CAAA;AACA,MAAA,CAAA,CAAA;;AAEA;AACA;AACA;AACA,MAAA,MAAA,CAAA,EAAA,CAAA,qBAAA,EAAA,WAAA,IAAA;AACA,QAAA,MAAA,OAAA,GAAA,WAAA,CAAA,WAAA,EAAA,CAAA,OAAA;AACA,QAAA,UAAA,CAAA,MAAA;AACA,UAAA,MAAA,CAAA,KAAA,CAAA,OAAA,CAAA;AACA,QAAA,CAAA,EAAA,GAAA,CAAA;AACA,MAAA,CAAA,CAAA;AACA,IAAA,CAAA;AACA,GAAA;AACA,CAAA,CAAA;;;;"}
@@ -0,0 +1,101 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
+
3
+ const core = require('@sentry/core');
4
+ const helpers = require('../helpers.js');
5
+
6
+ /**
7
+ * An integration to include a view hierarchy attachment which contains the DOM.
8
+ */
9
+ const viewHierarchyIntegration = core.defineIntegration((options = {}) => {
10
+ const skipHtmlTags = ['script'];
11
+
12
+ /** Walk an element */
13
+ function walk(element, windows, depth = 0) {
14
+ if (!element) {
15
+ return;
16
+ }
17
+
18
+ // With Web Components, we need to walk into shadow DOMs
19
+ const children = 'shadowRoot' in element && element.shadowRoot ? element.shadowRoot.children : element.children;
20
+
21
+ for (const child of children) {
22
+ if (!(child instanceof HTMLElement)) {
23
+ continue;
24
+ }
25
+
26
+ const componentName = core.getComponentName(child, 1) || undefined;
27
+ const tagName = child.tagName.toLowerCase();
28
+
29
+ if (skipHtmlTags.includes(tagName)) {
30
+ continue;
31
+ }
32
+
33
+ const result = options.onElement?.({ element: child, componentName, tagName, depth }) || {};
34
+
35
+ if (result === 'skip') {
36
+ continue;
37
+ }
38
+
39
+ // Skip this element but include its children
40
+ if (result === 'children') {
41
+ walk(child, windows, depth + 1);
42
+ continue;
43
+ }
44
+
45
+ const { x, y, width, height } = child.getBoundingClientRect();
46
+
47
+ const window = {
48
+ identifier: (child.id || undefined) ,
49
+ type: componentName || tagName,
50
+ visible: true,
51
+ alpha: 1,
52
+ height,
53
+ width,
54
+ x,
55
+ y,
56
+ ...result,
57
+ };
58
+
59
+ const children = [];
60
+ window.children = children;
61
+
62
+ // Recursively walk the children
63
+ walk(child, window.children, depth + 1);
64
+
65
+ windows.push(window);
66
+ }
67
+ }
68
+
69
+ return {
70
+ name: 'ViewHierarchy',
71
+ processEvent: (event, hint) => {
72
+ // only capture for error events
73
+ if (event.type !== undefined || options.shouldAttach?.(event, hint) === false) {
74
+ return event;
75
+ }
76
+
77
+ const root = {
78
+ rendering_system: 'DOM',
79
+ positioning: 'absolute',
80
+ windows: [],
81
+ };
82
+
83
+ walk(options.rootElement?.() || helpers.WINDOW.document.body, root.windows);
84
+
85
+ const attachment = {
86
+ filename: 'view-hierarchy.json',
87
+ attachmentType: 'event.view_hierarchy',
88
+ contentType: 'application/json',
89
+ data: JSON.stringify(root),
90
+ };
91
+
92
+ hint.attachments = hint.attachments || [];
93
+ hint.attachments.push(attachment);
94
+
95
+ return event;
96
+ },
97
+ };
98
+ });
99
+
100
+ exports.viewHierarchyIntegration = viewHierarchyIntegration;
101
+ //# sourceMappingURL=view-hierarchy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view-hierarchy.js","sources":["../../../../../src/integrations/view-hierarchy.ts"],"sourcesContent":["import type { Attachment, Event, EventHint, ViewHierarchyData, ViewHierarchyWindow } from '@sentry/core';\nimport { defineIntegration, getComponentName } from '@sentry/core';\nimport { WINDOW } from '../helpers';\n\ninterface OnElementArgs {\n /**\n * The element being processed.\n */\n element: HTMLElement;\n /**\n * Lowercase tag name of the element.\n */\n tagName: string;\n /**\n * The component name of the element.\n */\n componentName?: string;\n\n /**\n * The current depth of the element in the view hierarchy. The root element will have a depth of 0.\n *\n * This allows you to limit the traversal depth for large DOM trees.\n */\n depth?: number;\n}\n\ninterface Options {\n /**\n * Whether to attach the view hierarchy to the event.\n *\n * Default: Always attach.\n */\n shouldAttach?: (event: Event, hint: EventHint) => boolean;\n\n /**\n * A function that returns the root element to start walking the DOM from.\n *\n * Default: `window.document.body`\n */\n rootElement?: () => HTMLElement | undefined;\n\n /**\n * Called for each HTMLElement as we walk the DOM.\n *\n * Return an object to include the element with any additional properties.\n * Return `skip` to exclude the element and its children.\n * Return `children` to skip the element but include its children.\n */\n onElement?: (prop: OnElementArgs) => Record<string, string | number | boolean> | 'skip' | 'children';\n}\n\n/**\n * An integration to include a view hierarchy attachment which contains the DOM.\n */\nexport const viewHierarchyIntegration = defineIntegration((options: Options = {}) => {\n const skipHtmlTags = ['script'];\n\n /** Walk an element */\n function walk(element: HTMLElement, windows: ViewHierarchyWindow[], depth = 0): void {\n if (!element) {\n return;\n }\n\n // With Web Components, we need to walk into shadow DOMs\n const children = 'shadowRoot' in element && element.shadowRoot ? element.shadowRoot.children : element.children;\n\n for (const child of children) {\n if (!(child instanceof HTMLElement)) {\n continue;\n }\n\n const componentName = getComponentName(child, 1) || undefined;\n const tagName = child.tagName.toLowerCase();\n\n if (skipHtmlTags.includes(tagName)) {\n continue;\n }\n\n const result = options.onElement?.({ element: child, componentName, tagName, depth }) || {};\n\n if (result === 'skip') {\n continue;\n }\n\n // Skip this element but include its children\n if (result === 'children') {\n walk(child, windows, depth + 1);\n continue;\n }\n\n const { x, y, width, height } = child.getBoundingClientRect();\n\n const window: ViewHierarchyWindow = {\n identifier: (child.id || undefined) as string,\n type: componentName || tagName,\n visible: true,\n alpha: 1,\n height,\n width,\n x,\n y,\n ...result,\n };\n\n const children: ViewHierarchyWindow[] = [];\n window.children = children;\n\n // Recursively walk the children\n walk(child, window.children, depth + 1);\n\n windows.push(window);\n }\n }\n\n return {\n name: 'ViewHierarchy',\n processEvent: (event, hint) => {\n // only capture for error events\n if (event.type !== undefined || options.shouldAttach?.(event, hint) === false) {\n return event;\n }\n\n const root: ViewHierarchyData = {\n rendering_system: 'DOM',\n positioning: 'absolute',\n windows: [],\n };\n\n walk(options.rootElement?.() || WINDOW.document.body, root.windows);\n\n const attachment: Attachment = {\n filename: 'view-hierarchy.json',\n attachmentType: 'event.view_hierarchy',\n contentType: 'application/json',\n data: JSON.stringify(root),\n };\n\n hint.attachments = hint.attachments || [];\n hint.attachments.push(attachment);\n\n return event;\n },\n };\n});\n"],"names":["defineIntegration","getComponentName","WINDOW"],"mappings":"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"}
@@ -18,7 +18,7 @@ const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';
18
18
  const BOT_USER_AGENT_RE =
19
19
  /Googlebot|Google-InspectionTool|Storebot-Google|Bingbot|Slurp|DuckDuckBot|Baiduspider|YandexBot|Facebot|facebookexternalhit|LinkedInBot|Twitterbot|Applebot/i;
20
20
 
21
- function _isBotUserAgent() {
21
+ function isBotUserAgent() {
22
22
  const nav = helpers.WINDOW.navigator ;
23
23
  if (!nav?.userAgent) {
24
24
  return false;
@@ -104,7 +104,7 @@ const browserTracingIntegration = ((options = {}) => {
104
104
  ...options,
105
105
  };
106
106
 
107
- const _isBot = _isBotUserAgent();
107
+ const _isBot = isBotUserAgent();
108
108
 
109
109
  let _collectWebVitals;
110
110
  let lastInteractionTimestamp;
@@ -152,11 +152,13 @@ const browserTracingIntegration = ((options = {}) => {
152
152
  // This will generally always be defined here, because it is set in `setup()` of the integration
153
153
  // but technically, it is optional, so we guard here to be extra safe
154
154
  _collectWebVitals?.();
155
+ const spanStreamingEnabled = core.hasSpanStreamingEnabled(client);
155
156
  browserUtils.addPerformanceEntries(span, {
156
- recordClsOnPageloadSpan: !enableStandaloneClsSpans,
157
- recordLcpOnPageloadSpan: !enableStandaloneLcpSpans,
157
+ recordClsOnPageloadSpan: !spanStreamingEnabled && !enableStandaloneClsSpans,
158
+ recordLcpOnPageloadSpan: !spanStreamingEnabled && !enableStandaloneLcpSpans,
158
159
  ignoreResourceSpans,
159
160
  ignorePerformanceApiSpans,
161
+ spanStreamingEnabled,
160
162
  });
161
163
  setActiveIdleSpan(client, undefined);
162
164
 
@@ -213,13 +215,21 @@ const browserTracingIntegration = ((options = {}) => {
213
215
 
214
216
  core.registerSpanErrorInstrumentation();
215
217
 
218
+ const spanStreamingEnabled = core.hasSpanStreamingEnabled(client);
219
+
216
220
  _collectWebVitals = browserUtils.startTrackingWebVitals({
217
- recordClsStandaloneSpans: enableStandaloneClsSpans || false,
218
- recordLcpStandaloneSpans: enableStandaloneLcpSpans || false,
221
+ recordClsStandaloneSpans: spanStreamingEnabled ? undefined : enableStandaloneClsSpans || false,
222
+ recordLcpStandaloneSpans: spanStreamingEnabled ? undefined : enableStandaloneLcpSpans || false,
219
223
  client,
220
224
  });
221
225
 
222
- if (enableInp) {
226
+ if (spanStreamingEnabled) {
227
+ browserUtils.trackLcpAsSpan(client);
228
+ browserUtils.trackClsAsSpan(client);
229
+ if (enableInp) {
230
+ browserUtils.trackInpAsSpan();
231
+ }
232
+ } else if (enableInp) {
223
233
  browserUtils.startTrackingINP();
224
234
  }
225
235
 
@@ -610,6 +620,7 @@ exports.BROWSER_TRACING_INTEGRATION_ID = BROWSER_TRACING_INTEGRATION_ID;
610
620
  exports.browserTracingIntegration = browserTracingIntegration;
611
621
  exports.getMetaContent = getMetaContent;
612
622
  exports.getServerTiming = getServerTiming;
623
+ exports.isBotUserAgent = isBotUserAgent;
613
624
  exports.startBrowserTracingNavigationSpan = startBrowserTracingNavigationSpan;
614
625
  exports.startBrowserTracingPageLoadSpan = startBrowserTracingPageLoadSpan;
615
626
  //# sourceMappingURL=browserTracingIntegration.js.map