@sentry/browser 8.54.0 → 9.0.0-alpha.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 (152) hide show
  1. package/build/npm/cjs/client.js +36 -28
  2. package/build/npm/cjs/client.js.map +1 -1
  3. package/build/npm/cjs/debug-build.js +1 -1
  4. package/build/npm/cjs/eventbuilder.js +8 -8
  5. package/build/npm/cjs/eventbuilder.js.map +1 -1
  6. package/build/npm/cjs/feedbackAsync.js +1 -1
  7. package/build/npm/cjs/feedbackSync.js +1 -1
  8. package/build/npm/cjs/helpers.js +3 -3
  9. package/build/npm/cjs/helpers.js.map +1 -1
  10. package/build/npm/cjs/index.js +1 -8
  11. package/build/npm/cjs/index.js.map +1 -1
  12. package/build/npm/cjs/integrations/breadcrumbs.js +15 -10
  13. package/build/npm/cjs/integrations/breadcrumbs.js.map +1 -1
  14. package/build/npm/cjs/integrations/browserapierrors.js +4 -5
  15. package/build/npm/cjs/integrations/browserapierrors.js.map +1 -1
  16. package/build/npm/cjs/integrations/browsersession.js +1 -1
  17. package/build/npm/cjs/integrations/contextlines.js +4 -4
  18. package/build/npm/cjs/integrations/contextlines.js.map +1 -1
  19. package/build/npm/cjs/integrations/featureFlags/featureFlagsIntegration.js +1 -1
  20. package/build/npm/cjs/integrations/featureFlags/launchdarkly/integration.js +1 -1
  21. package/build/npm/cjs/integrations/featureFlags/openfeature/integration.js +1 -1
  22. package/build/npm/cjs/integrations/featureFlags/unleash/integration.js +1 -1
  23. package/build/npm/cjs/integrations/globalhandlers.js +3 -3
  24. package/build/npm/cjs/integrations/globalhandlers.js.map +1 -1
  25. package/build/npm/cjs/integrations/httpclient.js +4 -4
  26. package/build/npm/cjs/integrations/httpclient.js.map +1 -1
  27. package/build/npm/cjs/integrations/httpcontext.js +8 -4
  28. package/build/npm/cjs/integrations/httpcontext.js.map +1 -1
  29. package/build/npm/cjs/integrations/linkederrors.js +1 -1
  30. package/build/npm/cjs/integrations/reportingobserver.js +1 -1
  31. package/build/npm/cjs/integrations/spotlight.js +2 -2
  32. package/build/npm/cjs/integrations/spotlight.js.map +1 -1
  33. package/build/npm/cjs/profiling/integration.js +5 -5
  34. package/build/npm/cjs/profiling/integration.js.map +1 -1
  35. package/build/npm/cjs/profiling/startProfileForSpan.js +1 -1
  36. package/build/npm/cjs/profiling/utils.js +16 -16
  37. package/build/npm/cjs/profiling/utils.js.map +1 -1
  38. package/build/npm/cjs/sdk.js +30 -41
  39. package/build/npm/cjs/sdk.js.map +1 -1
  40. package/build/npm/cjs/stack-parsers.js +1 -1
  41. package/build/npm/cjs/stack-parsers.js.map +1 -1
  42. package/build/npm/cjs/tracing/backgroundtab.js +2 -2
  43. package/build/npm/cjs/tracing/backgroundtab.js.map +1 -1
  44. package/build/npm/cjs/tracing/browserTracingIntegration.js +68 -56
  45. package/build/npm/cjs/tracing/browserTracingIntegration.js.map +1 -1
  46. package/build/npm/cjs/tracing/request.js +40 -8
  47. package/build/npm/cjs/tracing/request.js.map +1 -1
  48. package/build/npm/cjs/transports/fetch.js +1 -1
  49. package/build/npm/cjs/transports/offline.js +1 -1
  50. package/build/npm/cjs/userfeedback.js +7 -8
  51. package/build/npm/cjs/userfeedback.js.map +1 -1
  52. package/build/npm/cjs/utils/featureFlags.js +1 -1
  53. package/build/npm/cjs/utils/featureFlags.js.map +1 -1
  54. package/build/npm/cjs/utils/lazyLoadIntegration.js +4 -7
  55. package/build/npm/cjs/utils/lazyLoadIntegration.js.map +1 -1
  56. package/build/npm/esm/client.js +36 -28
  57. package/build/npm/esm/client.js.map +1 -1
  58. package/build/npm/esm/eventbuilder.js +7 -7
  59. package/build/npm/esm/eventbuilder.js.map +1 -1
  60. package/build/npm/esm/helpers.js +2 -2
  61. package/build/npm/esm/helpers.js.map +1 -1
  62. package/build/npm/esm/index.js +2 -3
  63. package/build/npm/esm/index.js.map +1 -1
  64. package/build/npm/esm/integrations/breadcrumbs.js +14 -9
  65. package/build/npm/esm/integrations/breadcrumbs.js.map +1 -1
  66. package/build/npm/esm/integrations/browserapierrors.js +3 -4
  67. package/build/npm/esm/integrations/browserapierrors.js.map +1 -1
  68. package/build/npm/esm/integrations/contextlines.js +3 -3
  69. package/build/npm/esm/integrations/contextlines.js.map +1 -1
  70. package/build/npm/esm/integrations/globalhandlers.js +2 -2
  71. package/build/npm/esm/integrations/globalhandlers.js.map +1 -1
  72. package/build/npm/esm/integrations/httpclient.js +3 -3
  73. package/build/npm/esm/integrations/httpclient.js.map +1 -1
  74. package/build/npm/esm/integrations/httpcontext.js +8 -4
  75. package/build/npm/esm/integrations/httpcontext.js.map +1 -1
  76. package/build/npm/esm/integrations/spotlight.js +1 -1
  77. package/build/npm/esm/integrations/spotlight.js.map +1 -1
  78. package/build/npm/esm/package.json +1 -1
  79. package/build/npm/esm/profiling/integration.js +4 -4
  80. package/build/npm/esm/profiling/integration.js.map +1 -1
  81. package/build/npm/esm/profiling/utils.js +15 -15
  82. package/build/npm/esm/profiling/utils.js.map +1 -1
  83. package/build/npm/esm/sdk.js +30 -41
  84. package/build/npm/esm/sdk.js.map +1 -1
  85. package/build/npm/esm/stack-parsers.js.map +1 -1
  86. package/build/npm/esm/tracing/backgroundtab.js +1 -1
  87. package/build/npm/esm/tracing/backgroundtab.js.map +1 -1
  88. package/build/npm/esm/tracing/browserTracingIntegration.js +68 -56
  89. package/build/npm/esm/tracing/browserTracingIntegration.js.map +1 -1
  90. package/build/npm/esm/tracing/request.js +40 -9
  91. package/build/npm/esm/tracing/request.js.map +1 -1
  92. package/build/npm/esm/userfeedback.js +6 -7
  93. package/build/npm/esm/userfeedback.js.map +1 -1
  94. package/build/npm/esm/utils/featureFlags.js.map +1 -1
  95. package/build/npm/esm/utils/lazyLoadIntegration.js +3 -6
  96. package/build/npm/esm/utils/lazyLoadIntegration.js.map +1 -1
  97. package/build/npm/types/client.d.ts +4 -10
  98. package/build/npm/types/client.d.ts.map +1 -1
  99. package/build/npm/types/exports.d.ts +3 -4
  100. package/build/npm/types/exports.d.ts.map +1 -1
  101. package/build/npm/types/helpers.d.ts +26 -1
  102. package/build/npm/types/helpers.d.ts.map +1 -1
  103. package/build/npm/types/index.bundle.d.ts +2 -2
  104. package/build/npm/types/index.bundle.d.ts.map +1 -1
  105. package/build/npm/types/index.bundle.feedback.d.ts +2 -2
  106. package/build/npm/types/index.bundle.feedback.d.ts.map +1 -1
  107. package/build/npm/types/index.bundle.replay.d.ts +2 -2
  108. package/build/npm/types/index.bundle.replay.d.ts.map +1 -1
  109. package/build/npm/types/index.bundle.tracing.d.ts +0 -1
  110. package/build/npm/types/index.bundle.tracing.d.ts.map +1 -1
  111. package/build/npm/types/index.bundle.tracing.replay.d.ts +0 -1
  112. package/build/npm/types/index.bundle.tracing.replay.d.ts.map +1 -1
  113. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts +0 -1
  114. package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts.map +1 -1
  115. package/build/npm/types/index.d.ts +2 -3
  116. package/build/npm/types/index.d.ts.map +1 -1
  117. package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
  118. package/build/npm/types/integrations-bundle/index.debug.d.ts +0 -1
  119. package/build/npm/types/integrations-bundle/index.debug.d.ts.map +1 -1
  120. package/build/npm/types/sdk.d.ts +4 -36
  121. package/build/npm/types/sdk.d.ts.map +1 -1
  122. package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
  123. package/build/npm/types/tracing/request.d.ts +10 -0
  124. package/build/npm/types/tracing/request.d.ts.map +1 -1
  125. package/build/npm/types/userfeedback.d.ts.map +1 -1
  126. package/build/npm/types/utils/lazyLoadIntegration.d.ts +0 -2
  127. package/build/npm/types/utils/lazyLoadIntegration.d.ts.map +1 -1
  128. package/build/npm/types-ts3.8/client.d.ts +4 -10
  129. package/build/npm/types-ts3.8/exports.d.ts +3 -4
  130. package/build/npm/types-ts3.8/helpers.d.ts +26 -1
  131. package/build/npm/types-ts3.8/index.bundle.d.ts +2 -2
  132. package/build/npm/types-ts3.8/index.bundle.feedback.d.ts +2 -2
  133. package/build/npm/types-ts3.8/index.bundle.replay.d.ts +2 -2
  134. package/build/npm/types-ts3.8/index.bundle.tracing.d.ts +0 -1
  135. package/build/npm/types-ts3.8/index.bundle.tracing.replay.d.ts +0 -1
  136. package/build/npm/types-ts3.8/index.bundle.tracing.replay.feedback.d.ts +0 -1
  137. package/build/npm/types-ts3.8/index.d.ts +2 -3
  138. package/build/npm/types-ts3.8/integrations-bundle/index.debug.d.ts +0 -1
  139. package/build/npm/types-ts3.8/sdk.d.ts +4 -36
  140. package/build/npm/types-ts3.8/tracing/request.d.ts +10 -0
  141. package/build/npm/types-ts3.8/utils/lazyLoadIntegration.d.ts +0 -2
  142. package/package.json +9 -9
  143. package/build/npm/cjs/metrics.js +0 -79
  144. package/build/npm/cjs/metrics.js.map +0 -1
  145. package/build/npm/esm/metrics.js +0 -77
  146. package/build/npm/esm/metrics.js.map +0 -1
  147. package/build/npm/types/integrations-bundle/index.sessiontiming.d.ts +0 -2
  148. package/build/npm/types/integrations-bundle/index.sessiontiming.d.ts.map +0 -1
  149. package/build/npm/types/metrics.d.ts +0 -8
  150. package/build/npm/types/metrics.d.ts.map +0 -1
  151. package/build/npm/types-ts3.8/integrations-bundle/index.sessiontiming.d.ts +0 -2
  152. package/build/npm/types-ts3.8/metrics.d.ts +0 -8
@@ -1,5 +1,5 @@
1
1
  import { startTrackingWebVitals, startTrackingINP, startTrackingLongAnimationFrames, startTrackingLongTasks, startTrackingInteractions, addHistoryInstrumentationHandler, registerInpInteractionListener, addPerformanceEntries } from '@sentry-internal/browser-utils';
2
- import { TRACING_DEFAULTS, registerSpanErrorInstrumentation, GLOBAL_OBJ, getClient, propagationContextFromHeaders, getCurrentScope, spanToJSON, getRootSpan, spanIsSampled, getDynamicSamplingContextFromSpan, browserPerformanceTimeOrigin, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, getActiveSpan, getIsolationScope, generateTraceId, getDomElement, startIdleSpan, logger, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '@sentry/core';
2
+ import { TRACING_DEFAULTS, registerSpanErrorInstrumentation, GLOBAL_OBJ, getLocationHref, getClient, getIsolationScope, generateTraceId, getCurrentScope, propagationContextFromHeaders, browserPerformanceTimeOrigin, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, startIdleSpan, spanIsSampled, getDynamicSamplingContextFromSpan, spanToJSON, logger, addNonEnumerableProperty, SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON } from '@sentry/core';
3
3
  import { DEBUG_BUILD } from '../debug-build.js';
4
4
  import { WINDOW } from '../helpers.js';
5
5
  import { registerBackgroundTabDetection } from './backgroundtab.js';
@@ -31,6 +31,12 @@ const DEFAULT_BROWSER_TRACING_OPTIONS = {
31
31
  * We explicitly export the proper type here, as this has to be extended in some cases.
32
32
  */
33
33
  const browserTracingIntegration = ((_options = {}) => {
34
+ /**
35
+ * This is just a small wrapper that makes `document` optional.
36
+ * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.
37
+ */
38
+ const optionalWindowDocument = WINDOW.document ;
39
+
34
40
  registerSpanErrorInstrumentation();
35
41
 
36
42
  const {
@@ -110,33 +116,47 @@ const browserTracingIntegration = ((_options = {}) => {
110
116
  beforeSpanEnd: span => {
111
117
  _collectWebVitals();
112
118
  addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans });
119
+ setActiveIdleSpan(client, undefined);
120
+
121
+ // A trace should stay consistent over the entire timespan of one route - even after the pageload/navigation ended.
122
+ // Only when another navigation happens, we want to create a new trace.
123
+ // This way, e.g. errors that occur after the pageload span ended are still associated to the pageload trace.
124
+ const scope = getCurrentScope();
125
+ const oldPropagationContext = scope.getPropagationContext();
126
+
127
+ scope.setPropagationContext({
128
+ ...oldPropagationContext,
129
+ traceId: idleSpan.spanContext().traceId,
130
+ sampled: spanIsSampled(idleSpan),
131
+ dsc: getDynamicSamplingContextFromSpan(span),
132
+ });
113
133
  },
114
134
  });
135
+ setActiveIdleSpan(client, idleSpan);
115
136
 
116
137
  function emitFinish() {
117
- if (['interactive', 'complete'].includes(WINDOW.document.readyState)) {
138
+ if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {
118
139
  client.emit('idleSpanEnableAutoFinish', idleSpan);
119
140
  }
120
141
  }
121
142
 
122
- if (isPageloadTransaction && WINDOW.document) {
123
- WINDOW.document.addEventListener('readystatechange', () => {
143
+ if (isPageloadTransaction && optionalWindowDocument) {
144
+ optionalWindowDocument.addEventListener('readystatechange', () => {
124
145
  emitFinish();
125
146
  });
126
147
 
127
148
  emitFinish();
128
149
  }
129
-
130
- return idleSpan;
131
150
  }
132
151
 
133
152
  return {
134
153
  name: BROWSER_TRACING_INTEGRATION_ID,
135
154
  afterAllSetup(client) {
136
- let activeSpan;
137
- let startingUrl = WINDOW.location && WINDOW.location.href;
155
+ let startingUrl = getLocationHref();
138
156
 
139
157
  function maybeEndActiveSpan() {
158
+ const activeSpan = getActiveIdleSpan(client);
159
+
140
160
  if (activeSpan && !spanToJSON(activeSpan).timestamp) {
141
161
  DEBUG_BUILD && logger.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);
142
162
  // If there's an open active span, we need to finish it before creating an new one.
@@ -151,7 +171,10 @@ const browserTracingIntegration = ((_options = {}) => {
151
171
 
152
172
  maybeEndActiveSpan();
153
173
 
154
- activeSpan = _createRouteSpan(client, {
174
+ getIsolationScope().setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });
175
+ getCurrentScope().setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });
176
+
177
+ _createRouteSpan(client, {
155
178
  op: 'navigation',
156
179
  ...startSpanOptions,
157
180
  });
@@ -169,39 +192,19 @@ const browserTracingIntegration = ((_options = {}) => {
169
192
  const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);
170
193
  getCurrentScope().setPropagationContext(propagationContext);
171
194
 
172
- activeSpan = _createRouteSpan(client, {
195
+ _createRouteSpan(client, {
173
196
  op: 'pageload',
174
197
  ...startSpanOptions,
175
198
  });
176
199
  });
177
200
 
178
- // A trace should to stay the consistent over the entire time span of one route.
179
- // Therefore, when the initial pageload or navigation root span ends, we update the
180
- // scope's propagation context to keep span-specific attributes like the `sampled` decision and
181
- // the dynamic sampling context valid, even after the root span has ended.
182
- // This ensures that the trace data is consistent for the entire duration of the route.
183
- client.on('spanEnd', span => {
184
- const op = spanToJSON(span).op;
185
- if (span !== getRootSpan(span) || (op !== 'navigation' && op !== 'pageload')) {
186
- return;
187
- }
188
-
189
- const scope = getCurrentScope();
190
- const oldPropagationContext = scope.getPropagationContext();
191
-
192
- scope.setPropagationContext({
193
- ...oldPropagationContext,
194
- sampled: oldPropagationContext.sampled !== undefined ? oldPropagationContext.sampled : spanIsSampled(span),
195
- dsc: oldPropagationContext.dsc || getDynamicSamplingContextFromSpan(span),
196
- });
197
- });
198
-
199
201
  if (WINDOW.location) {
200
202
  if (instrumentPageLoad) {
203
+ const origin = browserPerformanceTimeOrigin();
201
204
  startBrowserTracingPageLoadSpan(client, {
202
205
  name: WINDOW.location.pathname,
203
206
  // pageload should always start at timeOrigin (and needs to be in s, not ms)
204
- startTime: browserPerformanceTimeOrigin ? browserPerformanceTimeOrigin / 1000 : undefined,
207
+ startTime: origin ? origin / 1000 : undefined,
205
208
  attributes: {
206
209
  [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',
207
210
  [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.pageload.browser',
@@ -220,7 +223,7 @@ const browserTracingIntegration = ((_options = {}) => {
220
223
  * only be caused in certain development environments where the usage of a hot module reloader is causing
221
224
  * errors.
222
225
  */
223
- if (from === undefined && startingUrl && startingUrl.indexOf(to) !== -1) {
226
+ if (from === undefined && startingUrl?.indexOf(to) !== -1) {
224
227
  startingUrl = undefined;
225
228
  return;
226
229
  }
@@ -244,7 +247,7 @@ const browserTracingIntegration = ((_options = {}) => {
244
247
  }
245
248
 
246
249
  if (enableInteractions) {
247
- registerInteractionListener(idleTimeout, finalTimeout, childSpanTimeout, latestRoute);
250
+ registerInteractionListener(client, idleTimeout, finalTimeout, childSpanTimeout, latestRoute);
248
251
  }
249
252
 
250
253
  if (enableInp) {
@@ -276,12 +279,9 @@ function startBrowserTracingPageLoadSpan(
276
279
  traceOptions,
277
280
  ) {
278
281
  client.emit('startPageLoadSpan', spanOptions, traceOptions);
279
-
280
282
  getCurrentScope().setTransactionName(spanOptions.name);
281
283
 
282
- const span = getActiveSpan();
283
- const op = span && spanToJSON(span).op;
284
- return op === 'pageload' ? span : undefined;
284
+ return getActiveIdleSpan(client);
285
285
  }
286
286
 
287
287
  /**
@@ -289,44 +289,46 @@ function startBrowserTracingPageLoadSpan(
289
289
  * This will only do something if a browser tracing integration has been setup.
290
290
  */
291
291
  function startBrowserTracingNavigationSpan(client, spanOptions) {
292
- getIsolationScope().setPropagationContext({ traceId: generateTraceId() });
293
- getCurrentScope().setPropagationContext({ traceId: generateTraceId() });
294
-
295
292
  client.emit('startNavigationSpan', spanOptions);
296
293
 
297
294
  getCurrentScope().setTransactionName(spanOptions.name);
298
295
 
299
- const span = getActiveSpan();
300
- const op = span && spanToJSON(span).op;
301
- return op === 'navigation' ? span : undefined;
296
+ return getActiveIdleSpan(client);
302
297
  }
303
298
 
304
299
  /** Returns the value of a meta tag */
305
300
  function getMetaContent(metaName) {
306
- // Can't specify generic to `getDomElement` because tracing can be used
307
- // in a variety of environments, have to disable `no-unsafe-member-access`
308
- // as a result.
309
- // eslint-disable-next-line deprecation/deprecation
310
- const metaTag = getDomElement(`meta[name=${metaName}]`);
311
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
312
- return metaTag ? metaTag.getAttribute('content') : undefined;
301
+ /**
302
+ * This is just a small wrapper that makes `document` optional.
303
+ * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.
304
+ */
305
+ const optionalWindowDocument = WINDOW.document ;
306
+
307
+ const metaTag = optionalWindowDocument?.querySelector(`meta[name=${metaName}]`);
308
+ return metaTag?.getAttribute('content') || undefined;
313
309
  }
314
310
 
315
311
  /** Start listener for interaction transactions */
316
312
  function registerInteractionListener(
313
+ client,
317
314
  idleTimeout,
318
315
  finalTimeout,
319
316
  childSpanTimeout,
320
317
  latestRoute,
321
318
  ) {
319
+ /**
320
+ * This is just a small wrapper that makes `document` optional.
321
+ * We want to be extra-safe and always check that this exists, to ensure weird environments do not blow up.
322
+ */
323
+ const optionalWindowDocument = WINDOW.document ;
324
+
322
325
  let inflightInteractionSpan;
323
326
  const registerInteractionTransaction = () => {
324
327
  const op = 'ui.action.click';
325
328
 
326
- const activeSpan = getActiveSpan();
327
- const rootSpan = activeSpan && getRootSpan(activeSpan);
328
- if (rootSpan) {
329
- const currentRootSpanOp = spanToJSON(rootSpan).op;
329
+ const activeIdleSpan = getActiveIdleSpan(client);
330
+ if (activeIdleSpan) {
331
+ const currentRootSpanOp = spanToJSON(activeIdleSpan).op;
330
332
  if (['navigation', 'pageload'].includes(currentRootSpanOp )) {
331
333
  DEBUG_BUILD &&
332
334
  logger.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);
@@ -361,10 +363,20 @@ function registerInteractionListener(
361
363
  );
362
364
  };
363
365
 
364
- if (WINDOW.document) {
366
+ if (optionalWindowDocument) {
365
367
  addEventListener('click', registerInteractionTransaction, { once: false, capture: true });
366
368
  }
367
369
  }
368
370
 
371
+ // We store the active idle span on the client object, so we can access it from exported functions
372
+ const ACTIVE_IDLE_SPAN_PROPERTY = '_sentry_idleSpan';
373
+ function getActiveIdleSpan(client) {
374
+ return (client )[ACTIVE_IDLE_SPAN_PROPERTY];
375
+ }
376
+
377
+ function setActiveIdleSpan(client, span) {
378
+ addNonEnumerableProperty(client, ACTIVE_IDLE_SPAN_PROPERTY, span);
379
+ }
380
+
369
381
  export { BROWSER_TRACING_INTEGRATION_ID, browserTracingIntegration, getMetaContent, startBrowserTracingNavigationSpan, startBrowserTracingPageLoadSpan };
370
382
  //# sourceMappingURL=browserTracingIntegration.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"browserTracingIntegration.js","sources":["../../../../src/tracing/browserTracingIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport {\n addHistoryInstrumentationHandler,\n addPerformanceEntries,\n registerInpInteractionListener,\n startTrackingINP,\n startTrackingInteractions,\n startTrackingLongAnimationFrames,\n startTrackingLongTasks,\n startTrackingWebVitals,\n} from '@sentry-internal/browser-utils';\nimport type { Client, IntegrationFn, Span, StartSpanOptions, TransactionSource } from '@sentry/core';\nimport {\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n TRACING_DEFAULTS,\n browserPerformanceTimeOrigin,\n generateTraceId,\n getActiveSpan,\n getClient,\n getCurrentScope,\n getDomElement,\n getDynamicSamplingContextFromSpan,\n getIsolationScope,\n getRootSpan,\n logger,\n propagationContextFromHeaders,\n registerSpanErrorInstrumentation,\n spanIsSampled,\n spanToJSON,\n startIdleSpan,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\nimport { registerBackgroundTabDetection } from './backgroundtab';\nimport { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request';\n\nexport const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';\n\ninterface RouteInfo {\n name: string | undefined;\n source: TransactionSource | undefined;\n}\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 * 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 enableInp: 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 * 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 * 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 * _experiments allows the user to send options to define how this integration works.\n *\n * Default: undefined\n */\n _experiments: Partial<{\n enableInteractions: boolean;\n enableStandaloneClsSpans: boolean;\n }>;\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\nconst DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {\n ...TRACING_DEFAULTS,\n instrumentNavigation: true,\n instrumentPageLoad: true,\n markBackgroundSpan: true,\n enableLongTask: true,\n enableLongAnimationFrame: true,\n enableInp: true,\n _experiments: {},\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 registerSpanErrorInstrumentation();\n\n const {\n enableInp,\n enableLongTask,\n enableLongAnimationFrame,\n _experiments: { enableInteractions, enableStandaloneClsSpans },\n beforeStartSpan,\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n markBackgroundSpan,\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n instrumentPageLoad,\n instrumentNavigation,\n } = {\n ...DEFAULT_BROWSER_TRACING_OPTIONS,\n ..._options,\n };\n\n const _collectWebVitals = startTrackingWebVitals({ recordClsStandaloneSpans: enableStandaloneClsSpans || false });\n\n if (enableInp) {\n startTrackingINP();\n }\n\n if (\n enableLongAnimationFrame &&\n GLOBAL_OBJ.PerformanceObserver &&\n PerformanceObserver.supportedEntryTypes &&\n PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')\n ) {\n startTrackingLongAnimationFrames();\n } else if (enableLongTask) {\n startTrackingLongTasks();\n }\n\n if (enableInteractions) {\n startTrackingInteractions();\n }\n\n const latestRoute: RouteInfo = {\n name: undefined,\n source: undefined,\n };\n\n /** Create routing idle transaction. */\n function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions): Span {\n const isPageloadTransaction = startSpanOptions.op === 'pageload';\n\n const finalStartSpanOptions: StartSpanOptions = beforeStartSpan\n ? beforeStartSpan(startSpanOptions)\n : startSpanOptions;\n\n const attributes = finalStartSpanOptions.attributes || {};\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 (startSpanOptions.name !== finalStartSpanOptions.name) {\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] = 'custom';\n finalStartSpanOptions.attributes = attributes;\n }\n\n latestRoute.name = finalStartSpanOptions.name;\n latestRoute.source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];\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: isPageloadTransaction,\n beforeSpanEnd: span => {\n _collectWebVitals();\n addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans });\n },\n });\n\n function emitFinish(): void {\n if (['interactive', 'complete'].includes(WINDOW.document.readyState)) {\n client.emit('idleSpanEnableAutoFinish', idleSpan);\n }\n }\n\n if (isPageloadTransaction && WINDOW.document) {\n WINDOW.document.addEventListener('readystatechange', () => {\n emitFinish();\n });\n\n emitFinish();\n }\n\n return idleSpan;\n }\n\n return {\n name: BROWSER_TRACING_INTEGRATION_ID,\n afterAllSetup(client) {\n let activeSpan: Span | undefined;\n let startingUrl: string | undefined = WINDOW.location && WINDOW.location.href;\n\n function maybeEndActiveSpan(): void {\n if (activeSpan && !spanToJSON(activeSpan).timestamp) {\n DEBUG_BUILD && logger.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);\n // If there's an open active span, we need to finish it before creating an new one.\n activeSpan.end();\n }\n }\n\n client.on('startNavigationSpan', startSpanOptions => {\n if (getClient() !== client) {\n return;\n }\n\n maybeEndActiveSpan();\n\n activeSpan = _createRouteSpan(client, {\n op: 'navigation',\n ...startSpanOptions,\n });\n });\n\n client.on('startPageLoadSpan', (startSpanOptions, traceOptions = {}) => {\n if (getClient() !== client) {\n return;\n }\n maybeEndActiveSpan();\n\n const sentryTrace = traceOptions.sentryTrace || getMetaContent('sentry-trace');\n const baggage = traceOptions.baggage || getMetaContent('baggage');\n\n const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);\n getCurrentScope().setPropagationContext(propagationContext);\n\n activeSpan = _createRouteSpan(client, {\n op: 'pageload',\n ...startSpanOptions,\n });\n });\n\n // A trace should to stay the consistent over the entire time span of one route.\n // Therefore, when the initial pageload or navigation root span ends, we update the\n // scope's propagation context to keep span-specific attributes like the `sampled` decision and\n // the dynamic sampling context valid, even after the root span has ended.\n // This ensures that the trace data is consistent for the entire duration of the route.\n client.on('spanEnd', span => {\n const op = spanToJSON(span).op;\n if (span !== getRootSpan(span) || (op !== 'navigation' && op !== 'pageload')) {\n return;\n }\n\n const scope = getCurrentScope();\n const oldPropagationContext = scope.getPropagationContext();\n\n scope.setPropagationContext({\n ...oldPropagationContext,\n sampled: oldPropagationContext.sampled !== undefined ? oldPropagationContext.sampled : spanIsSampled(span),\n dsc: oldPropagationContext.dsc || getDynamicSamplingContextFromSpan(span),\n });\n });\n\n if (WINDOW.location) {\n if (instrumentPageLoad) {\n startBrowserTracingPageLoadSpan(client, {\n name: WINDOW.location.pathname,\n // pageload should always start at timeOrigin (and needs to be in s, not ms)\n startTime: browserPerformanceTimeOrigin ? browserPerformanceTimeOrigin / 1000 : undefined,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_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 && startingUrl.indexOf(to) !== -1) {\n startingUrl = undefined;\n return;\n }\n\n if (from !== to) {\n startingUrl = undefined;\n startBrowserTracingNavigationSpan(client, {\n name: WINDOW.location.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.browser',\n },\n });\n }\n });\n }\n }\n\n if (markBackgroundSpan) {\n registerBackgroundTabDetection();\n }\n\n if (enableInteractions) {\n registerInteractionListener(idleTimeout, finalTimeout, childSpanTimeout, latestRoute);\n }\n\n if (enableInp) {\n registerInpInteractionListener();\n }\n\n instrumentOutgoingRequests(client, {\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n tracePropagationTargets: client.getOptions().tracePropagationTargets,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\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 client.emit('startPageLoadSpan', spanOptions, traceOptions);\n\n getCurrentScope().setTransactionName(spanOptions.name);\n\n const span = getActiveSpan();\n const op = span && spanToJSON(span).op;\n return op === 'pageload' ? span : undefined;\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(client: Client, spanOptions: StartSpanOptions): Span | undefined {\n getIsolationScope().setPropagationContext({ traceId: generateTraceId() });\n getCurrentScope().setPropagationContext({ traceId: generateTraceId() });\n\n client.emit('startNavigationSpan', spanOptions);\n\n getCurrentScope().setTransactionName(spanOptions.name);\n\n const span = getActiveSpan();\n const op = span && spanToJSON(span).op;\n return op === 'navigation' ? span : undefined;\n}\n\n/** Returns the value of a meta tag */\nexport function getMetaContent(metaName: string): string | undefined {\n // Can't specify generic to `getDomElement` because tracing can be used\n // in a variety of environments, have to disable `no-unsafe-member-access`\n // as a result.\n // eslint-disable-next-line deprecation/deprecation\n const metaTag = getDomElement(`meta[name=${metaName}]`);\n // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access\n return metaTag ? metaTag.getAttribute('content') : undefined;\n}\n\n/** Start listener for interaction transactions */\nfunction registerInteractionListener(\n idleTimeout: BrowserTracingOptions['idleTimeout'],\n finalTimeout: BrowserTracingOptions['finalTimeout'],\n childSpanTimeout: BrowserTracingOptions['childSpanTimeout'],\n latestRoute: RouteInfo,\n): void {\n let inflightInteractionSpan: Span | undefined;\n const registerInteractionTransaction = (): void => {\n const op = 'ui.action.click';\n\n const activeSpan = getActiveSpan();\n const rootSpan = activeSpan && getRootSpan(activeSpan);\n if (rootSpan) {\n const currentRootSpanOp = spanToJSON(rootSpan).op;\n if (['navigation', 'pageload'].includes(currentRootSpanOp as string)) {\n DEBUG_BUILD &&\n logger.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);\n return undefined;\n }\n }\n\n if (inflightInteractionSpan) {\n inflightInteractionSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'interactionInterrupted');\n inflightInteractionSpan.end();\n inflightInteractionSpan = undefined;\n }\n\n if (!latestRoute.name) {\n DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);\n return undefined;\n }\n\n inflightInteractionSpan = startIdleSpan(\n {\n name: latestRoute.name,\n op,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: latestRoute.source || 'url',\n },\n },\n {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n },\n );\n };\n\n if (WINDOW.document) {\n addEventListener('click', registerInteractionTransaction, { once: false, capture: true });\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"browserTracingIntegration.js","sources":["../../../../src/tracing/browserTracingIntegration.ts"],"sourcesContent":["/* eslint-disable max-lines */\nimport {\n addHistoryInstrumentationHandler,\n addPerformanceEntries,\n registerInpInteractionListener,\n startTrackingINP,\n startTrackingInteractions,\n startTrackingLongAnimationFrames,\n startTrackingLongTasks,\n startTrackingWebVitals,\n} from '@sentry-internal/browser-utils';\nimport type { Client, IntegrationFn, Span, StartSpanOptions, TransactionSource } from '@sentry/core';\nimport {\n GLOBAL_OBJ,\n SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SEMANTIC_ATTRIBUTE_SENTRY_SOURCE,\n TRACING_DEFAULTS,\n addNonEnumerableProperty,\n browserPerformanceTimeOrigin,\n generateTraceId,\n getClient,\n getCurrentScope,\n getDynamicSamplingContextFromSpan,\n getIsolationScope,\n getLocationHref,\n logger,\n propagationContextFromHeaders,\n registerSpanErrorInstrumentation,\n spanIsSampled,\n spanToJSON,\n startIdleSpan,\n} from '@sentry/core';\nimport { DEBUG_BUILD } from '../debug-build';\nimport { WINDOW } from '../helpers';\nimport { registerBackgroundTabDetection } from './backgroundtab';\nimport { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request';\n\nexport const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';\n\ninterface RouteInfo {\n name: string | undefined;\n source: TransactionSource | undefined;\n}\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 * 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 enableInp: 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 * 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 * 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 * _experiments allows the user to send options to define how this integration works.\n *\n * Default: undefined\n */\n _experiments: Partial<{\n enableInteractions: boolean;\n enableStandaloneClsSpans: boolean;\n }>;\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\nconst DEFAULT_BROWSER_TRACING_OPTIONS: BrowserTracingOptions = {\n ...TRACING_DEFAULTS,\n instrumentNavigation: true,\n instrumentPageLoad: true,\n markBackgroundSpan: true,\n enableLongTask: true,\n enableLongAnimationFrame: true,\n enableInp: true,\n _experiments: {},\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 /**\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 registerSpanErrorInstrumentation();\n\n const {\n enableInp,\n enableLongTask,\n enableLongAnimationFrame,\n _experiments: { enableInteractions, enableStandaloneClsSpans },\n beforeStartSpan,\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n markBackgroundSpan,\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\n instrumentPageLoad,\n instrumentNavigation,\n } = {\n ...DEFAULT_BROWSER_TRACING_OPTIONS,\n ..._options,\n };\n\n const _collectWebVitals = startTrackingWebVitals({ recordClsStandaloneSpans: enableStandaloneClsSpans || false });\n\n if (enableInp) {\n startTrackingINP();\n }\n\n if (\n enableLongAnimationFrame &&\n GLOBAL_OBJ.PerformanceObserver &&\n PerformanceObserver.supportedEntryTypes &&\n PerformanceObserver.supportedEntryTypes.includes('long-animation-frame')\n ) {\n startTrackingLongAnimationFrames();\n } else if (enableLongTask) {\n startTrackingLongTasks();\n }\n\n if (enableInteractions) {\n startTrackingInteractions();\n }\n\n const latestRoute: RouteInfo = {\n name: undefined,\n source: undefined,\n };\n\n /** Create routing idle transaction. */\n function _createRouteSpan(client: Client, startSpanOptions: StartSpanOptions): void {\n const isPageloadTransaction = startSpanOptions.op === 'pageload';\n\n const finalStartSpanOptions: StartSpanOptions = beforeStartSpan\n ? beforeStartSpan(startSpanOptions)\n : startSpanOptions;\n\n const attributes = finalStartSpanOptions.attributes || {};\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 (startSpanOptions.name !== finalStartSpanOptions.name) {\n attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] = 'custom';\n finalStartSpanOptions.attributes = attributes;\n }\n\n latestRoute.name = finalStartSpanOptions.name;\n latestRoute.source = attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE];\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: isPageloadTransaction,\n beforeSpanEnd: span => {\n _collectWebVitals();\n addPerformanceEntries(span, { recordClsOnPageloadSpan: !enableStandaloneClsSpans });\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: idleSpan.spanContext().traceId,\n sampled: spanIsSampled(idleSpan),\n dsc: getDynamicSamplingContextFromSpan(span),\n });\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 }\n }\n\n if (isPageloadTransaction && optionalWindowDocument) {\n optionalWindowDocument.addEventListener('readystatechange', () => {\n emitFinish();\n });\n\n emitFinish();\n }\n }\n\n return {\n name: BROWSER_TRACING_INTEGRATION_ID,\n afterAllSetup(client) {\n let startingUrl: string | undefined = getLocationHref();\n\n function maybeEndActiveSpan(): void {\n const activeSpan = getActiveIdleSpan(client);\n\n if (activeSpan && !spanToJSON(activeSpan).timestamp) {\n DEBUG_BUILD && logger.log(`[Tracing] Finishing current active span with op: ${spanToJSON(activeSpan).op}`);\n // If there's an open active span, we need to finish it before creating an new one.\n activeSpan.end();\n }\n }\n\n client.on('startNavigationSpan', startSpanOptions => {\n if (getClient() !== client) {\n return;\n }\n\n maybeEndActiveSpan();\n\n getIsolationScope().setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });\n getCurrentScope().setPropagationContext({ traceId: generateTraceId(), sampleRand: Math.random() });\n\n _createRouteSpan(client, {\n op: 'navigation',\n ...startSpanOptions,\n });\n });\n\n client.on('startPageLoadSpan', (startSpanOptions, traceOptions = {}) => {\n if (getClient() !== client) {\n return;\n }\n maybeEndActiveSpan();\n\n const sentryTrace = traceOptions.sentryTrace || getMetaContent('sentry-trace');\n const baggage = traceOptions.baggage || getMetaContent('baggage');\n\n const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);\n getCurrentScope().setPropagationContext(propagationContext);\n\n _createRouteSpan(client, {\n op: 'pageload',\n ...startSpanOptions,\n });\n });\n\n if (WINDOW.location) {\n if (instrumentPageLoad) {\n const origin = browserPerformanceTimeOrigin();\n startBrowserTracingPageLoadSpan(client, {\n name: WINDOW.location.pathname,\n // pageload should always start at timeOrigin (and needs to be in s, not ms)\n startTime: origin ? origin / 1000 : undefined,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_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?.indexOf(to) !== -1) {\n startingUrl = undefined;\n return;\n }\n\n if (from !== to) {\n startingUrl = undefined;\n startBrowserTracingNavigationSpan(client, {\n name: WINDOW.location.pathname,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: 'url',\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.navigation.browser',\n },\n });\n }\n });\n }\n }\n\n if (markBackgroundSpan) {\n registerBackgroundTabDetection();\n }\n\n if (enableInteractions) {\n registerInteractionListener(client, idleTimeout, finalTimeout, childSpanTimeout, latestRoute);\n }\n\n if (enableInp) {\n registerInpInteractionListener();\n }\n\n instrumentOutgoingRequests(client, {\n traceFetch,\n traceXHR,\n trackFetchStreamPerformance,\n tracePropagationTargets: client.getOptions().tracePropagationTargets,\n shouldCreateSpanForRequest,\n enableHTTPTimings,\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 client.emit('startPageLoadSpan', spanOptions, traceOptions);\n getCurrentScope().setTransactionName(spanOptions.name);\n\n return getActiveIdleSpan(client);\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(client: Client, spanOptions: StartSpanOptions): Span | undefined {\n client.emit('startNavigationSpan', spanOptions);\n\n getCurrentScope().setTransactionName(spanOptions.name);\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/** Start listener for interaction transactions */\nfunction registerInteractionListener(\n client: Client,\n idleTimeout: BrowserTracingOptions['idleTimeout'],\n finalTimeout: BrowserTracingOptions['finalTimeout'],\n childSpanTimeout: BrowserTracingOptions['childSpanTimeout'],\n latestRoute: RouteInfo,\n): void {\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 let inflightInteractionSpan: Span | undefined;\n const registerInteractionTransaction = (): void => {\n const op = 'ui.action.click';\n\n const activeIdleSpan = getActiveIdleSpan(client);\n if (activeIdleSpan) {\n const currentRootSpanOp = spanToJSON(activeIdleSpan).op;\n if (['navigation', 'pageload'].includes(currentRootSpanOp as string)) {\n DEBUG_BUILD &&\n logger.warn(`[Tracing] Did not create ${op} span because a pageload or navigation span is in progress.`);\n return undefined;\n }\n }\n\n if (inflightInteractionSpan) {\n inflightInteractionSpan.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_IDLE_SPAN_FINISH_REASON, 'interactionInterrupted');\n inflightInteractionSpan.end();\n inflightInteractionSpan = undefined;\n }\n\n if (!latestRoute.name) {\n DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);\n return undefined;\n }\n\n inflightInteractionSpan = startIdleSpan(\n {\n name: latestRoute.name,\n op,\n attributes: {\n [SEMANTIC_ATTRIBUTE_SENTRY_SOURCE]: latestRoute.source || 'url',\n },\n },\n {\n idleTimeout,\n finalTimeout,\n childSpanTimeout,\n },\n );\n };\n\n if (optionalWindowDocument) {\n addEventListener('click', registerInteractionTransaction, { once: false, capture: true });\n }\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"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import { addXhrInstrumentationHandler, addPerformanceInstrumentationHandler, extractNetworkProtocol, SENTRY_XHR_DATA_KEY } from '@sentry-internal/browser-utils';
2
- import { addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, instrumentFetchRequest, parseUrl, spanToJSON, browserPerformanceTimeOrigin, hasTracingEnabled, setHttpStatus, getActiveSpan, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SentryNonRecordingSpan, getTraceData, stringMatchesSomePattern } from '@sentry/core';
1
+ import { addXhrInstrumentationHandler, addPerformanceInstrumentationHandler, SENTRY_XHR_DATA_KEY } from '@sentry-internal/browser-utils';
2
+ import { addFetchEndInstrumentationHandler, addFetchInstrumentationHandler, instrumentFetchRequest, parseUrl, spanToJSON, browserPerformanceTimeOrigin, hasTracingEnabled, setHttpStatus, getActiveSpan, startInactiveSpan, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SentryNonRecordingSpan, getTraceData, getLocationHref, stringMatchesSomePattern } from '@sentry/core';
3
3
  import { WINDOW } from '../helpers.js';
4
4
 
5
5
  /** Options for Request Instrumentation */
@@ -117,7 +117,7 @@ function isPerformanceResourceTiming(entry) {
117
117
  * @param span A span that has yet to be finished, must contain `url` on data.
118
118
  */
119
119
  function addHTTPTimings(span) {
120
- const { url } = spanToJSON(span).data || {};
120
+ const { url } = spanToJSON(span).data;
121
121
 
122
122
  if (!url || typeof url !== 'string') {
123
123
  return;
@@ -136,8 +136,39 @@ function addHTTPTimings(span) {
136
136
  });
137
137
  }
138
138
 
139
+ /**
140
+ * Converts ALPN protocol ids to name and version.
141
+ *
142
+ * (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)
143
+ * @param nextHopProtocol PerformanceResourceTiming.nextHopProtocol
144
+ */
145
+ function extractNetworkProtocol(nextHopProtocol) {
146
+ let name = 'unknown';
147
+ let version = 'unknown';
148
+ let _name = '';
149
+ for (const char of nextHopProtocol) {
150
+ // http/1.1 etc.
151
+ if (char === '/') {
152
+ [name, version] = nextHopProtocol.split('/') ;
153
+ break;
154
+ }
155
+ // h2, h3 etc.
156
+ if (!isNaN(Number(char))) {
157
+ name = _name === 'h' ? 'http' : _name;
158
+ version = nextHopProtocol.split(_name)[1] ;
159
+ break;
160
+ }
161
+ _name += char;
162
+ }
163
+ if (_name === nextHopProtocol) {
164
+ // webrtc, ftp, etc.
165
+ name = _name;
166
+ }
167
+ return { name, version };
168
+ }
169
+
139
170
  function getAbsoluteTime(time = 0) {
140
- return ((browserPerformanceTimeOrigin || performance.timeOrigin) + time) / 1000;
171
+ return ((browserPerformanceTimeOrigin() || performance.timeOrigin) + time) / 1000;
141
172
  }
142
173
 
143
174
  function resourceTimingEntryToSpanData(resourceTiming) {
@@ -147,7 +178,7 @@ function resourceTimingEntryToSpanData(resourceTiming) {
147
178
 
148
179
  timingSpanData.push(['network.protocol.version', version], ['network.protocol.name', name]);
149
180
 
150
- if (!browserPerformanceTimeOrigin) {
181
+ if (!browserPerformanceTimeOrigin()) {
151
182
  return timingSpanData;
152
183
  }
153
184
  return [
@@ -175,7 +206,7 @@ function shouldAttachHeaders(
175
206
  ) {
176
207
  // window.location.href not being defined is an edge case in the browser but we need to handle it.
177
208
  // Potentially dangerous situations where it may not be defined: Browser Extensions, Web Workers, patching of the location obj
178
- const href = WINDOW.location && WINDOW.location.href;
209
+ const href = getLocationHref();
179
210
 
180
211
  if (!href) {
181
212
  // If there is no window.location.origin, we default to only attaching tracing headers to relative requests, i.e. ones that start with `/`
@@ -223,7 +254,7 @@ function xhrCallback(
223
254
  spans,
224
255
  ) {
225
256
  const xhr = handlerData.xhr;
226
- const sentryXhrData = xhr && xhr[SENTRY_XHR_DATA_KEY];
257
+ const sentryXhrData = xhr?.[SENTRY_XHR_DATA_KEY];
227
258
 
228
259
  if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {
229
260
  return undefined;
@@ -318,10 +349,10 @@ function getFullURL(url) {
318
349
  // If `url` is a full URL, the base URL is ignored anyhow
319
350
  const parsed = new URL(url, WINDOW.location.origin);
320
351
  return parsed.href;
321
- } catch (e2) {
352
+ } catch {
322
353
  return undefined;
323
354
  }
324
355
  }
325
356
 
326
- export { defaultRequestInstrumentationOptions, instrumentOutgoingRequests, shouldAttachHeaders, xhrCallback };
357
+ export { defaultRequestInstrumentationOptions, extractNetworkProtocol, instrumentOutgoingRequests, shouldAttachHeaders, xhrCallback };
327
358
  //# sourceMappingURL=request.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"request.js","sources":["../../../../src/tracing/request.ts"],"sourcesContent":["import {\n SENTRY_XHR_DATA_KEY,\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n extractNetworkProtocol,\n} from '@sentry-internal/browser-utils';\nimport type { Client, HandlerDataXhr, SentryWrappedXMLHttpRequest, Span } from '@sentry/core';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n browserPerformanceTimeOrigin,\n getActiveSpan,\n getTraceData,\n hasTracingEnabled,\n instrumentFetchRequest,\n parseUrl,\n setHttpStatus,\n spanToJSON,\n startInactiveSpan,\n stringMatchesSomePattern,\n} from '@sentry/core';\nimport { WINDOW } from '../helpers';\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\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 } = {\n traceFetch: defaultRequestInstrumentationOptions.traceFetch,\n traceXHR: defaultRequestInstrumentationOptions.traceXHR,\n trackFetchStreamPerformance: defaultRequestInstrumentationOptions.trackFetchStreamPerformance,\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 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\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,\n 'server.address': host,\n });\n }\n\n if (enableHTTPTimings && createdSpan) {\n addHTTPTimings(createdSpan);\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans);\n if (enableHTTPTimings && createdSpan) {\n addHTTPTimings(createdSpan);\n }\n });\n }\n}\n\nfunction isPerformanceResourceTiming(entry: PerformanceEntry): entry is PerformanceResourceTiming {\n return (\n entry.entryType === 'resource' &&\n 'initiatorType' in entry &&\n typeof (entry as PerformanceResourceTiming).nextHopProtocol === 'string' &&\n (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest')\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 const spanData = resourceTimingEntryToSpanData(entry);\n spanData.forEach(data => span.setAttribute(...data));\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\nfunction getAbsoluteTime(time: number = 0): number {\n return ((browserPerformanceTimeOrigin || performance.timeOrigin) + time) / 1000;\n}\n\nfunction resourceTimingEntryToSpanData(resourceTiming: PerformanceResourceTiming): [string, string | number][] {\n const { name, version } = extractNetworkProtocol(resourceTiming.nextHopProtocol);\n\n const timingSpanData: [string, string | number][] = [];\n\n timingSpanData.push(['network.protocol.version', version], ['network.protocol.name', name]);\n\n if (!browserPerformanceTimeOrigin) {\n return timingSpanData;\n }\n return [\n ...timingSpanData,\n ['http.request.redirect_start', getAbsoluteTime(resourceTiming.redirectStart)],\n ['http.request.fetch_start', getAbsoluteTime(resourceTiming.fetchStart)],\n ['http.request.domain_lookup_start', getAbsoluteTime(resourceTiming.domainLookupStart)],\n ['http.request.domain_lookup_end', getAbsoluteTime(resourceTiming.domainLookupEnd)],\n ['http.request.connect_start', getAbsoluteTime(resourceTiming.connectStart)],\n ['http.request.secure_connection_start', getAbsoluteTime(resourceTiming.secureConnectionStart)],\n ['http.request.connection_end', getAbsoluteTime(resourceTiming.connectEnd)],\n ['http.request.request_start', getAbsoluteTime(resourceTiming.requestStart)],\n ['http.request.response_start', getAbsoluteTime(resourceTiming.responseStart)],\n ['http.request.response_end', getAbsoluteTime(resourceTiming.responseEnd)],\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: string | undefined = WINDOW.location && WINDOW.location.href;\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 (e) {\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 */\nexport function xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\n): Span | undefined {\n const xhr = handlerData.xhr;\n const sentryXhrData = xhr && xhr[SENTRY_XHR_DATA_KEY];\n\n if (!xhr || xhr.__sentry_own_request__ || !sentryXhrData) {\n return undefined;\n }\n\n const shouldCreateSpanResult = hasTracingEnabled() && shouldCreateSpan(sentryXhrData.url);\n\n // check first if the request has finished and is tracked by an existing span which should now end\n if (handlerData.endTimestamp && shouldCreateSpanResult) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n if (span && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n return undefined;\n }\n\n const fullUrl = getFullURL(sentryXhrData.url);\n const host = fullUrl ? parseUrl(fullUrl).host : undefined;\n\n const hasParent = !!getActiveSpan();\n\n const span =\n shouldCreateSpanResult && hasParent\n ? startInactiveSpan({\n name: `${sentryXhrData.method} ${sentryXhrData.url}`,\n attributes: {\n type: 'xhr',\n 'http.method': sentryXhrData.method,\n 'http.url': fullUrl,\n url: sentryXhrData.url,\n 'server.address': host,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\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(sentryXhrData.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 hasTracingEnabled() && hasParent ? span : undefined,\n );\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(xhr: SentryWrappedXMLHttpRequest, span?: Span): void {\n const { 'sentry-trace': sentryTrace, baggage } = getTraceData({ span });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n): void {\n try {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n xhr.setRequestHeader!('sentry-trace', sentryTraceHeader);\n if (sentryBaggageHeader) {\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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n xhr.setRequestHeader!('baggage', sentryBaggageHeader);\n }\n } catch (_) {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n\nfunction getFullURL(url: string): string | undefined {\n try {\n // By adding a base URL to new URL(), this will also work for relative urls\n // If `url` is a full URL, the base URL is ignored anyhow\n const parsed = new URL(url, WINDOW.location.origin);\n return parsed.href;\n } catch {\n return undefined;\n }\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"request.js","sources":["../../../../src/tracing/request.ts"],"sourcesContent":["import {\n SENTRY_XHR_DATA_KEY,\n addPerformanceInstrumentationHandler,\n addXhrInstrumentationHandler,\n} from '@sentry-internal/browser-utils';\nimport type { Client, HandlerDataXhr, SentryWrappedXMLHttpRequest, Span } from '@sentry/core';\nimport {\n SEMANTIC_ATTRIBUTE_SENTRY_OP,\n SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN,\n SentryNonRecordingSpan,\n addFetchEndInstrumentationHandler,\n addFetchInstrumentationHandler,\n browserPerformanceTimeOrigin,\n getActiveSpan,\n getLocationHref,\n getTraceData,\n hasTracingEnabled,\n instrumentFetchRequest,\n parseUrl,\n setHttpStatus,\n spanToJSON,\n startInactiveSpan,\n stringMatchesSomePattern,\n} from '@sentry/core';\nimport { WINDOW } from '../helpers';\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\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 } = {\n traceFetch: defaultRequestInstrumentationOptions.traceFetch,\n traceXHR: defaultRequestInstrumentationOptions.traceXHR,\n trackFetchStreamPerformance: defaultRequestInstrumentationOptions.trackFetchStreamPerformance,\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 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\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,\n 'server.address': host,\n });\n }\n\n if (enableHTTPTimings && createdSpan) {\n addHTTPTimings(createdSpan);\n }\n });\n }\n\n if (traceXHR) {\n addXhrInstrumentationHandler(handlerData => {\n const createdSpan = xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans);\n if (enableHTTPTimings && createdSpan) {\n addHTTPTimings(createdSpan);\n }\n });\n }\n}\n\nfunction isPerformanceResourceTiming(entry: PerformanceEntry): entry is PerformanceResourceTiming {\n return (\n entry.entryType === 'resource' &&\n 'initiatorType' in entry &&\n typeof (entry as PerformanceResourceTiming).nextHopProtocol === 'string' &&\n (entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest')\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 const spanData = resourceTimingEntryToSpanData(entry);\n spanData.forEach(data => span.setAttribute(...data));\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 * Converts ALPN protocol ids to name and version.\n *\n * (https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xhtml#alpn-protocol-ids)\n * @param nextHopProtocol PerformanceResourceTiming.nextHopProtocol\n */\nexport function extractNetworkProtocol(nextHopProtocol: string): { name: string; version: string } {\n let name = 'unknown';\n let version = 'unknown';\n let _name = '';\n for (const char of nextHopProtocol) {\n // http/1.1 etc.\n if (char === '/') {\n [name, version] = nextHopProtocol.split('/') as [string, string];\n break;\n }\n // h2, h3 etc.\n if (!isNaN(Number(char))) {\n name = _name === 'h' ? 'http' : _name;\n version = nextHopProtocol.split(_name)[1] as string;\n break;\n }\n _name += char;\n }\n if (_name === nextHopProtocol) {\n // webrtc, ftp, etc.\n name = _name;\n }\n return { name, version };\n}\n\nfunction getAbsoluteTime(time: number = 0): number {\n return ((browserPerformanceTimeOrigin() || performance.timeOrigin) + time) / 1000;\n}\n\nfunction resourceTimingEntryToSpanData(resourceTiming: PerformanceResourceTiming): [string, string | number][] {\n const { name, version } = extractNetworkProtocol(resourceTiming.nextHopProtocol);\n\n const timingSpanData: [string, string | number][] = [];\n\n timingSpanData.push(['network.protocol.version', version], ['network.protocol.name', name]);\n\n if (!browserPerformanceTimeOrigin()) {\n return timingSpanData;\n }\n return [\n ...timingSpanData,\n ['http.request.redirect_start', getAbsoluteTime(resourceTiming.redirectStart)],\n ['http.request.fetch_start', getAbsoluteTime(resourceTiming.fetchStart)],\n ['http.request.domain_lookup_start', getAbsoluteTime(resourceTiming.domainLookupStart)],\n ['http.request.domain_lookup_end', getAbsoluteTime(resourceTiming.domainLookupEnd)],\n ['http.request.connect_start', getAbsoluteTime(resourceTiming.connectStart)],\n ['http.request.secure_connection_start', getAbsoluteTime(resourceTiming.secureConnectionStart)],\n ['http.request.connection_end', getAbsoluteTime(resourceTiming.connectEnd)],\n ['http.request.request_start', getAbsoluteTime(resourceTiming.requestStart)],\n ['http.request.response_start', getAbsoluteTime(resourceTiming.responseStart)],\n ['http.request.response_end', getAbsoluteTime(resourceTiming.responseEnd)],\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 (e) {\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 */\nexport function xhrCallback(\n handlerData: HandlerDataXhr,\n shouldCreateSpan: (url: string) => boolean,\n shouldAttachHeaders: (url: string) => boolean,\n spans: Record<string, Span>,\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 shouldCreateSpanResult = hasTracingEnabled() && shouldCreateSpan(sentryXhrData.url);\n\n // check first if the request has finished and is tracked by an existing span which should now end\n if (handlerData.endTimestamp && shouldCreateSpanResult) {\n const spanId = xhr.__sentry_xhr_span_id__;\n if (!spanId) return;\n\n const span = spans[spanId];\n if (span && sentryXhrData.status_code !== undefined) {\n setHttpStatus(span, sentryXhrData.status_code);\n span.end();\n\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete spans[spanId];\n }\n return undefined;\n }\n\n const fullUrl = getFullURL(sentryXhrData.url);\n const host = fullUrl ? parseUrl(fullUrl).host : undefined;\n\n const hasParent = !!getActiveSpan();\n\n const span =\n shouldCreateSpanResult && hasParent\n ? startInactiveSpan({\n name: `${sentryXhrData.method} ${sentryXhrData.url}`,\n attributes: {\n type: 'xhr',\n 'http.method': sentryXhrData.method,\n 'http.url': fullUrl,\n url: sentryXhrData.url,\n 'server.address': host,\n [SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: 'auto.http.browser',\n [SEMANTIC_ATTRIBUTE_SENTRY_OP]: 'http.client',\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(sentryXhrData.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 hasTracingEnabled() && hasParent ? span : undefined,\n );\n }\n\n return span;\n}\n\nfunction addTracingHeadersToXhrRequest(xhr: SentryWrappedXMLHttpRequest, span?: Span): void {\n const { 'sentry-trace': sentryTrace, baggage } = getTraceData({ span });\n\n if (sentryTrace) {\n setHeaderOnXhr(xhr, sentryTrace, baggage);\n }\n}\n\nfunction setHeaderOnXhr(\n xhr: SentryWrappedXMLHttpRequest,\n sentryTraceHeader: string,\n sentryBaggageHeader: string | undefined,\n): void {\n try {\n // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n xhr.setRequestHeader!('sentry-trace', sentryTraceHeader);\n if (sentryBaggageHeader) {\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 // eslint-disable-next-line @typescript-eslint/no-non-null-assertion\n xhr.setRequestHeader!('baggage', sentryBaggageHeader);\n }\n } catch (_) {\n // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.\n }\n}\n\nfunction getFullURL(url: string): string | undefined {\n try {\n // By adding a base URL to new URL(), this will also work for relative urls\n // If `url` is a full URL, the base URL is ignored anyhow\n const parsed = new URL(url, WINDOW.location.origin);\n return parsed.href;\n } catch {\n return undefined;\n }\n}\n"],"names":[],"mappings":"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"}
@@ -16,13 +16,12 @@ function createUserFeedbackEnvelope(
16
16
  const headers = {
17
17
  event_id: feedback.event_id,
18
18
  sent_at: new Date().toISOString(),
19
- ...(metadata &&
20
- metadata.sdk && {
21
- sdk: {
22
- name: metadata.sdk.name,
23
- version: metadata.sdk.version,
24
- },
25
- }),
19
+ ...(metadata?.sdk && {
20
+ sdk: {
21
+ name: metadata.sdk.name,
22
+ version: metadata.sdk.version,
23
+ },
24
+ }),
26
25
  ...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),
27
26
  };
28
27
  const item = createUserFeedbackEnvelopeItem(feedback);
@@ -1 +1 @@
1
- {"version":3,"file":"userfeedback.js","sources":["../../../src/userfeedback.ts"],"sourcesContent":["import { createEnvelope, dsnToString } from '@sentry/core';\nimport type { DsnComponents, EventEnvelope, SdkMetadata, UserFeedback, UserFeedbackItem } from '@sentry/core';\n\n/**\n * Creates an envelope from a user feedback.\n */\nexport function createUserFeedbackEnvelope(\n feedback: UserFeedback,\n {\n metadata,\n tunnel,\n dsn,\n }: {\n metadata: SdkMetadata | undefined;\n tunnel: string | undefined;\n dsn: DsnComponents | undefined;\n },\n): EventEnvelope {\n const headers: EventEnvelope[0] = {\n event_id: feedback.event_id,\n sent_at: new Date().toISOString(),\n ...(metadata &&\n metadata.sdk && {\n sdk: {\n name: metadata.sdk.name,\n version: metadata.sdk.version,\n },\n }),\n ...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),\n };\n const item = createUserFeedbackEnvelopeItem(feedback);\n\n return createEnvelope(headers, [item]);\n}\n\nfunction createUserFeedbackEnvelopeItem(feedback: UserFeedback): UserFeedbackItem {\n const feedbackHeaders: UserFeedbackItem[0] = {\n type: 'user_report',\n };\n return [feedbackHeaders, feedback];\n}\n"],"names":[],"mappings":";;AAGA;AACA;AACA;AACO,SAAS,0BAA0B;AAC1C,EAAE,QAAQ;AACV,EAAE;AACF,IAAI,QAAQ;AACZ,IAAI,MAAM;AACV,IAAI,GAAG;AACP;;AAIE;AACF,EAAiB;AACjB,EAAE,MAAM,OAAO,GAAqB;AACpC,IAAI,QAAQ,EAAE,QAAQ,CAAC,QAAQ;AAC/B,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACrC,IAAI,IAAI,QAAS;AACjB,MAAM,QAAQ,CAAC,GAAA,IAAO;AACtB,QAAQ,GAAG,EAAE;AACb,UAAU,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI;AACjC,UAAU,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO;AACvC,SAAS;AACT,OAAO,CAAC;AACR,IAAI,IAAI,CAAC,CAAC,MAAO,IAAG,CAAC,CAAC,GAAA,IAAO,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,CAAA,EAAG,CAAC;AACvD,GAAG;AACH,EAAE,MAAM,IAAK,GAAE,8BAA8B,CAAC,QAAQ,CAAC;;AAEvD,EAAE,OAAO,cAAc,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;AACxC;;AAEA,SAAS,8BAA8B,CAAC,QAAQ,EAAkC;AAClF,EAAE,MAAM,eAAe,GAAwB;AAC/C,IAAI,IAAI,EAAE,aAAa;AACvB,GAAG;AACH,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC;AACpC;;;;"}
1
+ {"version":3,"file":"userfeedback.js","sources":["../../../src/userfeedback.ts"],"sourcesContent":["import { createEnvelope, dsnToString } from '@sentry/core';\nimport type { DsnComponents, EventEnvelope, SdkMetadata, UserFeedback, UserFeedbackItem } from '@sentry/core';\n\n/**\n * Creates an envelope from a user feedback.\n */\nexport function createUserFeedbackEnvelope(\n feedback: UserFeedback,\n {\n metadata,\n tunnel,\n dsn,\n }: {\n metadata: SdkMetadata | undefined;\n tunnel: string | undefined;\n dsn: DsnComponents | undefined;\n },\n): EventEnvelope {\n const headers: EventEnvelope[0] = {\n event_id: feedback.event_id,\n sent_at: new Date().toISOString(),\n ...(metadata?.sdk && {\n sdk: {\n name: metadata.sdk.name,\n version: metadata.sdk.version,\n },\n }),\n ...(!!tunnel && !!dsn && { dsn: dsnToString(dsn) }),\n };\n const item = createUserFeedbackEnvelopeItem(feedback);\n\n return createEnvelope(headers, [item]);\n}\n\nfunction createUserFeedbackEnvelopeItem(feedback: UserFeedback): UserFeedbackItem {\n const feedbackHeaders: UserFeedbackItem[0] = {\n type: 'user_report',\n };\n return [feedbackHeaders, feedback];\n}\n"],"names":[],"mappings":";;AAGA;AACA;AACA;AACO,SAAS,0BAA0B;AAC1C,EAAE,QAAQ;AACV,EAAE;AACF,IAAI,QAAQ;AACZ,IAAI,MAAM;AACV,IAAI,GAAG;AACP;;AAIE;AACF,EAAiB;AACjB,EAAE,MAAM,OAAO,GAAqB;AACpC,IAAI,QAAQ,EAAE,QAAQ,CAAC,QAAQ;AAC/B,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACrC,IAAI,IAAI,QAAQ,EAAE,OAAO;AACzB,MAAM,GAAG,EAAE;AACX,QAAQ,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI;AAC/B,QAAQ,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO;AACrC,OAAO;AACP,KAAK,CAAC;AACN,IAAI,IAAI,CAAC,CAAC,MAAO,IAAG,CAAC,CAAC,GAAA,IAAO,EAAE,GAAG,EAAE,WAAW,CAAC,GAAG,CAAA,EAAG,CAAC;AACvD,GAAG;AACH,EAAE,MAAM,IAAK,GAAE,8BAA8B,CAAC,QAAQ,CAAC;;AAEvD,EAAE,OAAO,cAAc,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC;AACxC;;AAEA,SAAS,8BAA8B,CAAC,QAAQ,EAAkC;AAClF,EAAE,MAAM,eAAe,GAAwB;AAC/C,IAAI,IAAI,EAAE,aAAa;AACvB,GAAG;AACH,EAAE,OAAO,CAAC,eAAe,EAAE,QAAQ,CAAC;AACpC;;;;"}