@sentry/browser 8.53.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.
- package/build/npm/cjs/client.js +36 -28
- package/build/npm/cjs/client.js.map +1 -1
- package/build/npm/cjs/debug-build.js +1 -1
- package/build/npm/cjs/eventbuilder.js +8 -8
- package/build/npm/cjs/eventbuilder.js.map +1 -1
- package/build/npm/cjs/feedbackAsync.js +1 -1
- package/build/npm/cjs/feedbackSync.js +1 -1
- package/build/npm/cjs/helpers.js +3 -3
- package/build/npm/cjs/helpers.js.map +1 -1
- package/build/npm/cjs/index.js +1 -8
- package/build/npm/cjs/index.js.map +1 -1
- package/build/npm/cjs/integrations/breadcrumbs.js +15 -10
- package/build/npm/cjs/integrations/breadcrumbs.js.map +1 -1
- package/build/npm/cjs/integrations/browserapierrors.js +4 -5
- package/build/npm/cjs/integrations/browserapierrors.js.map +1 -1
- package/build/npm/cjs/integrations/browsersession.js +1 -1
- package/build/npm/cjs/integrations/contextlines.js +4 -4
- package/build/npm/cjs/integrations/contextlines.js.map +1 -1
- package/build/npm/cjs/integrations/featureFlags/featureFlagsIntegration.js +1 -1
- package/build/npm/cjs/integrations/featureFlags/launchdarkly/integration.js +1 -1
- package/build/npm/cjs/integrations/featureFlags/openfeature/integration.js +1 -1
- package/build/npm/cjs/integrations/featureFlags/unleash/integration.js +1 -1
- package/build/npm/cjs/integrations/globalhandlers.js +3 -3
- package/build/npm/cjs/integrations/globalhandlers.js.map +1 -1
- package/build/npm/cjs/integrations/httpclient.js +4 -4
- package/build/npm/cjs/integrations/httpclient.js.map +1 -1
- package/build/npm/cjs/integrations/httpcontext.js +8 -4
- package/build/npm/cjs/integrations/httpcontext.js.map +1 -1
- package/build/npm/cjs/integrations/linkederrors.js +1 -1
- package/build/npm/cjs/integrations/reportingobserver.js +1 -1
- package/build/npm/cjs/integrations/spotlight.js +2 -2
- package/build/npm/cjs/integrations/spotlight.js.map +1 -1
- package/build/npm/cjs/profiling/integration.js +5 -5
- package/build/npm/cjs/profiling/integration.js.map +1 -1
- package/build/npm/cjs/profiling/startProfileForSpan.js +1 -1
- package/build/npm/cjs/profiling/utils.js +16 -16
- package/build/npm/cjs/profiling/utils.js.map +1 -1
- package/build/npm/cjs/sdk.js +30 -41
- package/build/npm/cjs/sdk.js.map +1 -1
- package/build/npm/cjs/stack-parsers.js +1 -1
- package/build/npm/cjs/stack-parsers.js.map +1 -1
- package/build/npm/cjs/tracing/backgroundtab.js +2 -2
- package/build/npm/cjs/tracing/backgroundtab.js.map +1 -1
- package/build/npm/cjs/tracing/browserTracingIntegration.js +68 -56
- package/build/npm/cjs/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/cjs/tracing/request.js +40 -8
- package/build/npm/cjs/tracing/request.js.map +1 -1
- package/build/npm/cjs/transports/fetch.js +1 -1
- package/build/npm/cjs/transports/offline.js +1 -1
- package/build/npm/cjs/userfeedback.js +7 -8
- package/build/npm/cjs/userfeedback.js.map +1 -1
- package/build/npm/cjs/utils/featureFlags.js +1 -1
- package/build/npm/cjs/utils/featureFlags.js.map +1 -1
- package/build/npm/cjs/utils/lazyLoadIntegration.js +4 -7
- package/build/npm/cjs/utils/lazyLoadIntegration.js.map +1 -1
- package/build/npm/esm/client.js +36 -28
- package/build/npm/esm/client.js.map +1 -1
- package/build/npm/esm/eventbuilder.js +7 -7
- package/build/npm/esm/eventbuilder.js.map +1 -1
- package/build/npm/esm/helpers.js +2 -2
- package/build/npm/esm/helpers.js.map +1 -1
- package/build/npm/esm/index.js +2 -3
- package/build/npm/esm/index.js.map +1 -1
- package/build/npm/esm/integrations/breadcrumbs.js +14 -9
- package/build/npm/esm/integrations/breadcrumbs.js.map +1 -1
- package/build/npm/esm/integrations/browserapierrors.js +3 -4
- package/build/npm/esm/integrations/browserapierrors.js.map +1 -1
- package/build/npm/esm/integrations/contextlines.js +3 -3
- package/build/npm/esm/integrations/contextlines.js.map +1 -1
- package/build/npm/esm/integrations/globalhandlers.js +2 -2
- package/build/npm/esm/integrations/globalhandlers.js.map +1 -1
- package/build/npm/esm/integrations/httpclient.js +3 -3
- package/build/npm/esm/integrations/httpclient.js.map +1 -1
- package/build/npm/esm/integrations/httpcontext.js +8 -4
- package/build/npm/esm/integrations/httpcontext.js.map +1 -1
- package/build/npm/esm/integrations/spotlight.js +1 -1
- package/build/npm/esm/integrations/spotlight.js.map +1 -1
- package/build/npm/esm/package.json +1 -1
- package/build/npm/esm/profiling/integration.js +4 -4
- package/build/npm/esm/profiling/integration.js.map +1 -1
- package/build/npm/esm/profiling/utils.js +15 -15
- package/build/npm/esm/profiling/utils.js.map +1 -1
- package/build/npm/esm/sdk.js +30 -41
- package/build/npm/esm/sdk.js.map +1 -1
- package/build/npm/esm/stack-parsers.js.map +1 -1
- package/build/npm/esm/tracing/backgroundtab.js +1 -1
- package/build/npm/esm/tracing/backgroundtab.js.map +1 -1
- package/build/npm/esm/tracing/browserTracingIntegration.js +68 -56
- package/build/npm/esm/tracing/browserTracingIntegration.js.map +1 -1
- package/build/npm/esm/tracing/request.js +40 -9
- package/build/npm/esm/tracing/request.js.map +1 -1
- package/build/npm/esm/userfeedback.js +6 -7
- package/build/npm/esm/userfeedback.js.map +1 -1
- package/build/npm/esm/utils/featureFlags.js.map +1 -1
- package/build/npm/esm/utils/lazyLoadIntegration.js +3 -6
- package/build/npm/esm/utils/lazyLoadIntegration.js.map +1 -1
- package/build/npm/types/client.d.ts +4 -10
- package/build/npm/types/client.d.ts.map +1 -1
- package/build/npm/types/exports.d.ts +3 -4
- package/build/npm/types/exports.d.ts.map +1 -1
- package/build/npm/types/helpers.d.ts +26 -1
- package/build/npm/types/helpers.d.ts.map +1 -1
- package/build/npm/types/index.bundle.d.ts +2 -2
- package/build/npm/types/index.bundle.d.ts.map +1 -1
- package/build/npm/types/index.bundle.feedback.d.ts +2 -2
- package/build/npm/types/index.bundle.feedback.d.ts.map +1 -1
- package/build/npm/types/index.bundle.replay.d.ts +2 -2
- package/build/npm/types/index.bundle.replay.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.d.ts +0 -1
- package/build/npm/types/index.bundle.tracing.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.replay.d.ts +0 -1
- package/build/npm/types/index.bundle.tracing.replay.d.ts.map +1 -1
- package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts +0 -1
- package/build/npm/types/index.bundle.tracing.replay.feedback.d.ts.map +1 -1
- package/build/npm/types/index.d.ts +2 -3
- package/build/npm/types/index.d.ts.map +1 -1
- package/build/npm/types/integrations/httpcontext.d.ts.map +1 -1
- package/build/npm/types/integrations-bundle/index.debug.d.ts +0 -1
- package/build/npm/types/integrations-bundle/index.debug.d.ts.map +1 -1
- package/build/npm/types/sdk.d.ts +4 -36
- package/build/npm/types/sdk.d.ts.map +1 -1
- package/build/npm/types/tracing/browserTracingIntegration.d.ts.map +1 -1
- package/build/npm/types/tracing/request.d.ts +10 -0
- package/build/npm/types/tracing/request.d.ts.map +1 -1
- package/build/npm/types/userfeedback.d.ts.map +1 -1
- package/build/npm/types/utils/lazyLoadIntegration.d.ts +0 -2
- package/build/npm/types/utils/lazyLoadIntegration.d.ts.map +1 -1
- package/build/npm/types-ts3.8/client.d.ts +4 -10
- package/build/npm/types-ts3.8/exports.d.ts +3 -4
- package/build/npm/types-ts3.8/helpers.d.ts +26 -1
- package/build/npm/types-ts3.8/index.bundle.d.ts +2 -2
- package/build/npm/types-ts3.8/index.bundle.feedback.d.ts +2 -2
- package/build/npm/types-ts3.8/index.bundle.replay.d.ts +2 -2
- package/build/npm/types-ts3.8/index.bundle.tracing.d.ts +0 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.replay.d.ts +0 -1
- package/build/npm/types-ts3.8/index.bundle.tracing.replay.feedback.d.ts +0 -1
- package/build/npm/types-ts3.8/index.d.ts +2 -3
- package/build/npm/types-ts3.8/integrations-bundle/index.debug.d.ts +0 -1
- package/build/npm/types-ts3.8/sdk.d.ts +4 -36
- package/build/npm/types-ts3.8/tracing/request.d.ts +10 -0
- package/build/npm/types-ts3.8/utils/lazyLoadIntegration.d.ts +0 -2
- package/package.json +9 -9
- package/build/npm/cjs/metrics.js +0 -79
- package/build/npm/cjs/metrics.js.map +0 -1
- package/build/npm/esm/metrics.js +0 -77
- package/build/npm/esm/metrics.js.map +0 -1
- package/build/npm/types/integrations-bundle/index.sessiontiming.d.ts +0 -2
- package/build/npm/types/integrations-bundle/index.sessiontiming.d.ts.map +0 -1
- package/build/npm/types/metrics.d.ts +0 -8
- package/build/npm/types/metrics.d.ts.map +0 -1
- package/build/npm/types-ts3.8/integrations-bundle/index.sessiontiming.d.ts +0 -2
- 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,
|
|
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(
|
|
138
|
+
if (optionalWindowDocument && ['interactive', 'complete'].includes(optionalWindowDocument.readyState)) {
|
|
118
139
|
client.emit('idleSpanEnableAutoFinish', idleSpan);
|
|
119
140
|
}
|
|
120
141
|
}
|
|
121
142
|
|
|
122
|
-
if (isPageloadTransaction &&
|
|
123
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
const
|
|
311
|
-
|
|
312
|
-
|
|
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
|
|
327
|
-
|
|
328
|
-
|
|
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 (
|
|
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":";;;;;;;AAAA;;AAsCO,MAAM,8BAA+B,GAAE;;AAmI9C,MAAM,+BAA+B,GAA0B;AAC/D,EAAE,GAAG,gBAAgB;AACrB,EAAE,oBAAoB,EAAE,IAAI;AAC5B,EAAE,kBAAkB,EAAE,IAAI;AAC1B,EAAE,kBAAkB,EAAE,IAAI;AAC1B,EAAE,cAAc,EAAE,IAAI;AACtB,EAAE,wBAAwB,EAAE,IAAI;AAChC,EAAE,SAAS,EAAE,IAAI;AACjB,EAAE,YAAY,EAAE,EAAE;AAClB,EAAE,GAAG,oCAAoC;AACzC,CAAC;;AAED;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,yBAA0B,IAAG,CAAC,QAAQ,GAAmC,EAAE,KAAK;AAC7F;AACA;AACA;AACA;AACA,EAAE,MAAM,sBAAA,GAAyB,MAAM,CAAC,QAAS;;AAEjD,EAAE,gCAAgC,EAAE;;AAEpC,EAAE,MAAM;AACR,IAAI,SAAS;AACb,IAAI,cAAc;AAClB,IAAI,wBAAwB;AAC5B,IAAI,YAAY,EAAE,EAAE,kBAAkB,EAAE,0BAA0B;AAClE,IAAI,eAAe;AACnB,IAAI,WAAW;AACf,IAAI,YAAY;AAChB,IAAI,gBAAgB;AACpB,IAAI,kBAAkB;AACtB,IAAI,UAAU;AACd,IAAI,QAAQ;AACZ,IAAI,2BAA2B;AAC/B,IAAI,0BAA0B;AAC9B,IAAI,iBAAiB;AACrB,IAAI,kBAAkB;AACtB,IAAI,oBAAoB;AACxB,MAAM;AACN,IAAI,GAAG,+BAA+B;AACtC,IAAI,GAAG,QAAQ;AACf,GAAG;;AAEH,EAAE,MAAM,iBAAA,GAAoB,sBAAsB,CAAC,EAAE,wBAAwB,EAAE,wBAAyB,IAAG,KAAM,EAAC,CAAC;;AAEnH,EAAE,IAAI,SAAS,EAAE;AACjB,IAAI,gBAAgB,EAAE;AACtB;;AAEA,EAAE;AACF,IAAI,wBAAyB;AAC7B,IAAI,UAAU,CAAC,mBAAoB;AACnC,IAAI,mBAAmB,CAAC,mBAAoB;AAC5C,IAAI,mBAAmB,CAAC,mBAAmB,CAAC,QAAQ,CAAC,sBAAsB;AAC3E,IAAI;AACJ,IAAI,gCAAgC,EAAE;AACtC,GAAI,MAAK,IAAI,cAAc,EAAE;AAC7B,IAAI,sBAAsB,EAAE;AAC5B;;AAEA,EAAE,IAAI,kBAAkB,EAAE;AAC1B,IAAI,yBAAyB,EAAE;AAC/B;;AAEA,EAAE,MAAM,WAAW,GAAc;AACjC,IAAI,IAAI,EAAE,SAAS;AACnB,IAAI,MAAM,EAAE,SAAS;AACrB,GAAG;;AAEH;AACA,EAAE,SAAS,gBAAgB,CAAC,MAAM,EAAU,gBAAgB,EAA0B;AACtF,IAAI,MAAM,qBAAsB,GAAE,gBAAgB,CAAC,EAAA,KAAO,UAAU;;AAEpE,IAAI,MAAM,qBAAqB,GAAqB;AACpD,QAAQ,eAAe,CAAC,gBAAgB;AACxC,QAAQ,gBAAgB;;AAExB,IAAI,MAAM,aAAa,qBAAqB,CAAC,UAAW,IAAG,EAAE;;AAE7D;AACA;AACA,IAAI,IAAI,gBAAgB,CAAC,SAAS,qBAAqB,CAAC,IAAI,EAAE;AAC9D,MAAM,UAAU,CAAC,gCAAgC,CAAA,GAAI,QAAQ;AAC7D,MAAM,qBAAqB,CAAC,UAAW,GAAE,UAAU;AACnD;;AAEA,IAAI,WAAW,CAAC,IAAA,GAAO,qBAAqB,CAAC,IAAI;AACjD,IAAI,WAAW,CAAC,MAAA,GAAS,UAAU,CAAC,gCAAgC,CAAC;;AAErE,IAAI,MAAM,QAAS,GAAE,aAAa,CAAC,qBAAqB,EAAE;AAC1D,MAAM,WAAW;AACjB,MAAM,YAAY;AAClB,MAAM,gBAAgB;AACtB;AACA,MAAM,iBAAiB,EAAE,qBAAqB;AAC9C,MAAM,aAAa,EAAE,IAAA,IAAQ;AAC7B,QAAQ,iBAAiB,EAAE;AAC3B,QAAQ,qBAAqB,CAAC,IAAI,EAAE,EAAE,uBAAuB,EAAE,CAAC,wBAAyB,EAAC,CAAC;AAC3F,QAAQ,iBAAiB,CAAC,MAAM,EAAE,SAAS,CAAC;;AAE5C;AACA;AACA;AACA,QAAQ,MAAM,KAAA,GAAQ,eAAe,EAAE;AACvC,QAAQ,MAAM,qBAAsB,GAAE,KAAK,CAAC,qBAAqB,EAAE;;AAEnE,QAAQ,KAAK,CAAC,qBAAqB,CAAC;AACpC,UAAU,GAAG,qBAAqB;AAClC,UAAU,OAAO,EAAE,QAAQ,CAAC,WAAW,EAAE,CAAC,OAAO;AACjD,UAAU,OAAO,EAAE,aAAa,CAAC,QAAQ,CAAC;AAC1C,UAAU,GAAG,EAAE,iCAAiC,CAAC,IAAI,CAAC;AACtD,SAAS,CAAC;AACV,OAAO;AACP,KAAK,CAAC;AACN,IAAI,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC;;AAEvC,IAAI,SAAS,UAAU,GAAS;AAChC,MAAM,IAAI,sBAAA,IAA0B,CAAC,aAAa,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,sBAAsB,CAAC,UAAU,CAAC,EAAE;AAC7G,QAAQ,MAAM,CAAC,IAAI,CAAC,0BAA0B,EAAE,QAAQ,CAAC;AACzD;AACA;;AAEA,IAAI,IAAI,qBAAsB,IAAG,sBAAsB,EAAE;AACzD,MAAM,sBAAsB,CAAC,gBAAgB,CAAC,kBAAkB,EAAE,MAAM;AACxE,QAAQ,UAAU,EAAE;AACpB,OAAO,CAAC;;AAER,MAAM,UAAU,EAAE;AAClB;AACA;;AAEA,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,8BAA8B;AACxC,IAAI,aAAa,CAAC,MAAM,EAAE;AAC1B,MAAM,IAAI,WAAW,GAAuB,eAAe,EAAE;;AAE7D,MAAM,SAAS,kBAAkB,GAAS;AAC1C,QAAQ,MAAM,UAAW,GAAE,iBAAiB,CAAC,MAAM,CAAC;;AAEpD,QAAQ,IAAI,UAAA,IAAc,CAAC,UAAU,CAAC,UAAU,CAAC,CAAC,SAAS,EAAE;AAC7D,UAAU,eAAe,MAAM,CAAC,GAAG,CAAC,CAAC,iDAAiD,EAAE,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,CAAC,CAAA,CAAA;AACA;AACA,UAAA,UAAA,CAAA,GAAA,EAAA;AACA;AACA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,qBAAA,EAAA,gBAAA,IAAA;AACA,QAAA,IAAA,SAAA,EAAA,KAAA,MAAA,EAAA;AACA,UAAA;AACA;;AAEA,QAAA,kBAAA,EAAA;;AAEA,QAAA,iBAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,OAAA,EAAA,eAAA,EAAA,EAAA,UAAA,EAAA,IAAA,CAAA,MAAA,EAAA,EAAA,CAAA;AACA,QAAA,eAAA,EAAA,CAAA,qBAAA,CAAA,EAAA,OAAA,EAAA,eAAA,EAAA,EAAA,UAAA,EAAA,IAAA,CAAA,MAAA,EAAA,EAAA,CAAA;;AAEA,QAAA,gBAAA,CAAA,MAAA,EAAA;AACA,UAAA,EAAA,EAAA,YAAA;AACA,UAAA,GAAA,gBAAA;AACA,SAAA,CAAA;AACA,OAAA,CAAA;;AAEA,MAAA,MAAA,CAAA,EAAA,CAAA,mBAAA,EAAA,CAAA,gBAAA,EAAA,YAAA,GAAA,EAAA,KAAA;AACA,QAAA,IAAA,SAAA,EAAA,KAAA,MAAA,EAAA;AACA,UAAA;AACA;AACA,QAAA,kBAAA,EAAA;;AAEA,QAAA,MAAA,WAAA,GAAA,YAAA,CAAA,WAAA,IAAA,cAAA,CAAA,cAAA,CAAA;AACA,QAAA,MAAA,OAAA,GAAA,YAAA,CAAA,OAAA,IAAA,cAAA,CAAA,SAAA,CAAA;;AAEA,QAAA,MAAA,kBAAA,GAAA,6BAAA,CAAA,WAAA,EAAA,OAAA,CAAA;AACA,QAAA,eAAA,EAAA,CAAA,qBAAA,CAAA,kBAAA,CAAA;;AAEA,QAAA,gBAAA,CAAA,MAAA,EAAA;AACA,UAAA,EAAA,EAAA,UAAA;AACA,UAAA,GAAA,gBAAA;AACA,SAAA,CAAA;AACA,OAAA,CAAA;;AAEA,MAAA,IAAA,MAAA,CAAA,QAAA,EAAA;AACA,QAAA,IAAA,kBAAA,EAAA;AACA,UAAA,MAAA,MAAA,GAAA,4BAAA,EAAA;AACA,UAAA,+BAAA,CAAA,MAAA,EAAA;AACA,YAAA,IAAA,EAAA,MAAA,CAAA,QAAA,CAAA,QAAA;AACA;AACA,YAAA,SAAA,EAAA,MAAA,GAAA,MAAA,GAAA,IAAA,GAAA,SAAA;AACA,YAAA,UAAA,EAAA;AACA,cAAA,CAAA,gCAAA,GAAA,KAAA;AACA,cAAA,CAAA,gCAAA,GAAA,uBAAA;AACA,aAAA;AACA,WAAA,CAAA;AACA;;AAEA,QAAA,IAAA,oBAAA,EAAA;AACA,UAAA,gCAAA,CAAA,CAAA,EAAA,EAAA,EAAA,IAAA,EAAA,KAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,YAAA,IAAA,IAAA,KAAA,SAAA,IAAA,WAAA,EAAA,OAAA,CAAA,EAAA,CAAA,KAAA,EAAA,EAAA;AACA,cAAA,WAAA,GAAA,SAAA;AACA,cAAA;AACA;;AAEA,YAAA,IAAA,IAAA,KAAA,EAAA,EAAA;AACA,cAAA,WAAA,GAAA,SAAA;AACA,cAAA,iCAAA,CAAA,MAAA,EAAA;AACA,gBAAA,IAAA,EAAA,MAAA,CAAA,QAAA,CAAA,QAAA;AACA,gBAAA,UAAA,EAAA;AACA,kBAAA,CAAA,gCAAA,GAAA,KAAA;AACA,kBAAA,CAAA,gCAAA,GAAA,yBAAA;AACA,iBAAA;AACA,eAAA,CAAA;AACA;AACA,WAAA,CAAA;AACA;AACA;;AAEA,MAAA,IAAA,kBAAA,EAAA;AACA,QAAA,8BAAA,EAAA;AACA;;AAEA,MAAA,IAAA,kBAAA,EAAA;AACA,QAAA,2BAAA,CAAA,MAAA,EAAA,WAAA,EAAA,YAAA,EAAA,gBAAA,EAAA,WAAA,CAAA;AACA;;AAEA,MAAA,IAAA,SAAA,EAAA;AACA,QAAA,8BAAA,EAAA;AACA;;AAEA,MAAA,0BAAA,CAAA,MAAA,EAAA;AACA,QAAA,UAAA;AACA,QAAA,QAAA;AACA,QAAA,2BAAA;AACA,QAAA,uBAAA,EAAA,MAAA,CAAA,UAAA,EAAA,CAAA,uBAAA;AACA,QAAA,0BAAA;AACA,QAAA,iBAAA;AACA,OAAA,CAAA;AACA,KAAA;AACA,GAAA;AACA,CAAA,CAAA;;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAAA,+BAAA;AACA,EAAA,MAAA;AACA,EAAA,WAAA;AACA,EAAA,YAAA;AACA,EAAA;AACA,EAAA,MAAA,CAAA,IAAA,CAAA,mBAAA,EAAA,WAAA,EAAA,YAAA,CAAA;AACA,EAAA,eAAA,EAAA,CAAA,kBAAA,CAAA,WAAA,CAAA,IAAA,CAAA;;AAEA,EAAA,OAAA,iBAAA,CAAA,MAAA,CAAA;AACA;;AAEA;AACA;AACA;AACA;AACA,SAAA,iCAAA,CAAA,MAAA,EAAA,WAAA,EAAA;AACA,EAAA,MAAA,CAAA,IAAA,CAAA,qBAAA,EAAA,WAAA,CAAA;;AAEA,EAAA,eAAA,EAAA,CAAA,kBAAA,CAAA,WAAA,CAAA,IAAA,CAAA;;AAEA,EAAA,OAAA,iBAAA,CAAA,MAAA,CAAA;AACA;;AAEA;AACA,SAAA,cAAA,CAAA,QAAA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA,MAAA,sBAAA,GAAA,MAAA,CAAA,QAAA;;AAEA,EAAA,MAAA,OAAA,GAAA,sBAAA,EAAA,aAAA,CAAA,CAAA,UAAA,EAAA,QAAA,CAAA,CAAA,CAAA,CAAA;AACA,EAAA,OAAA,OAAA,EAAA,YAAA,CAAA,SAAA,CAAA,IAAA,SAAA;AACA;;AAEA;AACA,SAAA,2BAAA;AACA,EAAA,MAAA;AACA,EAAA,WAAA;AACA,EAAA,YAAA;AACA,EAAA,gBAAA;AACA,EAAA,WAAA;AACA,EAAA;AACA;AACA;AACA;AACA;AACA,EAAA,MAAA,sBAAA,GAAA,MAAA,CAAA,QAAA;;AAEA,EAAA,IAAA,uBAAA;AACA,EAAA,MAAA,8BAAA,GAAA,MAAA;AACA,IAAA,MAAA,EAAA,GAAA,iBAAA;;AAEA,IAAA,MAAA,cAAA,GAAA,iBAAA,CAAA,MAAA,CAAA;AACA,IAAA,IAAA,cAAA,EAAA;AACA,MAAA,MAAA,iBAAA,GAAA,UAAA,CAAA,cAAA,CAAA,CAAA,EAAA;AACA,MAAA,IAAA,CAAA,YAAA,EAAA,UAAA,CAAA,CAAA,QAAA,CAAA,iBAAA,EAAA,EAAA;AACA,QAAA,WAAA;AACA,UAAA,MAAA,CAAA,IAAA,CAAA,CAAA,yBAAA,EAAA,EAAA,CAAA,2DAAA,CAAA,CAAA;AACA,QAAA,OAAA,SAAA;AACA;AACA;;AAEA,IAAA,IAAA,uBAAA,EAAA;AACA,MAAA,uBAAA,CAAA,YAAA,CAAA,iDAAA,EAAA,wBAAA,CAAA;AACA,MAAA,uBAAA,CAAA,GAAA,EAAA;AACA,MAAA,uBAAA,GAAA,SAAA;AACA;;AAEA,IAAA,IAAA,CAAA,WAAA,CAAA,IAAA,EAAA;AACA,MAAA,WAAA,IAAA,MAAA,CAAA,IAAA,CAAA,CAAA,yBAAA,EAAA,EAAA,CAAA,iDAAA,CAAA,CAAA;AACA,MAAA,OAAA,SAAA;AACA;;AAEA,IAAA,uBAAA,GAAA,aAAA;AACA,MAAA;AACA,QAAA,IAAA,EAAA,WAAA,CAAA,IAAA;AACA,QAAA,EAAA;AACA,QAAA,UAAA,EAAA;AACA,UAAA,CAAA,gCAAA,GAAA,WAAA,CAAA,MAAA,IAAA,KAAA;AACA,SAAA;AACA,OAAA;AACA,MAAA;AACA,QAAA,WAAA;AACA,QAAA,YAAA;AACA,QAAA,gBAAA;AACA,OAAA;AACA,KAAA;AACA,GAAA;;AAEA,EAAA,IAAA,sBAAA,EAAA;AACA,IAAA,gBAAA,CAAA,OAAA,EAAA,8BAAA,EAAA,EAAA,IAAA,EAAA,KAAA,EAAA,OAAA,EAAA,IAAA,EAAA,CAAA;AACA;AACA;;AAEA;AACA,MAAA,yBAAA,GAAA,kBAAA;AACA,SAAA,iBAAA,CAAA,MAAA,EAAA;AACA,EAAA,OAAA,CAAA,MAAA,GAAA,yBAAA,CAAA;AACA;;AAEA,SAAA,iBAAA,CAAA,MAAA,EAAA,IAAA,EAAA;AACA,EAAA,wBAAA,CAAA,MAAA,EAAA,yBAAA,EAAA,IAAA,CAAA;AACA;;;;"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { addXhrInstrumentationHandler, addPerformanceInstrumentationHandler,
|
|
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 =
|
|
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
|
|
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
|
|
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
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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;;;;"}
|