summaryrefslogtreecommitdiff
path: root/shared/logger/node_modules/@sentry-internal/tracing/esm/browser
diff options
context:
space:
mode:
authorrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
committerrxliuli <rxliuli@gmail.com>2025-11-04 05:03:50 +0800
commitbce557cc2dc767628bed6aac87301a1be7c5431b (patch)
treeb51a051228d01fe3306cd7626d4a96768aadb944 /shared/logger/node_modules/@sentry-internal/tracing/esm/browser
init commit
Diffstat (limited to 'shared/logger/node_modules/@sentry-internal/tracing/esm/browser')
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/backgroundtab.js36
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/browsertracing.js300
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/index.js484
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/utils.js25
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/request.js335
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/router.js64
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/types.js6
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getCLS.js105
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getFID.js63
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getLCP.js85
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/bindReporter.js28
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/generateUniqueID.js27
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getActivationStart.js25
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getNavigationEntry.js53
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getVisibilityWatcher.js54
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/initMetric.js46
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/observe.js37
-rw-r--r--shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/onHidden.js36
18 files changed, 1809 insertions, 0 deletions
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/backgroundtab.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/backgroundtab.js
new file mode 100644
index 0000000..62c1d20
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/backgroundtab.js
@@ -0,0 +1,36 @@
+import { getActiveTransaction } from '@sentry/core';
+import { logger } from '@sentry/utils';
+import { WINDOW } from './types.js';
+
+/**
+ * Add a listener that cancels and finishes a transaction when the global
+ * document is hidden.
+ */
+function registerBackgroundTabDetection() {
+ if (WINDOW && WINDOW.document) {
+ WINDOW.document.addEventListener('visibilitychange', () => {
+ const activeTransaction = getActiveTransaction() ;
+ if (WINDOW.document.hidden && activeTransaction) {
+ const statusType = 'cancelled';
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.log(
+ `[Tracing] Transaction: ${statusType} -> since tab moved to the background, op: ${activeTransaction.op}`,
+ );
+ // We should not set status if it is already set, this prevent important statuses like
+ // error or data loss from being overwritten on transaction.
+ if (!activeTransaction.status) {
+ activeTransaction.setStatus(statusType);
+ }
+ activeTransaction.setTag('visibilitychange', 'document.hidden');
+ activeTransaction.finish();
+ }
+ });
+ } else {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn('[Tracing] Could not set up background tab detection due to lack of global document');
+ }
+}
+
+export { registerBackgroundTabDetection };
+//# sourceMappingURL=backgroundtab.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/browsertracing.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/browsertracing.js
new file mode 100644
index 0000000..3b79fb3
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/browsertracing.js
@@ -0,0 +1,300 @@
+import { TRACING_DEFAULTS, addTracingExtensions, extractTraceparentData, startIdleTransaction, getActiveTransaction } from '@sentry/core';
+import { logger, baggageHeaderToDynamicSamplingContext, getDomElement } from '@sentry/utils';
+import { registerBackgroundTabDetection } from './backgroundtab.js';
+import { startTrackingWebVitals, startTrackingLongTasks, startTrackingInteractions, addPerformanceEntries } from './metrics/index.js';
+import { defaultRequestInstrumentationOptions, instrumentOutgoingRequests } from './request.js';
+import { instrumentRoutingWithDefaults } from './router.js';
+import { WINDOW } from './types.js';
+
+const BROWSER_TRACING_INTEGRATION_ID = 'BrowserTracing';
+
+/** Options for Browser Tracing integration */
+
+const DEFAULT_BROWSER_TRACING_OPTIONS = {
+ ...TRACING_DEFAULTS,
+ markBackgroundTransactions: true,
+ routingInstrumentation: instrumentRoutingWithDefaults,
+ startTransactionOnLocationChange: true,
+ startTransactionOnPageLoad: true,
+ enableLongTask: true,
+ ...defaultRequestInstrumentationOptions,
+};
+
+/**
+ * The Browser Tracing integration automatically instruments browser pageload/navigation
+ * actions as transactions, and captures requests, metrics and errors as spans.
+ *
+ * The integration can be configured with a variety of options, and can be extended to use
+ * any routing library. This integration uses {@see IdleTransaction} to create transactions.
+ */
+class BrowserTracing {
+ // This class currently doesn't have a static `id` field like the other integration classes, because it prevented
+ // @sentry/tracing from being treeshaken. Tree shakers do not like static fields, because they behave like side effects.
+ // TODO: Come up with a better plan, than using static fields on integration classes, and use that plan on all
+ // integrations.
+
+ /** Browser Tracing integration options */
+
+ /**
+ * @inheritDoc
+ */
+ __init() {this.name = BROWSER_TRACING_INTEGRATION_ID;}
+
+ __init2() {this._hasSetTracePropagationTargets = false;}
+
+ constructor(_options) {BrowserTracing.prototype.__init.call(this);BrowserTracing.prototype.__init2.call(this);
+ addTracingExtensions();
+
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)) {
+ this._hasSetTracePropagationTargets = !!(
+ _options &&
+ // eslint-disable-next-line deprecation/deprecation
+ (_options.tracePropagationTargets || _options.tracingOrigins)
+ );
+ }
+
+ this.options = {
+ ...DEFAULT_BROWSER_TRACING_OPTIONS,
+ ..._options,
+ };
+
+ // Special case: enableLongTask can be set in _experiments
+ // TODO (v8): Remove this in v8
+ if (this.options._experiments.enableLongTask !== undefined) {
+ this.options.enableLongTask = this.options._experiments.enableLongTask;
+ }
+
+ // TODO (v8): remove this block after tracingOrigins is removed
+ // Set tracePropagationTargets to tracingOrigins if specified by the user
+ // In case both are specified, tracePropagationTargets takes precedence
+ // eslint-disable-next-line deprecation/deprecation
+ if (_options && !_options.tracePropagationTargets && _options.tracingOrigins) {
+ // eslint-disable-next-line deprecation/deprecation
+ this.options.tracePropagationTargets = _options.tracingOrigins;
+ }
+
+ this._collectWebVitals = startTrackingWebVitals();
+ if (this.options.enableLongTask) {
+ startTrackingLongTasks();
+ }
+ if (this.options._experiments.enableInteractions) {
+ startTrackingInteractions();
+ }
+ }
+
+ /**
+ * @inheritDoc
+ */
+ setupOnce(_, getCurrentHub) {
+ this._getCurrentHub = getCurrentHub;
+ const hub = getCurrentHub();
+ const client = hub.getClient();
+ const clientOptions = client && client.getOptions();
+
+ const {
+ routingInstrumentation: instrumentRouting,
+ startTransactionOnLocationChange,
+ startTransactionOnPageLoad,
+ markBackgroundTransactions,
+ traceFetch,
+ traceXHR,
+ shouldCreateSpanForRequest,
+ _experiments,
+ } = this.options;
+
+ const clientOptionsTracePropagationTargets = clientOptions && clientOptions.tracePropagationTargets;
+ // There are three ways to configure tracePropagationTargets:
+ // 1. via top level client option `tracePropagationTargets`
+ // 2. via BrowserTracing option `tracePropagationTargets`
+ // 3. via BrowserTracing option `tracingOrigins` (deprecated)
+ //
+ // To avoid confusion, favour top level client option `tracePropagationTargets`, and fallback to
+ // BrowserTracing option `tracePropagationTargets` and then `tracingOrigins` (deprecated).
+ // This is done as it minimizes bundle size (we don't have to have undefined checks).
+ //
+ // If both 1 and either one of 2 or 3 are set (from above), we log out a warning.
+ const tracePropagationTargets = clientOptionsTracePropagationTargets || this.options.tracePropagationTargets;
+ if ((typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && this._hasSetTracePropagationTargets && clientOptionsTracePropagationTargets) {
+ logger.warn(
+ '[Tracing] The `tracePropagationTargets` option was set in the BrowserTracing integration and top level `Sentry.init`. The top level `Sentry.init` value is being used.',
+ );
+ }
+
+ instrumentRouting(
+ (context) => {
+ const transaction = this._createRouteTransaction(context);
+
+ this.options._experiments.onStartRouteTransaction &&
+ this.options._experiments.onStartRouteTransaction(transaction, context, getCurrentHub);
+
+ return transaction;
+ },
+ startTransactionOnPageLoad,
+ startTransactionOnLocationChange,
+ );
+
+ if (markBackgroundTransactions) {
+ registerBackgroundTabDetection();
+ }
+
+ if (_experiments.enableInteractions) {
+ this._registerInteractionListener();
+ }
+
+ instrumentOutgoingRequests({
+ traceFetch,
+ traceXHR,
+ tracePropagationTargets,
+ shouldCreateSpanForRequest,
+ _experiments: {
+ enableHTTPTimings: _experiments.enableHTTPTimings,
+ },
+ });
+ }
+
+ /** Create routing idle transaction. */
+ _createRouteTransaction(context) {
+ if (!this._getCurrentHub) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn(`[Tracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.`);
+ return undefined;
+ }
+
+ const { beforeNavigate, idleTimeout, finalTimeout, heartbeatInterval } = this.options;
+
+ const isPageloadTransaction = context.op === 'pageload';
+
+ const sentryTraceMetaTagValue = isPageloadTransaction ? getMetaContent('sentry-trace') : null;
+ const baggageMetaTagValue = isPageloadTransaction ? getMetaContent('baggage') : null;
+
+ const traceParentData = sentryTraceMetaTagValue ? extractTraceparentData(sentryTraceMetaTagValue) : undefined;
+ const dynamicSamplingContext = baggageMetaTagValue
+ ? baggageHeaderToDynamicSamplingContext(baggageMetaTagValue)
+ : undefined;
+
+ const expandedContext = {
+ ...context,
+ ...traceParentData,
+ metadata: {
+ ...context.metadata,
+ dynamicSamplingContext: traceParentData && !dynamicSamplingContext ? {} : dynamicSamplingContext,
+ },
+ trimEnd: true,
+ };
+
+ const modifiedContext = typeof beforeNavigate === 'function' ? beforeNavigate(expandedContext) : expandedContext;
+
+ // For backwards compatibility reasons, beforeNavigate can return undefined to "drop" the transaction (prevent it
+ // from being sent to Sentry).
+ const finalContext = modifiedContext === undefined ? { ...expandedContext, sampled: false } : modifiedContext;
+
+ // If `beforeNavigate` set a custom name, record that fact
+ finalContext.metadata =
+ finalContext.name !== expandedContext.name
+ ? { ...finalContext.metadata, source: 'custom' }
+ : finalContext.metadata;
+
+ this._latestRouteName = finalContext.name;
+ this._latestRouteSource = finalContext.metadata && finalContext.metadata.source;
+
+ if (finalContext.sampled === false) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`);
+ }
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`);
+
+ const hub = this._getCurrentHub();
+ const { location } = WINDOW;
+
+ const idleTransaction = startIdleTransaction(
+ hub,
+ finalContext,
+ idleTimeout,
+ finalTimeout,
+ true,
+ { location }, // for use in the tracesSampler
+ heartbeatInterval,
+ );
+ idleTransaction.registerBeforeFinishCallback(transaction => {
+ this._collectWebVitals();
+ addPerformanceEntries(transaction);
+ });
+
+ return idleTransaction ;
+ }
+
+ /** Start listener for interaction transactions */
+ _registerInteractionListener() {
+ let inflightInteractionTransaction;
+ const registerInteractionTransaction = () => {
+ const { idleTimeout, finalTimeout, heartbeatInterval } = this.options;
+ const op = 'ui.action.click';
+
+ const currentTransaction = getActiveTransaction();
+ if (currentTransaction && currentTransaction.op && ['navigation', 'pageload'].includes(currentTransaction.op)) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn(
+ `[Tracing] Did not create ${op} transaction because a pageload or navigation transaction is in progress.`,
+ );
+ return undefined;
+ }
+
+ if (inflightInteractionTransaction) {
+ inflightInteractionTransaction.setFinishReason('interactionInterrupted');
+ inflightInteractionTransaction.finish();
+ inflightInteractionTransaction = undefined;
+ }
+
+ if (!this._getCurrentHub) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn(`[Tracing] Did not create ${op} transaction because _getCurrentHub is invalid.`);
+ return undefined;
+ }
+
+ if (!this._latestRouteName) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`);
+ return undefined;
+ }
+
+ const hub = this._getCurrentHub();
+ const { location } = WINDOW;
+
+ const context = {
+ name: this._latestRouteName,
+ op,
+ trimEnd: true,
+ metadata: {
+ source: this._latestRouteSource || 'url',
+ },
+ };
+
+ inflightInteractionTransaction = startIdleTransaction(
+ hub,
+ context,
+ idleTimeout,
+ finalTimeout,
+ true,
+ { location }, // for use in the tracesSampler
+ heartbeatInterval,
+ );
+ };
+
+ ['click'].forEach(type => {
+ addEventListener(type, registerInteractionTransaction, { once: false, capture: true });
+ });
+ }
+}
+
+/** Returns the value of a meta tag */
+function getMetaContent(metaName) {
+ // Can't specify generic to `getDomElement` because tracing can be used
+ // in a variety of environments, have to disable `no-unsafe-member-access`
+ // as a result.
+ const metaTag = getDomElement(`meta[name=${metaName}]`);
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ return metaTag ? metaTag.getAttribute('content') : null;
+}
+
+export { BROWSER_TRACING_INTEGRATION_ID, BrowserTracing, getMetaContent };
+//# sourceMappingURL=browsertracing.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/index.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/index.js
new file mode 100644
index 0000000..5bca7af
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/index.js
@@ -0,0 +1,484 @@
+import { getActiveTransaction } from '@sentry/core';
+import { browserPerformanceTimeOrigin, logger, htmlTreeAsString } from '@sentry/utils';
+import { WINDOW } from '../types.js';
+import { onCLS } from '../web-vitals/getCLS.js';
+import { onFID } from '../web-vitals/getFID.js';
+import { onLCP } from '../web-vitals/getLCP.js';
+import { getVisibilityWatcher } from '../web-vitals/lib/getVisibilityWatcher.js';
+import { observe } from '../web-vitals/lib/observe.js';
+import { _startChild, isMeasurementValue } from './utils.js';
+
+/**
+ * Converts from milliseconds to seconds
+ * @param time time in ms
+ */
+function msToSec(time) {
+ return time / 1000;
+}
+
+function getBrowserPerformanceAPI() {
+ // @ts-ignore we want to make sure all of these are available, even if TS is sure they are
+ return WINDOW && WINDOW.addEventListener && WINDOW.performance;
+}
+
+let _performanceCursor = 0;
+
+let _measurements = {};
+let _lcpEntry;
+let _clsEntry;
+
+/**
+ * Start tracking web vitals
+ *
+ * @returns A function that forces web vitals collection
+ */
+function startTrackingWebVitals() {
+ const performance = getBrowserPerformanceAPI();
+ if (performance && browserPerformanceTimeOrigin) {
+ // @ts-ignore we want to make sure all of these are available, even if TS is sure they are
+ if (performance.mark) {
+ WINDOW.performance.mark('sentry-tracing-init');
+ }
+ _trackFID();
+ const clsCallback = _trackCLS();
+ const lcpCallback = _trackLCP();
+
+ return () => {
+ if (clsCallback) {
+ clsCallback();
+ }
+ if (lcpCallback) {
+ lcpCallback();
+ }
+ };
+ }
+
+ return () => undefined;
+}
+
+/**
+ * Start tracking long tasks.
+ */
+function startTrackingLongTasks() {
+ const entryHandler = (entries) => {
+ for (const entry of entries) {
+ const transaction = getActiveTransaction() ;
+ if (!transaction) {
+ return;
+ }
+ const startTime = msToSec((browserPerformanceTimeOrigin ) + entry.startTime);
+ const duration = msToSec(entry.duration);
+
+ transaction.startChild({
+ description: 'Main UI thread blocked',
+ op: 'ui.long-task',
+ startTimestamp: startTime,
+ endTimestamp: startTime + duration,
+ });
+ }
+ };
+
+ observe('longtask', entryHandler);
+}
+
+/**
+ * Start tracking interaction events.
+ */
+function startTrackingInteractions() {
+ const entryHandler = (entries) => {
+ for (const entry of entries) {
+ const transaction = getActiveTransaction() ;
+ if (!transaction) {
+ return;
+ }
+
+ if (entry.name === 'click') {
+ const startTime = msToSec((browserPerformanceTimeOrigin ) + entry.startTime);
+ const duration = msToSec(entry.duration);
+
+ transaction.startChild({
+ description: htmlTreeAsString(entry.target),
+ op: `ui.interaction.${entry.name}`,
+ startTimestamp: startTime,
+ endTimestamp: startTime + duration,
+ });
+ }
+ }
+ };
+
+ observe('event', entryHandler, { durationThreshold: 0 });
+}
+
+/** Starts tracking the Cumulative Layout Shift on the current page. */
+function _trackCLS() {
+ // See:
+ // https://web.dev/evolving-cls/
+ // https://web.dev/cls-web-tooling/
+ return onCLS(metric => {
+ const entry = metric.entries.pop();
+ if (!entry) {
+ return;
+ }
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding CLS');
+ _measurements['cls'] = { value: metric.value, unit: '' };
+ _clsEntry = entry ;
+ });
+}
+
+/** Starts tracking the Largest Contentful Paint on the current page. */
+function _trackLCP() {
+ return onLCP(metric => {
+ const entry = metric.entries.pop();
+ if (!entry) {
+ return;
+ }
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding LCP');
+ _measurements['lcp'] = { value: metric.value, unit: 'millisecond' };
+ _lcpEntry = entry ;
+ });
+}
+
+/** Starts tracking the First Input Delay on the current page. */
+function _trackFID() {
+ onFID(metric => {
+ const entry = metric.entries.pop();
+ if (!entry) {
+ return;
+ }
+
+ const timeOrigin = msToSec(browserPerformanceTimeOrigin );
+ const startTime = msToSec(entry.startTime);
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding FID');
+ _measurements['fid'] = { value: metric.value, unit: 'millisecond' };
+ _measurements['mark.fid'] = { value: timeOrigin + startTime, unit: 'second' };
+ });
+}
+
+/** Add performance related spans to a transaction */
+function addPerformanceEntries(transaction) {
+ const performance = getBrowserPerformanceAPI();
+ if (!performance || !WINDOW.performance.getEntries || !browserPerformanceTimeOrigin) {
+ // Gatekeeper if performance API not available
+ return;
+ }
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Tracing] Adding & adjusting spans using Performance API');
+ const timeOrigin = msToSec(browserPerformanceTimeOrigin);
+
+ const performanceEntries = performance.getEntries();
+
+ let responseStartTimestamp;
+ let requestStartTimestamp;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ performanceEntries.slice(_performanceCursor).forEach((entry) => {
+ const startTime = msToSec(entry.startTime);
+ const duration = msToSec(entry.duration);
+
+ if (transaction.op === 'navigation' && timeOrigin + startTime < transaction.startTimestamp) {
+ return;
+ }
+
+ switch (entry.entryType) {
+ case 'navigation': {
+ _addNavigationSpans(transaction, entry, timeOrigin);
+ responseStartTimestamp = timeOrigin + msToSec(entry.responseStart);
+ requestStartTimestamp = timeOrigin + msToSec(entry.requestStart);
+ break;
+ }
+ case 'mark':
+ case 'paint':
+ case 'measure': {
+ _addMeasureSpans(transaction, entry, startTime, duration, timeOrigin);
+
+ // capture web vitals
+ const firstHidden = getVisibilityWatcher();
+ // Only report if the page wasn't hidden prior to the web vital.
+ const shouldRecord = entry.startTime < firstHidden.firstHiddenTime;
+
+ if (entry.name === 'first-paint' && shouldRecord) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding FP');
+ _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' };
+ }
+ if (entry.name === 'first-contentful-paint' && shouldRecord) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding FCP');
+ _measurements['fcp'] = { value: entry.startTime, unit: 'millisecond' };
+ }
+ break;
+ }
+ case 'resource': {
+ const resourceName = (entry.name ).replace(WINDOW.location.origin, '');
+ _addResourceSpans(transaction, entry, resourceName, startTime, duration, timeOrigin);
+ break;
+ }
+ // Ignore other entry types.
+ }
+ });
+
+ _performanceCursor = Math.max(performanceEntries.length - 1, 0);
+
+ _trackNavigator(transaction);
+
+ // Measurements are only available for pageload transactions
+ if (transaction.op === 'pageload') {
+ // Generate TTFB (Time to First Byte), which measured as the time between the beginning of the transaction and the
+ // start of the response in milliseconds
+ if (typeof responseStartTimestamp === 'number') {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding TTFB');
+ _measurements['ttfb'] = {
+ value: (responseStartTimestamp - transaction.startTimestamp) * 1000,
+ unit: 'millisecond',
+ };
+
+ if (typeof requestStartTimestamp === 'number' && requestStartTimestamp <= responseStartTimestamp) {
+ // Capture the time spent making the request and receiving the first byte of the response.
+ // This is the time between the start of the request and the start of the response in milliseconds.
+ _measurements['ttfb.requestTime'] = {
+ value: (responseStartTimestamp - requestStartTimestamp) * 1000,
+ unit: 'millisecond',
+ };
+ }
+ }
+
+ ['fcp', 'fp', 'lcp'].forEach(name => {
+ if (!_measurements[name] || timeOrigin >= transaction.startTimestamp) {
+ return;
+ }
+ // The web vitals, fcp, fp, lcp, and ttfb, all measure relative to timeOrigin.
+ // Unfortunately, timeOrigin is not captured within the transaction span data, so these web vitals will need
+ // to be adjusted to be relative to transaction.startTimestamp.
+ const oldValue = _measurements[name].value;
+ const measurementTimestamp = timeOrigin + msToSec(oldValue);
+
+ // normalizedValue should be in milliseconds
+ const normalizedValue = Math.abs((measurementTimestamp - transaction.startTimestamp) * 1000);
+ const delta = normalizedValue - oldValue;
+
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) &&
+ logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`);
+ _measurements[name].value = normalizedValue;
+ });
+
+ const fidMark = _measurements['mark.fid'];
+ if (fidMark && _measurements['fid']) {
+ // create span for FID
+ _startChild(transaction, {
+ description: 'first input delay',
+ endTimestamp: fidMark.value + msToSec(_measurements['fid'].value),
+ op: 'ui.action',
+ startTimestamp: fidMark.value,
+ });
+
+ // Delete mark.fid as we don't want it to be part of final payload
+ delete _measurements['mark.fid'];
+ }
+
+ // If FCP is not recorded we should not record the cls value
+ // according to the new definition of CLS.
+ if (!('fcp' in _measurements)) {
+ delete _measurements.cls;
+ }
+
+ Object.keys(_measurements).forEach(measurementName => {
+ transaction.setMeasurement(
+ measurementName,
+ _measurements[measurementName].value,
+ _measurements[measurementName].unit,
+ );
+ });
+
+ _tagMetricInfo(transaction);
+ }
+
+ _lcpEntry = undefined;
+ _clsEntry = undefined;
+ _measurements = {};
+}
+
+/** Create measure related spans */
+function _addMeasureSpans(
+ transaction,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ entry,
+ startTime,
+ duration,
+ timeOrigin,
+) {
+ const measureStartTimestamp = timeOrigin + startTime;
+ const measureEndTimestamp = measureStartTimestamp + duration;
+
+ _startChild(transaction, {
+ description: entry.name ,
+ endTimestamp: measureEndTimestamp,
+ op: entry.entryType ,
+ startTimestamp: measureStartTimestamp,
+ });
+
+ return measureStartTimestamp;
+}
+
+/** Instrument navigation entries */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function _addNavigationSpans(transaction, entry, timeOrigin) {
+ ['unloadEvent', 'redirect', 'domContentLoadedEvent', 'loadEvent', 'connect'].forEach(event => {
+ _addPerformanceNavigationTiming(transaction, entry, event, timeOrigin);
+ });
+ _addPerformanceNavigationTiming(transaction, entry, 'secureConnection', timeOrigin, 'TLS/SSL', 'connectEnd');
+ _addPerformanceNavigationTiming(transaction, entry, 'fetch', timeOrigin, 'cache', 'domainLookupStart');
+ _addPerformanceNavigationTiming(transaction, entry, 'domainLookup', timeOrigin, 'DNS');
+ _addRequest(transaction, entry, timeOrigin);
+}
+
+/** Create performance navigation related spans */
+function _addPerformanceNavigationTiming(
+ transaction,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ entry,
+ event,
+ timeOrigin,
+ description,
+ eventEnd,
+) {
+ const end = eventEnd ? (entry[eventEnd] ) : (entry[`${event}End`] );
+ const start = entry[`${event}Start`] ;
+ if (!start || !end) {
+ return;
+ }
+ _startChild(transaction, {
+ op: 'browser',
+ description: description || event,
+ startTimestamp: timeOrigin + msToSec(start),
+ endTimestamp: timeOrigin + msToSec(end),
+ });
+}
+
+/** Create request and response related spans */
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+function _addRequest(transaction, entry, timeOrigin) {
+ _startChild(transaction, {
+ op: 'browser',
+ description: 'request',
+ startTimestamp: timeOrigin + msToSec(entry.requestStart ),
+ endTimestamp: timeOrigin + msToSec(entry.responseEnd ),
+ });
+
+ _startChild(transaction, {
+ op: 'browser',
+ description: 'response',
+ startTimestamp: timeOrigin + msToSec(entry.responseStart ),
+ endTimestamp: timeOrigin + msToSec(entry.responseEnd ),
+ });
+}
+
+/** Create resource-related spans */
+function _addResourceSpans(
+ transaction,
+ entry,
+ resourceName,
+ startTime,
+ duration,
+ timeOrigin,
+) {
+ // we already instrument based on fetch and xhr, so we don't need to
+ // duplicate spans here.
+ if (entry.initiatorType === 'xmlhttprequest' || entry.initiatorType === 'fetch') {
+ return;
+ }
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const data = {};
+ if ('transferSize' in entry) {
+ data['http.response_transfer_size'] = entry.transferSize;
+ }
+ if ('encodedBodySize' in entry) {
+ data['http.response_content_length'] = entry.encodedBodySize;
+ }
+ if ('decodedBodySize' in entry) {
+ data['http.decoded_response_content_length'] = entry.decodedBodySize;
+ }
+ if ('renderBlockingStatus' in entry) {
+ data['resource.render_blocking_status'] = entry.renderBlockingStatus;
+ }
+
+ const startTimestamp = timeOrigin + startTime;
+ const endTimestamp = startTimestamp + duration;
+
+ _startChild(transaction, {
+ description: resourceName,
+ endTimestamp,
+ op: entry.initiatorType ? `resource.${entry.initiatorType}` : 'resource.other',
+ startTimestamp,
+ data,
+ });
+}
+
+/**
+ * Capture the information of the user agent.
+ */
+function _trackNavigator(transaction) {
+ const navigator = WINDOW.navigator ;
+ if (!navigator) {
+ return;
+ }
+
+ // track network connectivity
+ const connection = navigator.connection;
+ if (connection) {
+ if (connection.effectiveType) {
+ transaction.setTag('effectiveConnectionType', connection.effectiveType);
+ }
+
+ if (connection.type) {
+ transaction.setTag('connectionType', connection.type);
+ }
+
+ if (isMeasurementValue(connection.rtt)) {
+ _measurements['connection.rtt'] = { value: connection.rtt, unit: 'millisecond' };
+ }
+ }
+
+ if (isMeasurementValue(navigator.deviceMemory)) {
+ transaction.setTag('deviceMemory', `${navigator.deviceMemory} GB`);
+ }
+
+ if (isMeasurementValue(navigator.hardwareConcurrency)) {
+ transaction.setTag('hardwareConcurrency', String(navigator.hardwareConcurrency));
+ }
+}
+
+/** Add LCP / CLS data to transaction to allow debugging */
+function _tagMetricInfo(transaction) {
+ if (_lcpEntry) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding LCP Data');
+
+ // Capture Properties of the LCP element that contributes to the LCP.
+
+ if (_lcpEntry.element) {
+ transaction.setTag('lcp.element', htmlTreeAsString(_lcpEntry.element));
+ }
+
+ if (_lcpEntry.id) {
+ transaction.setTag('lcp.id', _lcpEntry.id);
+ }
+
+ if (_lcpEntry.url) {
+ // Trim URL to the first 200 characters.
+ transaction.setTag('lcp.url', _lcpEntry.url.trim().slice(0, 200));
+ }
+
+ transaction.setTag('lcp.size', _lcpEntry.size);
+ }
+
+ // See: https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift
+ if (_clsEntry && _clsEntry.sources) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log('[Measurements] Adding CLS Data');
+ _clsEntry.sources.forEach((source, index) =>
+ transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)),
+ );
+ }
+}
+
+export { _addMeasureSpans, _addResourceSpans, addPerformanceEntries, startTrackingInteractions, startTrackingLongTasks, startTrackingWebVitals };
+//# sourceMappingURL=index.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/utils.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/utils.js
new file mode 100644
index 0000000..ecb4873
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/metrics/utils.js
@@ -0,0 +1,25 @@
+/**
+ * Checks if a given value is a valid measurement value.
+ */
+function isMeasurementValue(value) {
+ return typeof value === 'number' && isFinite(value);
+}
+
+/**
+ * Helper function to start child on transactions. This function will make sure that the transaction will
+ * use the start timestamp of the created child span if it is earlier than the transactions actual
+ * start timestamp.
+ */
+function _startChild(transaction, { startTimestamp, ...ctx }) {
+ if (startTimestamp && transaction.startTimestamp > startTimestamp) {
+ transaction.startTimestamp = startTimestamp;
+ }
+
+ return transaction.startChild({
+ startTimestamp,
+ ...ctx,
+ });
+}
+
+export { _startChild, isMeasurementValue };
+//# sourceMappingURL=utils.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/request.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/request.js
new file mode 100644
index 0000000..d505546
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/request.js
@@ -0,0 +1,335 @@
+import { _optionalChain } from '@sentry/utils/esm/buildPolyfills';
+import { hasTracingEnabled, getCurrentHub } from '@sentry/core';
+import { addInstrumentationHandler, browserPerformanceTimeOrigin, dynamicSamplingContextToSentryBaggageHeader, isInstanceOf, BAGGAGE_HEADER_NAME, SENTRY_XHR_DATA_KEY, stringMatchesSomePattern } from '@sentry/utils';
+
+/* eslint-disable max-lines */
+
+const DEFAULT_TRACE_PROPAGATION_TARGETS = ['localhost', /^\/(?!\/)/];
+
+/** Options for Request Instrumentation */
+
+const defaultRequestInstrumentationOptions = {
+ traceFetch: true,
+ traceXHR: true,
+ // TODO (v8): Remove this property
+ tracingOrigins: DEFAULT_TRACE_PROPAGATION_TARGETS,
+ tracePropagationTargets: DEFAULT_TRACE_PROPAGATION_TARGETS,
+ _experiments: {},
+};
+
+/** Registers span creators for xhr and fetch requests */
+function instrumentOutgoingRequests(_options) {
+ // eslint-disable-next-line deprecation/deprecation
+ const { traceFetch, traceXHR, tracePropagationTargets, tracingOrigins, shouldCreateSpanForRequest, _experiments } = {
+ traceFetch: defaultRequestInstrumentationOptions.traceFetch,
+ traceXHR: defaultRequestInstrumentationOptions.traceXHR,
+ ..._options,
+ };
+
+ const shouldCreateSpan =
+ typeof shouldCreateSpanForRequest === 'function' ? shouldCreateSpanForRequest : (_) => true;
+
+ // TODO(v8) Remove tracingOrigins here
+ // The only reason we're passing it in here is because this instrumentOutgoingRequests function is publicly exported
+ // and we don't want to break the API. We can remove it in v8.
+ const shouldAttachHeadersWithTargets = (url) =>
+ shouldAttachHeaders(url, tracePropagationTargets || tracingOrigins);
+
+ const spans = {};
+
+ if (traceFetch) {
+ addInstrumentationHandler('fetch', (handlerData) => {
+ const createdSpan = fetchCallback(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans);
+ if (_optionalChain([_experiments, 'optionalAccess', _2 => _2.enableHTTPTimings]) && createdSpan) {
+ addHTTPTimings(createdSpan);
+ }
+ });
+ }
+
+ if (traceXHR) {
+ addInstrumentationHandler('xhr', (handlerData) => {
+ const createdSpan = xhrCallback(handlerData, shouldCreateSpan, shouldAttachHeadersWithTargets, spans);
+ if (_optionalChain([_experiments, 'optionalAccess', _3 => _3.enableHTTPTimings]) && createdSpan) {
+ addHTTPTimings(createdSpan);
+ }
+ });
+ }
+}
+
+/**
+ * Creates a temporary observer to listen to the next fetch/xhr resourcing timings,
+ * so that when timings hit their per-browser limit they don't need to be removed.
+ *
+ * @param span A span that has yet to be finished, must contain `url` on data.
+ */
+function addHTTPTimings(span) {
+ const url = span.data.url;
+ const observer = new PerformanceObserver(list => {
+ const entries = list.getEntries() ;
+ entries.forEach(entry => {
+ if ((entry.initiatorType === 'fetch' || entry.initiatorType === 'xmlhttprequest') && entry.name.endsWith(url)) {
+ const spanData = resourceTimingEntryToSpanData(entry);
+ spanData.forEach(data => span.setData(...data));
+ observer.disconnect();
+ }
+ });
+ });
+ observer.observe({
+ entryTypes: ['resource'],
+ });
+}
+
+function resourceTimingEntryToSpanData(resourceTiming) {
+ const version = resourceTiming.nextHopProtocol.split('/')[1] || 'none';
+
+ const timingSpanData = [];
+ if (version) {
+ timingSpanData.push(['network.protocol.version', version]);
+ }
+
+ if (!browserPerformanceTimeOrigin) {
+ return timingSpanData;
+ }
+ return [
+ ...timingSpanData,
+ ['http.request.connect_start', (browserPerformanceTimeOrigin + resourceTiming.connectStart) / 1000],
+ ['http.request.request_start', (browserPerformanceTimeOrigin + resourceTiming.requestStart) / 1000],
+ ['http.request.response_start', (browserPerformanceTimeOrigin + resourceTiming.responseStart) / 1000],
+ ];
+}
+
+/**
+ * A function that determines whether to attach tracing headers to a request.
+ * This was extracted from `instrumentOutgoingRequests` to make it easier to test shouldAttachHeaders.
+ * We only export this fuction for testing purposes.
+ */
+function shouldAttachHeaders(url, tracePropagationTargets) {
+ return stringMatchesSomePattern(url, tracePropagationTargets || DEFAULT_TRACE_PROPAGATION_TARGETS);
+}
+
+/**
+ * Create and track fetch request spans
+ *
+ * @returns Span if a span was created, otherwise void.
+ */
+function fetchCallback(
+ handlerData,
+ shouldCreateSpan,
+ shouldAttachHeaders,
+ spans,
+) {
+ if (!hasTracingEnabled() || !(handlerData.fetchData && shouldCreateSpan(handlerData.fetchData.url))) {
+ return;
+ }
+
+ if (handlerData.endTimestamp) {
+ const spanId = handlerData.fetchData.__span;
+ if (!spanId) return;
+
+ const span = spans[spanId];
+ if (span) {
+ if (handlerData.response) {
+ // TODO (kmclb) remove this once types PR goes through
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ span.setHttpStatus(handlerData.response.status);
+
+ const contentLength =
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ handlerData.response && handlerData.response.headers && handlerData.response.headers.get('content-length');
+
+ const contentLengthNum = parseInt(contentLength);
+ if (contentLengthNum > 0) {
+ span.setData('http.response_content_length', contentLengthNum);
+ }
+ } else if (handlerData.error) {
+ span.setStatus('internal_error');
+ }
+ span.finish();
+
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+ delete spans[spanId];
+ }
+ return;
+ }
+
+ const currentSpan = getCurrentHub().getScope().getSpan();
+ const activeTransaction = currentSpan && currentSpan.transaction;
+
+ if (currentSpan && activeTransaction) {
+ const { method, url } = handlerData.fetchData;
+ const span = currentSpan.startChild({
+ data: {
+ url,
+ type: 'fetch',
+ 'http.method': method,
+ },
+ description: `${method} ${url}`,
+ op: 'http.client',
+ });
+
+ handlerData.fetchData.__span = span.spanId;
+ spans[span.spanId] = span;
+
+ const request = handlerData.args[0];
+
+ // In case the user hasn't set the second argument of a fetch call we default it to `{}`.
+ handlerData.args[1] = handlerData.args[1] || {};
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ const options = handlerData.args[1];
+
+ if (shouldAttachHeaders(handlerData.fetchData.url)) {
+ options.headers = addTracingHeadersToFetchRequest(
+ request,
+ activeTransaction.getDynamicSamplingContext(),
+ span,
+ options,
+ );
+ }
+ return span;
+ }
+}
+
+/**
+ * Adds sentry-trace and baggage headers to the various forms of fetch headers
+ */
+function addTracingHeadersToFetchRequest(
+ request, // unknown is actually type Request but we can't export DOM types from this package,
+ dynamicSamplingContext,
+ span,
+ options
+
+,
+) {
+ const sentryBaggageHeader = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext);
+ const sentryTraceHeader = span.toTraceparent();
+
+ const headers =
+ typeof Request !== 'undefined' && isInstanceOf(request, Request) ? (request ).headers : options.headers;
+
+ if (!headers) {
+ return { 'sentry-trace': sentryTraceHeader, baggage: sentryBaggageHeader };
+ } else if (typeof Headers !== 'undefined' && isInstanceOf(headers, Headers)) {
+ const newHeaders = new Headers(headers );
+
+ newHeaders.append('sentry-trace', sentryTraceHeader);
+
+ if (sentryBaggageHeader) {
+ // If the same header is appended multiple times the browser will merge the values into a single request header.
+ // Its therefore safe to simply push a "baggage" entry, even though there might already be another baggage header.
+ newHeaders.append(BAGGAGE_HEADER_NAME, sentryBaggageHeader);
+ }
+
+ return newHeaders ;
+ } else if (Array.isArray(headers)) {
+ const newHeaders = [...headers, ['sentry-trace', sentryTraceHeader]];
+
+ if (sentryBaggageHeader) {
+ // If there are multiple entries with the same key, the browser will merge the values into a single request header.
+ // Its therefore safe to simply push a "baggage" entry, even though there might already be another baggage header.
+ newHeaders.push([BAGGAGE_HEADER_NAME, sentryBaggageHeader]);
+ }
+
+ return newHeaders ;
+ } else {
+ const existingBaggageHeader = 'baggage' in headers ? headers.baggage : undefined;
+ const newBaggageHeaders = [];
+
+ if (Array.isArray(existingBaggageHeader)) {
+ newBaggageHeaders.push(...existingBaggageHeader);
+ } else if (existingBaggageHeader) {
+ newBaggageHeaders.push(existingBaggageHeader);
+ }
+
+ if (sentryBaggageHeader) {
+ newBaggageHeaders.push(sentryBaggageHeader);
+ }
+
+ return {
+ ...(headers ),
+ 'sentry-trace': sentryTraceHeader,
+ baggage: newBaggageHeaders.length > 0 ? newBaggageHeaders.join(',') : undefined,
+ };
+ }
+}
+
+/**
+ * Create and track xhr request spans
+ *
+ * @returns Span if a span was created, otherwise void.
+ */
+function xhrCallback(
+ handlerData,
+ shouldCreateSpan,
+ shouldAttachHeaders,
+ spans,
+) {
+ const xhr = handlerData.xhr;
+ const sentryXhrData = xhr && xhr[SENTRY_XHR_DATA_KEY];
+
+ if (
+ !hasTracingEnabled() ||
+ (xhr && xhr.__sentry_own_request__) ||
+ !(xhr && sentryXhrData && shouldCreateSpan(sentryXhrData.url))
+ ) {
+ return;
+ }
+
+ // check first if the request has finished and is tracked by an existing span which should now end
+ if (handlerData.endTimestamp) {
+ const spanId = xhr.__sentry_xhr_span_id__;
+ if (!spanId) return;
+
+ const span = spans[spanId];
+ if (span) {
+ span.setHttpStatus(sentryXhrData.status_code);
+ span.finish();
+
+ // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
+ delete spans[spanId];
+ }
+ return;
+ }
+
+ const currentSpan = getCurrentHub().getScope().getSpan();
+ const activeTransaction = currentSpan && currentSpan.transaction;
+
+ if (currentSpan && activeTransaction) {
+ const span = currentSpan.startChild({
+ data: {
+ ...sentryXhrData.data,
+ type: 'xhr',
+ 'http.method': sentryXhrData.method,
+ url: sentryXhrData.url,
+ },
+ description: `${sentryXhrData.method} ${sentryXhrData.url}`,
+ op: 'http.client',
+ });
+
+ xhr.__sentry_xhr_span_id__ = span.spanId;
+ spans[xhr.__sentry_xhr_span_id__] = span;
+
+ if (xhr.setRequestHeader && shouldAttachHeaders(sentryXhrData.url)) {
+ try {
+ xhr.setRequestHeader('sentry-trace', span.toTraceparent());
+
+ const dynamicSamplingContext = activeTransaction.getDynamicSamplingContext();
+ const sentryBaggageHeader = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext);
+
+ if (sentryBaggageHeader) {
+ // From MDN: "If this method is called several times with the same header, the values are merged into one single request header."
+ // We can therefore simply set a baggage header without checking what was there before
+ // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/setRequestHeader
+ xhr.setRequestHeader(BAGGAGE_HEADER_NAME, sentryBaggageHeader);
+ }
+ } catch (_) {
+ // Error: InvalidStateError: Failed to execute 'setRequestHeader' on 'XMLHttpRequest': The object's state must be OPENED.
+ }
+ }
+
+ return span;
+ }
+}
+
+export { DEFAULT_TRACE_PROPAGATION_TARGETS, addTracingHeadersToFetchRequest, defaultRequestInstrumentationOptions, instrumentOutgoingRequests, shouldAttachHeaders };
+//# sourceMappingURL=request.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/router.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/router.js
new file mode 100644
index 0000000..8c70bef
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/router.js
@@ -0,0 +1,64 @@
+import { logger, browserPerformanceTimeOrigin, addInstrumentationHandler } from '@sentry/utils';
+import { WINDOW } from './types.js';
+
+/**
+ * Default function implementing pageload and navigation transactions
+ */
+function instrumentRoutingWithDefaults(
+ customStartTransaction,
+ startTransactionOnPageLoad = true,
+ startTransactionOnLocationChange = true,
+) {
+ if (!WINDOW || !WINDOW.location) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.warn('Could not initialize routing instrumentation due to invalid location');
+ return;
+ }
+
+ let startingUrl = WINDOW.location.href;
+
+ let activeTransaction;
+ if (startTransactionOnPageLoad) {
+ activeTransaction = customStartTransaction({
+ name: WINDOW.location.pathname,
+ // pageload should always start at timeOrigin (and needs to be in s, not ms)
+ startTimestamp: browserPerformanceTimeOrigin ? browserPerformanceTimeOrigin / 1000 : undefined,
+ op: 'pageload',
+ metadata: { source: 'url' },
+ });
+ }
+
+ if (startTransactionOnLocationChange) {
+ addInstrumentationHandler('history', ({ to, from }) => {
+ /**
+ * This early return is there to account for some cases where a navigation transaction starts right after
+ * long-running pageload. We make sure that if `from` is undefined and a valid `startingURL` exists, we don't
+ * create an uneccessary navigation transaction.
+ *
+ * This was hard to duplicate, but this behavior stopped as soon as this fix was applied. This issue might also
+ * only be caused in certain development environments where the usage of a hot module reloader is causing
+ * errors.
+ */
+ if (from === undefined && startingUrl && startingUrl.indexOf(to) !== -1) {
+ startingUrl = undefined;
+ return;
+ }
+
+ if (from !== to) {
+ startingUrl = undefined;
+ if (activeTransaction) {
+ (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__) && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`);
+ // If there's an open transaction on the scope, we need to finish it before creating an new one.
+ activeTransaction.finish();
+ }
+ activeTransaction = customStartTransaction({
+ name: WINDOW.location.pathname,
+ op: 'navigation',
+ metadata: { source: 'url' },
+ });
+ }
+ });
+ }
+}
+
+export { instrumentRoutingWithDefaults };
+//# sourceMappingURL=router.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/types.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/types.js
new file mode 100644
index 0000000..b01c87e
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/types.js
@@ -0,0 +1,6 @@
+import { GLOBAL_OBJ } from '@sentry/utils';
+
+const WINDOW = GLOBAL_OBJ ;
+
+export { WINDOW };
+//# sourceMappingURL=types.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getCLS.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getCLS.js
new file mode 100644
index 0000000..22f1922
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getCLS.js
@@ -0,0 +1,105 @@
+import { bindReporter } from './lib/bindReporter.js';
+import { initMetric } from './lib/initMetric.js';
+import { observe } from './lib/observe.js';
+import { onHidden } from './lib/onHidden.js';
+
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Calculates the [CLS](https://web.dev/cls/) value for the current page and
+ * calls the `callback` function once the value is ready to be reported, along
+ * with all `layout-shift` performance entries that were used in the metric
+ * value calculation. The reported value is a `double` (corresponding to a
+ * [layout shift score](https://web.dev/cls/#layout-shift-score)).
+ *
+ * If the `reportAllChanges` configuration option is set to `true`, the
+ * `callback` function will be called as soon as the value is initially
+ * determined as well as any time the value changes throughout the page
+ * lifespan.
+ *
+ * _**Important:** CLS should be continually monitored for changes throughout
+ * the entire lifespan of a page—including if the user returns to the page after
+ * it's been hidden/backgrounded. However, since browsers often [will not fire
+ * additional callbacks once the user has backgrounded a
+ * page](https://developer.chrome.com/blog/page-lifecycle-api/#advice-hidden),
+ * `callback` is always called when the page's visibility state changes to
+ * hidden. As a result, the `callback` function might be called multiple times
+ * during the same page load._
+ */
+const onCLS = (onReport) => {
+ const metric = initMetric('CLS', 0);
+ let report;
+
+ let sessionValue = 0;
+ let sessionEntries = [];
+
+ // const handleEntries = (entries: Metric['entries']) => {
+ const handleEntries = (entries) => {
+ entries.forEach(entry => {
+ // Only count layout shifts without recent user input.
+ if (!entry.hadRecentInput) {
+ const firstSessionEntry = sessionEntries[0];
+ const lastSessionEntry = sessionEntries[sessionEntries.length - 1];
+
+ // If the entry occurred less than 1 second after the previous entry and
+ // less than 5 seconds after the first entry in the session, include the
+ // entry in the current session. Otherwise, start a new session.
+ if (
+ sessionValue &&
+ sessionEntries.length !== 0 &&
+ entry.startTime - lastSessionEntry.startTime < 1000 &&
+ entry.startTime - firstSessionEntry.startTime < 5000
+ ) {
+ sessionValue += entry.value;
+ sessionEntries.push(entry);
+ } else {
+ sessionValue = entry.value;
+ sessionEntries = [entry];
+ }
+
+ // If the current session value is larger than the current CLS value,
+ // update CLS and the entries contributing to it.
+ if (sessionValue > metric.value) {
+ metric.value = sessionValue;
+ metric.entries = sessionEntries;
+ if (report) {
+ report();
+ }
+ }
+ }
+ });
+ };
+
+ const po = observe('layout-shift', handleEntries);
+ if (po) {
+ report = bindReporter(onReport, metric);
+
+ const stopListening = () => {
+ handleEntries(po.takeRecords() );
+ report(true);
+ };
+
+ onHidden(stopListening);
+
+ return stopListening;
+ }
+
+ return;
+};
+
+export { onCLS };
+//# sourceMappingURL=getCLS.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getFID.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getFID.js
new file mode 100644
index 0000000..fc135c8
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getFID.js
@@ -0,0 +1,63 @@
+import { bindReporter } from './lib/bindReporter.js';
+import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
+import { initMetric } from './lib/initMetric.js';
+import { observe } from './lib/observe.js';
+import { onHidden } from './lib/onHidden.js';
+
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Calculates the [FID](https://web.dev/fid/) value for the current page and
+ * calls the `callback` function once the value is ready, along with the
+ * relevant `first-input` performance entry used to determine the value. The
+ * reported value is a `DOMHighResTimeStamp`.
+ *
+ * _**Important:** since FID is only reported after the user interacts with the
+ * page, it's possible that it will not be reported for some page loads._
+ */
+const onFID = (onReport) => {
+ const visibilityWatcher = getVisibilityWatcher();
+ const metric = initMetric('FID');
+ // eslint-disable-next-line prefer-const
+ let report;
+
+ const handleEntry = (entry) => {
+ // Only report if the page wasn't hidden prior to the first input.
+ if (entry.startTime < visibilityWatcher.firstHiddenTime) {
+ metric.value = entry.processingStart - entry.startTime;
+ metric.entries.push(entry);
+ report(true);
+ }
+ };
+
+ const handleEntries = (entries) => {
+ (entries ).forEach(handleEntry);
+ };
+
+ const po = observe('first-input', handleEntries);
+ report = bindReporter(onReport, metric);
+
+ if (po) {
+ onHidden(() => {
+ handleEntries(po.takeRecords() );
+ po.disconnect();
+ }, true);
+ }
+};
+
+export { onFID };
+//# sourceMappingURL=getFID.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getLCP.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getLCP.js
new file mode 100644
index 0000000..0d3c610
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/getLCP.js
@@ -0,0 +1,85 @@
+import { bindReporter } from './lib/bindReporter.js';
+import { getActivationStart } from './lib/getActivationStart.js';
+import { getVisibilityWatcher } from './lib/getVisibilityWatcher.js';
+import { initMetric } from './lib/initMetric.js';
+import { observe } from './lib/observe.js';
+import { onHidden } from './lib/onHidden.js';
+
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const reportedMetricIDs = {};
+
+/**
+ * Calculates the [LCP](https://web.dev/lcp/) value for the current page and
+ * calls the `callback` function once the value is ready (along with the
+ * relevant `largest-contentful-paint` performance entry used to determine the
+ * value). The reported value is a `DOMHighResTimeStamp`.
+ */
+const onLCP = (onReport) => {
+ const visibilityWatcher = getVisibilityWatcher();
+ const metric = initMetric('LCP');
+ let report;
+
+ const handleEntries = (entries) => {
+ const lastEntry = entries[entries.length - 1] ;
+ if (lastEntry) {
+ // The startTime attribute returns the value of the renderTime if it is
+ // not 0, and the value of the loadTime otherwise. The activationStart
+ // reference is used because LCP should be relative to page activation
+ // rather than navigation start if the page was prerendered.
+ const value = Math.max(lastEntry.startTime - getActivationStart(), 0);
+
+ // Only report if the page wasn't hidden prior to LCP.
+ if (value < visibilityWatcher.firstHiddenTime) {
+ metric.value = value;
+ metric.entries = [lastEntry];
+ report();
+ }
+ }
+ };
+
+ const po = observe('largest-contentful-paint', handleEntries);
+
+ if (po) {
+ report = bindReporter(onReport, metric);
+
+ const stopListening = () => {
+ if (!reportedMetricIDs[metric.id]) {
+ handleEntries(po.takeRecords() );
+ po.disconnect();
+ reportedMetricIDs[metric.id] = true;
+ report(true);
+ }
+ };
+
+ // Stop listening after input. Note: while scrolling is an input that
+ // stop LCP observation, it's unreliable since it can be programmatically
+ // generated. See: https://github.com/GoogleChrome/web-vitals/issues/75
+ ['keydown', 'click'].forEach(type => {
+ addEventListener(type, stopListening, { once: true, capture: true });
+ });
+
+ onHidden(stopListening, true);
+
+ return stopListening;
+ }
+
+ return;
+};
+
+export { onLCP };
+//# sourceMappingURL=getLCP.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/bindReporter.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/bindReporter.js
new file mode 100644
index 0000000..dc66278
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/bindReporter.js
@@ -0,0 +1,28 @@
+const bindReporter = (
+ callback,
+ metric,
+ reportAllChanges,
+) => {
+ let prevValue;
+ let delta;
+ return (forceReport) => {
+ if (metric.value >= 0) {
+ if (forceReport || reportAllChanges) {
+ delta = metric.value - (prevValue || 0);
+
+ // Report the metric if there's a non-zero delta or if no previous
+ // value exists (which can happen in the case of the document becoming
+ // hidden when the metric value is 0).
+ // See: https://github.com/GoogleChrome/web-vitals/issues/14
+ if (delta || prevValue === undefined) {
+ prevValue = metric.value;
+ metric.delta = delta;
+ callback(metric);
+ }
+ }
+ }
+ };
+};
+
+export { bindReporter };
+//# sourceMappingURL=bindReporter.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/generateUniqueID.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/generateUniqueID.js
new file mode 100644
index 0000000..dfde3bb
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/generateUniqueID.js
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Performantly generate a unique, 30-char string by combining a version
+ * number, the current timestamp with a 13-digit number integer.
+ * @return {string}
+ */
+const generateUniqueID = () => {
+ return `v3-${Date.now()}-${Math.floor(Math.random() * (9e12 - 1)) + 1e12}`;
+};
+
+export { generateUniqueID };
+//# sourceMappingURL=generateUniqueID.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getActivationStart.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getActivationStart.js
new file mode 100644
index 0000000..e7b7f65
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getActivationStart.js
@@ -0,0 +1,25 @@
+import { getNavigationEntry } from './getNavigationEntry.js';
+
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const getActivationStart = () => {
+ const navEntry = getNavigationEntry();
+ return (navEntry && navEntry.activationStart) || 0;
+};
+
+export { getActivationStart };
+//# sourceMappingURL=getActivationStart.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getNavigationEntry.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getNavigationEntry.js
new file mode 100644
index 0000000..89a65a5
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getNavigationEntry.js
@@ -0,0 +1,53 @@
+import { WINDOW } from '../../types.js';
+
+/*
+ * Copyright 2022 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const getNavigationEntryFromPerformanceTiming = () => {
+ // eslint-disable-next-line deprecation/deprecation
+ const timing = WINDOW.performance.timing;
+ // eslint-disable-next-line deprecation/deprecation
+ const type = WINDOW.performance.navigation.type;
+
+ const navigationEntry = {
+ entryType: 'navigation',
+ startTime: 0,
+ type: type == 2 ? 'back_forward' : type === 1 ? 'reload' : 'navigate',
+ };
+
+ for (const key in timing) {
+ if (key !== 'navigationStart' && key !== 'toJSON') {
+ // eslint-disable-next-line deprecation/deprecation
+ navigationEntry[key] = Math.max((timing[key ] ) - timing.navigationStart, 0);
+ }
+ }
+ return navigationEntry ;
+};
+
+const getNavigationEntry = () => {
+ if (WINDOW.__WEB_VITALS_POLYFILL__) {
+ return (
+ WINDOW.performance &&
+ ((performance.getEntriesByType && performance.getEntriesByType('navigation')[0]) ||
+ getNavigationEntryFromPerformanceTiming())
+ );
+ } else {
+ return WINDOW.performance && performance.getEntriesByType && performance.getEntriesByType('navigation')[0];
+ }
+};
+
+export { getNavigationEntry };
+//# sourceMappingURL=getNavigationEntry.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getVisibilityWatcher.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getVisibilityWatcher.js
new file mode 100644
index 0000000..fb86cc2
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/getVisibilityWatcher.js
@@ -0,0 +1,54 @@
+import { WINDOW } from '../../types.js';
+import { onHidden } from './onHidden.js';
+
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+let firstHiddenTime = -1;
+
+const initHiddenTime = () => {
+ // If the document is hidden and not prerendering, assume it was always
+ // hidden and the page was loaded in the background.
+ return WINDOW.document.visibilityState === 'hidden' && !WINDOW.document.prerendering ? 0 : Infinity;
+};
+
+const trackChanges = () => {
+ // Update the time if/when the document becomes hidden.
+ onHidden(({ timeStamp }) => {
+ firstHiddenTime = timeStamp;
+ }, true);
+};
+
+const getVisibilityWatcher = (
+
+) => {
+ if (firstHiddenTime < 0) {
+ // If the document is hidden when this code runs, assume it was hidden
+ // since navigation start. This isn't a perfect heuristic, but it's the
+ // best we can do until an API is available to support querying past
+ // visibilityState.
+ firstHiddenTime = initHiddenTime();
+ trackChanges();
+ }
+ return {
+ get firstHiddenTime() {
+ return firstHiddenTime;
+ },
+ };
+};
+
+export { getVisibilityWatcher };
+//# sourceMappingURL=getVisibilityWatcher.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/initMetric.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/initMetric.js
new file mode 100644
index 0000000..498c63d
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/initMetric.js
@@ -0,0 +1,46 @@
+import { WINDOW } from '../../types.js';
+import { generateUniqueID } from './generateUniqueID.js';
+import { getActivationStart } from './getActivationStart.js';
+import { getNavigationEntry } from './getNavigationEntry.js';
+
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const initMetric = (name, value) => {
+ const navEntry = getNavigationEntry();
+ let navigationType = 'navigate';
+
+ if (navEntry) {
+ if (WINDOW.document.prerendering || getActivationStart() > 0) {
+ navigationType = 'prerender';
+ } else {
+ navigationType = navEntry.type.replace(/_/g, '-') ;
+ }
+ }
+
+ return {
+ name,
+ value: typeof value === 'undefined' ? -1 : value,
+ rating: 'good', // Will be updated if the value changes.
+ delta: 0,
+ entries: [],
+ id: generateUniqueID(),
+ navigationType,
+ };
+};
+
+export { initMetric };
+//# sourceMappingURL=initMetric.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/observe.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/observe.js
new file mode 100644
index 0000000..94b7351
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/observe.js
@@ -0,0 +1,37 @@
+/**
+ * Takes a performance entry type and a callback function, and creates a
+ * `PerformanceObserver` instance that will observe the specified entry type
+ * with buffering enabled and call the callback _for each entry_.
+ *
+ * This function also feature-detects entry support and wraps the logic in a
+ * try/catch to avoid errors in unsupporting browsers.
+ */
+const observe = (
+ type,
+ callback,
+ opts,
+) => {
+ try {
+ if (PerformanceObserver.supportedEntryTypes.includes(type)) {
+ const po = new PerformanceObserver(list => {
+ callback(list.getEntries() );
+ });
+ po.observe(
+ Object.assign(
+ {
+ type,
+ buffered: true,
+ },
+ opts || {},
+ ) ,
+ );
+ return po;
+ }
+ } catch (e) {
+ // Do nothing.
+ }
+ return;
+};
+
+export { observe };
+//# sourceMappingURL=observe.js.map
diff --git a/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/onHidden.js b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/onHidden.js
new file mode 100644
index 0000000..78bb128
--- /dev/null
+++ b/shared/logger/node_modules/@sentry-internal/tracing/esm/browser/web-vitals/lib/onHidden.js
@@ -0,0 +1,36 @@
+import { WINDOW } from '../../types.js';
+
+/*
+ * Copyright 2020 Google LLC
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+const onHidden = (cb, once) => {
+ const onHiddenOrPageHide = (event) => {
+ if (event.type === 'pagehide' || WINDOW.document.visibilityState === 'hidden') {
+ cb(event);
+ if (once) {
+ removeEventListener('visibilitychange', onHiddenOrPageHide, true);
+ removeEventListener('pagehide', onHiddenOrPageHide, true);
+ }
+ }
+ };
+ addEventListener('visibilitychange', onHiddenOrPageHide, true);
+ // Some browsers have buggy implementations of visibilitychange,
+ // so we use pagehide in addition, just to be safe.
+ addEventListener('pagehide', onHiddenOrPageHide, true);
+};
+
+export { onHidden };
+//# sourceMappingURL=onHidden.js.map