mirror of
https://github.com/MarSeventh/CloudFlare-ImgBed.git
synced 2026-04-29 16:36:30 +00:00
init
This commit is contained in:
94
node_modules/@sentry/core/esm/api.js
generated
vendored
Normal file
94
node_modules/@sentry/core/esm/api.js
generated
vendored
Normal file
@@ -0,0 +1,94 @@
|
||||
import { makeDsn, dsnToString, urlEncode } from '@sentry/utils';
|
||||
|
||||
const SENTRY_API_VERSION = '7';
|
||||
|
||||
/** Returns the prefix to construct Sentry ingestion API endpoints. */
|
||||
function getBaseApiEndpoint(dsn) {
|
||||
const protocol = dsn.protocol ? `${dsn.protocol}:` : '';
|
||||
const port = dsn.port ? `:${dsn.port}` : '';
|
||||
return `${protocol}//${dsn.host}${port}${dsn.path ? `/${dsn.path}` : ''}/api/`;
|
||||
}
|
||||
|
||||
/** Returns the ingest API endpoint for target. */
|
||||
function _getIngestEndpoint(dsn) {
|
||||
return `${getBaseApiEndpoint(dsn)}${dsn.projectId}/envelope/`;
|
||||
}
|
||||
|
||||
/** Returns a URL-encoded string with auth config suitable for a query string. */
|
||||
function _encodedAuth(dsn, sdkInfo) {
|
||||
return urlEncode({
|
||||
// We send only the minimum set of required information. See
|
||||
// https://github.com/getsentry/sentry-javascript/issues/2572.
|
||||
sentry_key: dsn.publicKey,
|
||||
sentry_version: SENTRY_API_VERSION,
|
||||
...(sdkInfo && { sentry_client: `${sdkInfo.name}/${sdkInfo.version}` }),
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the envelope endpoint URL with auth in the query string.
|
||||
*
|
||||
* Sending auth as part of the query string and not as custom HTTP headers avoids CORS preflight requests.
|
||||
*/
|
||||
function getEnvelopeEndpointWithUrlEncodedAuth(
|
||||
dsn,
|
||||
// TODO (v8): Remove `tunnelOrOptions` in favor of `options`, and use the substitute code below
|
||||
// options: ClientOptions = {} as ClientOptions,
|
||||
tunnelOrOptions = {} ,
|
||||
) {
|
||||
// TODO (v8): Use this code instead
|
||||
// const { tunnel, _metadata = {} } = options;
|
||||
// return tunnel ? tunnel : `${_getIngestEndpoint(dsn)}?${_encodedAuth(dsn, _metadata.sdk)}`;
|
||||
|
||||
const tunnel = typeof tunnelOrOptions === 'string' ? tunnelOrOptions : tunnelOrOptions.tunnel;
|
||||
const sdkInfo =
|
||||
typeof tunnelOrOptions === 'string' || !tunnelOrOptions._metadata ? undefined : tunnelOrOptions._metadata.sdk;
|
||||
|
||||
return tunnel ? tunnel : `${_getIngestEndpoint(dsn)}?${_encodedAuth(dsn, sdkInfo)}`;
|
||||
}
|
||||
|
||||
/** Returns the url to the report dialog endpoint. */
|
||||
function getReportDialogEndpoint(
|
||||
dsnLike,
|
||||
dialogOptions
|
||||
|
||||
,
|
||||
) {
|
||||
const dsn = makeDsn(dsnLike);
|
||||
if (!dsn) {
|
||||
return '';
|
||||
}
|
||||
|
||||
const endpoint = `${getBaseApiEndpoint(dsn)}embed/error-page/`;
|
||||
|
||||
let encodedOptions = `dsn=${dsnToString(dsn)}`;
|
||||
for (const key in dialogOptions) {
|
||||
if (key === 'dsn') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === 'onClose') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (key === 'user') {
|
||||
const user = dialogOptions.user;
|
||||
if (!user) {
|
||||
continue;
|
||||
}
|
||||
if (user.name) {
|
||||
encodedOptions += `&name=${encodeURIComponent(user.name)}`;
|
||||
}
|
||||
if (user.email) {
|
||||
encodedOptions += `&email=${encodeURIComponent(user.email)}`;
|
||||
}
|
||||
} else {
|
||||
encodedOptions += `&${encodeURIComponent(key)}=${encodeURIComponent(dialogOptions[key] )}`;
|
||||
}
|
||||
}
|
||||
|
||||
return `${endpoint}?${encodedOptions}`;
|
||||
}
|
||||
|
||||
export { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint };
|
||||
//# sourceMappingURL=api.js.map
|
||||
1
node_modules/@sentry/core/esm/api.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/api.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
809
node_modules/@sentry/core/esm/baseclient.js
generated
vendored
Normal file
809
node_modules/@sentry/core/esm/baseclient.js
generated
vendored
Normal file
@@ -0,0 +1,809 @@
|
||||
import { makeDsn, logger, checkOrSetAlreadyCaught, isParameterizedString, isPrimitive, resolvedSyncPromise, addItemToEnvelope, createAttachmentEnvelopeItem, SyncPromise, rejectedSyncPromise, SentryError, isThenable, isPlainObject } from '@sentry/utils';
|
||||
import { getEnvelopeEndpointWithUrlEncodedAuth } from './api.js';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
import { createEventEnvelope, createSessionEnvelope } from './envelope.js';
|
||||
import { getClient } from './exports.js';
|
||||
import { getIsolationScope } from './hub.js';
|
||||
import { setupIntegration, afterSetupIntegrations, setupIntegrations } from './integration.js';
|
||||
import { createMetricEnvelope } from './metrics/envelope.js';
|
||||
import { updateSession } from './session.js';
|
||||
import { getDynamicSamplingContextFromClient } from './tracing/dynamicSamplingContext.js';
|
||||
import { prepareEvent } from './utils/prepareEvent.js';
|
||||
|
||||
const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured.";
|
||||
|
||||
/**
|
||||
* Base implementation for all JavaScript SDK clients.
|
||||
*
|
||||
* Call the constructor with the corresponding options
|
||||
* specific to the client subclass. To access these options later, use
|
||||
* {@link Client.getOptions}.
|
||||
*
|
||||
* If a Dsn is specified in the options, it will be parsed and stored. Use
|
||||
* {@link Client.getDsn} to retrieve the Dsn at any moment. In case the Dsn is
|
||||
* invalid, the constructor will throw a {@link SentryException}. Note that
|
||||
* without a valid Dsn, the SDK will not send any events to Sentry.
|
||||
*
|
||||
* Before sending an event, it is passed through
|
||||
* {@link BaseClient._prepareEvent} to add SDK information and scope data
|
||||
* (breadcrumbs and context). To add more custom information, override this
|
||||
* method and extend the resulting prepared event.
|
||||
*
|
||||
* To issue automatically created events (e.g. via instrumentation), use
|
||||
* {@link Client.captureEvent}. It will prepare the event and pass it through
|
||||
* the callback lifecycle. To issue auto-breadcrumbs, use
|
||||
* {@link Client.addBreadcrumb}.
|
||||
*
|
||||
* @example
|
||||
* class NodeClient extends BaseClient<NodeOptions> {
|
||||
* public constructor(options: NodeOptions) {
|
||||
* super(options);
|
||||
* }
|
||||
*
|
||||
* // ...
|
||||
* }
|
||||
*/
|
||||
class BaseClient {
|
||||
/**
|
||||
* A reference to a metrics aggregator
|
||||
*
|
||||
* @experimental Note this is alpha API. It may experience breaking changes in the future.
|
||||
*/
|
||||
|
||||
/** Options passed to the SDK. */
|
||||
|
||||
/** The client Dsn, if specified in options. Without this Dsn, the SDK will be disabled. */
|
||||
|
||||
/** Array of set up integrations. */
|
||||
|
||||
/** Indicates whether this client's integrations have been set up. */
|
||||
|
||||
/** Number of calls being processed */
|
||||
|
||||
/** Holds flushable */
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
|
||||
/**
|
||||
* Initializes this client instance.
|
||||
*
|
||||
* @param options Options for the client.
|
||||
*/
|
||||
constructor(options) {
|
||||
this._options = options;
|
||||
this._integrations = {};
|
||||
this._integrationsInitialized = false;
|
||||
this._numProcessing = 0;
|
||||
this._outcomes = {};
|
||||
this._hooks = {};
|
||||
this._eventProcessors = [];
|
||||
|
||||
if (options.dsn) {
|
||||
this._dsn = makeDsn(options.dsn);
|
||||
} else {
|
||||
DEBUG_BUILD && logger.warn('No DSN provided, client will not send events.');
|
||||
}
|
||||
|
||||
if (this._dsn) {
|
||||
const url = getEnvelopeEndpointWithUrlEncodedAuth(this._dsn, options);
|
||||
this._transport = options.transport({
|
||||
tunnel: this._options.tunnel,
|
||||
recordDroppedEvent: this.recordDroppedEvent.bind(this),
|
||||
...options.transportOptions,
|
||||
url,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
||||
captureException(exception, hint, scope) {
|
||||
// ensure we haven't captured this very object before
|
||||
if (checkOrSetAlreadyCaught(exception)) {
|
||||
DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
let eventId = hint && hint.event_id;
|
||||
|
||||
this._process(
|
||||
this.eventFromException(exception, hint)
|
||||
.then(event => this._captureEvent(event, hint, scope))
|
||||
.then(result => {
|
||||
eventId = result;
|
||||
}),
|
||||
);
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
captureMessage(
|
||||
message,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
level,
|
||||
hint,
|
||||
scope,
|
||||
) {
|
||||
let eventId = hint && hint.event_id;
|
||||
|
||||
const eventMessage = isParameterizedString(message) ? message : String(message);
|
||||
|
||||
const promisedEvent = isPrimitive(message)
|
||||
? this.eventFromMessage(eventMessage, level, hint)
|
||||
: this.eventFromException(message, hint);
|
||||
|
||||
this._process(
|
||||
promisedEvent
|
||||
.then(event => this._captureEvent(event, hint, scope))
|
||||
.then(result => {
|
||||
eventId = result;
|
||||
}),
|
||||
);
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
captureEvent(event, hint, scope) {
|
||||
// ensure we haven't captured this very object before
|
||||
if (hint && hint.originalException && checkOrSetAlreadyCaught(hint.originalException)) {
|
||||
DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR);
|
||||
return;
|
||||
}
|
||||
|
||||
let eventId = hint && hint.event_id;
|
||||
|
||||
const sdkProcessingMetadata = event.sdkProcessingMetadata || {};
|
||||
const capturedSpanScope = sdkProcessingMetadata.capturedSpanScope;
|
||||
|
||||
this._process(
|
||||
this._captureEvent(event, hint, capturedSpanScope || scope).then(result => {
|
||||
eventId = result;
|
||||
}),
|
||||
);
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
captureSession(session) {
|
||||
if (!(typeof session.release === 'string')) {
|
||||
DEBUG_BUILD && logger.warn('Discarded session because of missing or non-string release');
|
||||
} else {
|
||||
this.sendSession(session);
|
||||
// After sending, we set init false to indicate it's not the first occurrence
|
||||
updateSession(session, { init: false });
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getDsn() {
|
||||
return this._dsn;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getOptions() {
|
||||
return this._options;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see SdkMetadata in @sentry/types
|
||||
*
|
||||
* @return The metadata of the SDK
|
||||
*/
|
||||
getSdkMetadata() {
|
||||
return this._options._metadata;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getTransport() {
|
||||
return this._transport;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
flush(timeout) {
|
||||
const transport = this._transport;
|
||||
if (transport) {
|
||||
if (this.metricsAggregator) {
|
||||
this.metricsAggregator.flush();
|
||||
}
|
||||
return this._isClientDoneProcessing(timeout).then(clientFinished => {
|
||||
return transport.flush(timeout).then(transportFlushed => clientFinished && transportFlushed);
|
||||
});
|
||||
} else {
|
||||
return resolvedSyncPromise(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
close(timeout) {
|
||||
return this.flush(timeout).then(result => {
|
||||
this.getOptions().enabled = false;
|
||||
if (this.metricsAggregator) {
|
||||
this.metricsAggregator.close();
|
||||
}
|
||||
return result;
|
||||
});
|
||||
}
|
||||
|
||||
/** Get all installed event processors. */
|
||||
getEventProcessors() {
|
||||
return this._eventProcessors;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
addEventProcessor(eventProcessor) {
|
||||
this._eventProcessors.push(eventProcessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is an internal function to setup all integrations that should run on the client.
|
||||
* @deprecated Use `client.init()` instead.
|
||||
*/
|
||||
setupIntegrations(forceInitialize) {
|
||||
if ((forceInitialize && !this._integrationsInitialized) || (this._isEnabled() && !this._integrationsInitialized)) {
|
||||
this._setupIntegrations();
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
init() {
|
||||
if (this._isEnabled()) {
|
||||
this._setupIntegrations();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an installed integration by its `id`.
|
||||
*
|
||||
* @returns The installed integration or `undefined` if no integration with that `id` was installed.
|
||||
* @deprecated Use `getIntegrationByName()` instead.
|
||||
*/
|
||||
getIntegrationById(integrationId) {
|
||||
return this.getIntegrationByName(integrationId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an installed integration by its name.
|
||||
*
|
||||
* @returns The installed integration or `undefined` if no integration with that `name` was installed.
|
||||
*/
|
||||
getIntegrationByName(integrationName) {
|
||||
return this._integrations[integrationName] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the client's instance of the given integration class, it any.
|
||||
* @deprecated Use `getIntegrationByName()` instead.
|
||||
*/
|
||||
getIntegration(integration) {
|
||||
try {
|
||||
return (this._integrations[integration.id] ) || null;
|
||||
} catch (_oO) {
|
||||
DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
addIntegration(integration) {
|
||||
const isAlreadyInstalled = this._integrations[integration.name];
|
||||
|
||||
// This hook takes care of only installing if not already installed
|
||||
setupIntegration(this, integration, this._integrations);
|
||||
// Here we need to check manually to make sure to not run this multiple times
|
||||
if (!isAlreadyInstalled) {
|
||||
afterSetupIntegrations(this, [integration]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
sendEvent(event, hint = {}) {
|
||||
this.emit('beforeSendEvent', event, hint);
|
||||
|
||||
let env = createEventEnvelope(event, this._dsn, this._options._metadata, this._options.tunnel);
|
||||
|
||||
for (const attachment of hint.attachments || []) {
|
||||
env = addItemToEnvelope(
|
||||
env,
|
||||
createAttachmentEnvelopeItem(
|
||||
attachment,
|
||||
this._options.transportOptions && this._options.transportOptions.textEncoder,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const promise = this._sendEnvelope(env);
|
||||
if (promise) {
|
||||
promise.then(sendResponse => this.emit('afterSendEvent', event, sendResponse), null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
sendSession(session) {
|
||||
const env = createSessionEnvelope(session, this._dsn, this._options._metadata, this._options.tunnel);
|
||||
|
||||
// _sendEnvelope should not throw
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this._sendEnvelope(env);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
recordDroppedEvent(reason, category, _event) {
|
||||
// Note: we use `event` in replay, where we overwrite this hook.
|
||||
|
||||
if (this._options.sendClientReports) {
|
||||
// We want to track each category (error, transaction, session, replay_event) separately
|
||||
// but still keep the distinction between different type of outcomes.
|
||||
// We could use nested maps, but it's much easier to read and type this way.
|
||||
// A correct type for map-based implementation if we want to go that route
|
||||
// would be `Partial<Record<SentryRequestType, Partial<Record<Outcome, number>>>>`
|
||||
// With typescript 4.1 we could even use template literal types
|
||||
const key = `${reason}:${category}`;
|
||||
DEBUG_BUILD && logger.log(`Adding outcome: "${key}"`);
|
||||
|
||||
// The following works because undefined + 1 === NaN and NaN is falsy
|
||||
this._outcomes[key] = this._outcomes[key] + 1 || 1;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
captureAggregateMetrics(metricBucketItems) {
|
||||
DEBUG_BUILD && logger.log(`Flushing aggregated metrics, number of metrics: ${metricBucketItems.length}`);
|
||||
const metricsEnvelope = createMetricEnvelope(
|
||||
metricBucketItems,
|
||||
this._dsn,
|
||||
this._options._metadata,
|
||||
this._options.tunnel,
|
||||
);
|
||||
|
||||
// _sendEnvelope should not throw
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this._sendEnvelope(metricsEnvelope);
|
||||
}
|
||||
|
||||
// Keep on() & emit() signatures in sync with types' client.ts interface
|
||||
/* eslint-disable @typescript-eslint/unified-signatures */
|
||||
|
||||
/** @inheritdoc */
|
||||
|
||||
/** @inheritdoc */
|
||||
on(hook, callback) {
|
||||
if (!this._hooks[hook]) {
|
||||
this._hooks[hook] = [];
|
||||
}
|
||||
|
||||
// @ts-expect-error We assue the types are correct
|
||||
this._hooks[hook].push(callback);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
|
||||
/** @inheritdoc */
|
||||
emit(hook, ...rest) {
|
||||
if (this._hooks[hook]) {
|
||||
this._hooks[hook].forEach(callback => callback(...rest));
|
||||
}
|
||||
}
|
||||
|
||||
/* eslint-enable @typescript-eslint/unified-signatures */
|
||||
|
||||
/** Setup integrations for this client. */
|
||||
_setupIntegrations() {
|
||||
const { integrations } = this._options;
|
||||
this._integrations = setupIntegrations(this, integrations);
|
||||
afterSetupIntegrations(this, integrations);
|
||||
|
||||
// TODO v8: We don't need this flag anymore
|
||||
this._integrationsInitialized = true;
|
||||
}
|
||||
|
||||
/** Updates existing session based on the provided event */
|
||||
_updateSessionFromEvent(session, event) {
|
||||
let crashed = false;
|
||||
let errored = false;
|
||||
const exceptions = event.exception && event.exception.values;
|
||||
|
||||
if (exceptions) {
|
||||
errored = true;
|
||||
|
||||
for (const ex of exceptions) {
|
||||
const mechanism = ex.mechanism;
|
||||
if (mechanism && mechanism.handled === false) {
|
||||
crashed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// A session is updated and that session update is sent in only one of the two following scenarios:
|
||||
// 1. Session with non terminal status and 0 errors + an error occurred -> Will set error count to 1 and send update
|
||||
// 2. Session with non terminal status and 1 error + a crash occurred -> Will set status crashed and send update
|
||||
const sessionNonTerminal = session.status === 'ok';
|
||||
const shouldUpdateAndSend = (sessionNonTerminal && session.errors === 0) || (sessionNonTerminal && crashed);
|
||||
|
||||
if (shouldUpdateAndSend) {
|
||||
updateSession(session, {
|
||||
...(crashed && { status: 'crashed' }),
|
||||
errors: session.errors || Number(errored || crashed),
|
||||
});
|
||||
this.captureSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the client is finished processing. Returns a promise because it will wait `timeout` ms before saying
|
||||
* "no" (resolving to `false`) in order to give the client a chance to potentially finish first.
|
||||
*
|
||||
* @param timeout The time, in ms, after which to resolve to `false` if the client is still busy. Passing `0` (or not
|
||||
* passing anything) will make the promise wait as long as it takes for processing to finish before resolving to
|
||||
* `true`.
|
||||
* @returns A promise which will resolve to `true` if processing is already done or finishes before the timeout, and
|
||||
* `false` otherwise
|
||||
*/
|
||||
_isClientDoneProcessing(timeout) {
|
||||
return new SyncPromise(resolve => {
|
||||
let ticked = 0;
|
||||
const tick = 1;
|
||||
|
||||
const interval = setInterval(() => {
|
||||
if (this._numProcessing == 0) {
|
||||
clearInterval(interval);
|
||||
resolve(true);
|
||||
} else {
|
||||
ticked += tick;
|
||||
if (timeout && ticked >= timeout) {
|
||||
clearInterval(interval);
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
}, tick);
|
||||
});
|
||||
}
|
||||
|
||||
/** Determines whether this SDK is enabled and a transport is present. */
|
||||
_isEnabled() {
|
||||
return this.getOptions().enabled !== false && this._transport !== undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds common information to events.
|
||||
*
|
||||
* The information includes release and environment from `options`,
|
||||
* breadcrumbs and context (extra, tags and user) from the scope.
|
||||
*
|
||||
* Information that is already present in the event is never overwritten. For
|
||||
* nested objects, such as the context, keys are merged.
|
||||
*
|
||||
* @param event The original event.
|
||||
* @param hint May contain additional information about the original exception.
|
||||
* @param scope A scope containing event metadata.
|
||||
* @returns A new event with more information.
|
||||
*/
|
||||
_prepareEvent(
|
||||
event,
|
||||
hint,
|
||||
scope,
|
||||
isolationScope = getIsolationScope(),
|
||||
) {
|
||||
const options = this.getOptions();
|
||||
const integrations = Object.keys(this._integrations);
|
||||
if (!hint.integrations && integrations.length > 0) {
|
||||
hint.integrations = integrations;
|
||||
}
|
||||
|
||||
this.emit('preprocessEvent', event, hint);
|
||||
|
||||
return prepareEvent(options, event, hint, scope, this, isolationScope).then(evt => {
|
||||
if (evt === null) {
|
||||
return evt;
|
||||
}
|
||||
|
||||
const propagationContext = {
|
||||
...isolationScope.getPropagationContext(),
|
||||
...(scope ? scope.getPropagationContext() : undefined),
|
||||
};
|
||||
|
||||
const trace = evt.contexts && evt.contexts.trace;
|
||||
if (!trace && propagationContext) {
|
||||
const { traceId: trace_id, spanId, parentSpanId, dsc } = propagationContext;
|
||||
evt.contexts = {
|
||||
trace: {
|
||||
trace_id,
|
||||
span_id: spanId,
|
||||
parent_span_id: parentSpanId,
|
||||
},
|
||||
...evt.contexts,
|
||||
};
|
||||
|
||||
const dynamicSamplingContext = dsc ? dsc : getDynamicSamplingContextFromClient(trace_id, this, scope);
|
||||
|
||||
evt.sdkProcessingMetadata = {
|
||||
dynamicSamplingContext,
|
||||
...evt.sdkProcessingMetadata,
|
||||
};
|
||||
}
|
||||
return evt;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes the event and logs an error in case of rejection
|
||||
* @param event
|
||||
* @param hint
|
||||
* @param scope
|
||||
*/
|
||||
_captureEvent(event, hint = {}, scope) {
|
||||
return this._processEvent(event, hint, scope).then(
|
||||
finalEvent => {
|
||||
return finalEvent.event_id;
|
||||
},
|
||||
reason => {
|
||||
if (DEBUG_BUILD) {
|
||||
// If something's gone wrong, log the error as a warning. If it's just us having used a `SentryError` for
|
||||
// control flow, log just the message (no stack) as a log-level log.
|
||||
const sentryError = reason ;
|
||||
if (sentryError.logLevel === 'log') {
|
||||
logger.log(sentryError.message);
|
||||
} else {
|
||||
logger.warn(sentryError);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes an event (either error or message) and sends it to Sentry.
|
||||
*
|
||||
* This also adds breadcrumbs and context information to the event. However,
|
||||
* platform specific meta data (such as the User's IP address) must be added
|
||||
* by the SDK implementor.
|
||||
*
|
||||
*
|
||||
* @param event The event to send to Sentry.
|
||||
* @param hint May contain additional information about the original exception.
|
||||
* @param scope A scope containing event metadata.
|
||||
* @returns A SyncPromise that resolves with the event or rejects in case event was/will not be send.
|
||||
*/
|
||||
_processEvent(event, hint, scope) {
|
||||
const options = this.getOptions();
|
||||
const { sampleRate } = options;
|
||||
|
||||
const isTransaction = isTransactionEvent(event);
|
||||
const isError = isErrorEvent(event);
|
||||
const eventType = event.type || 'error';
|
||||
const beforeSendLabel = `before send for type \`${eventType}\``;
|
||||
|
||||
// 1.0 === 100% events are sent
|
||||
// 0.0 === 0% events are sent
|
||||
// Sampling for transaction happens somewhere else
|
||||
if (isError && typeof sampleRate === 'number' && Math.random() > sampleRate) {
|
||||
this.recordDroppedEvent('sample_rate', 'error', event);
|
||||
return rejectedSyncPromise(
|
||||
new SentryError(
|
||||
`Discarding event because it's not included in the random sample (sampling rate = ${sampleRate})`,
|
||||
'log',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const dataCategory = eventType === 'replay_event' ? 'replay' : eventType;
|
||||
|
||||
const sdkProcessingMetadata = event.sdkProcessingMetadata || {};
|
||||
const capturedSpanIsolationScope = sdkProcessingMetadata.capturedSpanIsolationScope;
|
||||
|
||||
return this._prepareEvent(event, hint, scope, capturedSpanIsolationScope)
|
||||
.then(prepared => {
|
||||
if (prepared === null) {
|
||||
this.recordDroppedEvent('event_processor', dataCategory, event);
|
||||
throw new SentryError('An event processor returned `null`, will not send event.', 'log');
|
||||
}
|
||||
|
||||
const isInternalException = hint.data && (hint.data ).__sentry__ === true;
|
||||
if (isInternalException) {
|
||||
return prepared;
|
||||
}
|
||||
|
||||
const result = processBeforeSend(options, prepared, hint);
|
||||
return _validateBeforeSendResult(result, beforeSendLabel);
|
||||
})
|
||||
.then(processedEvent => {
|
||||
if (processedEvent === null) {
|
||||
this.recordDroppedEvent('before_send', dataCategory, event);
|
||||
throw new SentryError(`${beforeSendLabel} returned \`null\`, will not send event.`, 'log');
|
||||
}
|
||||
|
||||
const session = scope && scope.getSession();
|
||||
if (!isTransaction && session) {
|
||||
this._updateSessionFromEvent(session, processedEvent);
|
||||
}
|
||||
|
||||
// None of the Sentry built event processor will update transaction name,
|
||||
// so if the transaction name has been changed by an event processor, we know
|
||||
// it has to come from custom event processor added by a user
|
||||
const transactionInfo = processedEvent.transaction_info;
|
||||
if (isTransaction && transactionInfo && processedEvent.transaction !== event.transaction) {
|
||||
const source = 'custom';
|
||||
processedEvent.transaction_info = {
|
||||
...transactionInfo,
|
||||
source,
|
||||
};
|
||||
}
|
||||
|
||||
this.sendEvent(processedEvent, hint);
|
||||
return processedEvent;
|
||||
})
|
||||
.then(null, reason => {
|
||||
if (reason instanceof SentryError) {
|
||||
throw reason;
|
||||
}
|
||||
|
||||
this.captureException(reason, {
|
||||
data: {
|
||||
__sentry__: true,
|
||||
},
|
||||
originalException: reason,
|
||||
});
|
||||
throw new SentryError(
|
||||
`Event processing pipeline threw an error, original event will not be sent. Details have been sent as a new event.\nReason: ${reason}`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Occupies the client with processing and event
|
||||
*/
|
||||
_process(promise) {
|
||||
this._numProcessing++;
|
||||
void promise.then(
|
||||
value => {
|
||||
this._numProcessing--;
|
||||
return value;
|
||||
},
|
||||
reason => {
|
||||
this._numProcessing--;
|
||||
return reason;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
_sendEnvelope(envelope) {
|
||||
this.emit('beforeEnvelope', envelope);
|
||||
|
||||
if (this._isEnabled() && this._transport) {
|
||||
return this._transport.send(envelope).then(null, reason => {
|
||||
DEBUG_BUILD && logger.error('Error while sending event:', reason);
|
||||
});
|
||||
} else {
|
||||
DEBUG_BUILD && logger.error('Transport disabled');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears outcomes on this client and returns them.
|
||||
*/
|
||||
_clearOutcomes() {
|
||||
const outcomes = this._outcomes;
|
||||
this._outcomes = {};
|
||||
return Object.keys(outcomes).map(key => {
|
||||
const [reason, category] = key.split(':') ;
|
||||
return {
|
||||
reason,
|
||||
category,
|
||||
quantity: outcomes[key],
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that return value of configured `beforeSend` or `beforeSendTransaction` is of expected type, and returns the value if so.
|
||||
*/
|
||||
function _validateBeforeSendResult(
|
||||
beforeSendResult,
|
||||
beforeSendLabel,
|
||||
) {
|
||||
const invalidValueError = `${beforeSendLabel} must return \`null\` or a valid event.`;
|
||||
if (isThenable(beforeSendResult)) {
|
||||
return beforeSendResult.then(
|
||||
event => {
|
||||
if (!isPlainObject(event) && event !== null) {
|
||||
throw new SentryError(invalidValueError);
|
||||
}
|
||||
return event;
|
||||
},
|
||||
e => {
|
||||
throw new SentryError(`${beforeSendLabel} rejected with ${e}`);
|
||||
},
|
||||
);
|
||||
} else if (!isPlainObject(beforeSendResult) && beforeSendResult !== null) {
|
||||
throw new SentryError(invalidValueError);
|
||||
}
|
||||
return beforeSendResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the matching `beforeSendXXX` callback.
|
||||
*/
|
||||
function processBeforeSend(
|
||||
options,
|
||||
event,
|
||||
hint,
|
||||
) {
|
||||
const { beforeSend, beforeSendTransaction } = options;
|
||||
|
||||
if (isErrorEvent(event) && beforeSend) {
|
||||
return beforeSend(event, hint);
|
||||
}
|
||||
|
||||
if (isTransactionEvent(event) && beforeSendTransaction) {
|
||||
return beforeSendTransaction(event, hint);
|
||||
}
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
function isErrorEvent(event) {
|
||||
return event.type === undefined;
|
||||
}
|
||||
|
||||
function isTransactionEvent(event) {
|
||||
return event.type === 'transaction';
|
||||
}
|
||||
|
||||
/**
|
||||
* Add an event processor to the current client.
|
||||
* This event processor will run for all events processed by this client.
|
||||
*/
|
||||
function addEventProcessor(callback) {
|
||||
const client = getClient();
|
||||
|
||||
if (!client || !client.addEventProcessor) {
|
||||
return;
|
||||
}
|
||||
|
||||
client.addEventProcessor(callback);
|
||||
}
|
||||
|
||||
export { BaseClient, addEventProcessor };
|
||||
//# sourceMappingURL=baseclient.js.map
|
||||
1
node_modules/@sentry/core/esm/baseclient.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/baseclient.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
44
node_modules/@sentry/core/esm/checkin.js
generated
vendored
Normal file
44
node_modules/@sentry/core/esm/checkin.js
generated
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
import { dsnToString, dropUndefinedKeys, createEnvelope } from '@sentry/utils';
|
||||
|
||||
/**
|
||||
* Create envelope from check in item.
|
||||
*/
|
||||
function createCheckInEnvelope(
|
||||
checkIn,
|
||||
dynamicSamplingContext,
|
||||
metadata,
|
||||
tunnel,
|
||||
dsn,
|
||||
) {
|
||||
const headers = {
|
||||
sent_at: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (metadata && metadata.sdk) {
|
||||
headers.sdk = {
|
||||
name: metadata.sdk.name,
|
||||
version: metadata.sdk.version,
|
||||
};
|
||||
}
|
||||
|
||||
if (!!tunnel && !!dsn) {
|
||||
headers.dsn = dsnToString(dsn);
|
||||
}
|
||||
|
||||
if (dynamicSamplingContext) {
|
||||
headers.trace = dropUndefinedKeys(dynamicSamplingContext) ;
|
||||
}
|
||||
|
||||
const item = createCheckInEnvelopeItem(checkIn);
|
||||
return createEnvelope(headers, [item]);
|
||||
}
|
||||
|
||||
function createCheckInEnvelopeItem(checkIn) {
|
||||
const checkInHeaders = {
|
||||
type: 'check_in',
|
||||
};
|
||||
return [checkInHeaders, checkIn];
|
||||
}
|
||||
|
||||
export { createCheckInEnvelope };
|
||||
//# sourceMappingURL=checkin.js.map
|
||||
1
node_modules/@sentry/core/esm/checkin.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/checkin.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"checkin.js","sources":["../../src/checkin.ts"],"sourcesContent":["import type {\n CheckInEnvelope,\n CheckInItem,\n DsnComponents,\n DynamicSamplingContext,\n SdkMetadata,\n SerializedCheckIn,\n} from '@sentry/types';\nimport { createEnvelope, dropUndefinedKeys, dsnToString } from '@sentry/utils';\n\n/**\n * Create envelope from check in item.\n */\nexport function createCheckInEnvelope(\n checkIn: SerializedCheckIn,\n dynamicSamplingContext?: Partial<DynamicSamplingContext>,\n metadata?: SdkMetadata,\n tunnel?: string,\n dsn?: DsnComponents,\n): CheckInEnvelope {\n const headers: CheckInEnvelope[0] = {\n sent_at: new Date().toISOString(),\n };\n\n if (metadata && metadata.sdk) {\n headers.sdk = {\n name: metadata.sdk.name,\n version: metadata.sdk.version,\n };\n }\n\n if (!!tunnel && !!dsn) {\n headers.dsn = dsnToString(dsn);\n }\n\n if (dynamicSamplingContext) {\n headers.trace = dropUndefinedKeys(dynamicSamplingContext) as DynamicSamplingContext;\n }\n\n const item = createCheckInEnvelopeItem(checkIn);\n return createEnvelope<CheckInEnvelope>(headers, [item]);\n}\n\nfunction createCheckInEnvelopeItem(checkIn: SerializedCheckIn): CheckInItem {\n const checkInHeaders: CheckInItem[0] = {\n type: 'check_in',\n };\n return [checkInHeaders, checkIn];\n}\n"],"names":[],"mappings":";;AAUA;AACA;AACA;AACO,SAAS,qBAAqB;AACrC,EAAE,OAAO;AACT,EAAE,sBAAsB;AACxB,EAAE,QAAQ;AACV,EAAE,MAAM;AACR,EAAE,GAAG;AACL,EAAmB;AACnB,EAAE,MAAM,OAAO,GAAuB;AACtC,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACrC,GAAG,CAAA;AACH;AACA,EAAE,IAAI,QAAA,IAAY,QAAQ,CAAC,GAAG,EAAE;AAChC,IAAI,OAAO,CAAC,GAAA,GAAM;AAClB,MAAM,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI;AAC7B,MAAM,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO;AACnC,KAAK,CAAA;AACL,GAAE;AACF;AACA,EAAE,IAAI,CAAC,CAAC,UAAU,CAAC,CAAC,GAAG,EAAE;AACzB,IAAI,OAAO,CAAC,GAAA,GAAM,WAAW,CAAC,GAAG,CAAC,CAAA;AAClC,GAAE;AACF;AACA,EAAE,IAAI,sBAAsB,EAAE;AAC9B,IAAI,OAAO,CAAC,KAAA,GAAQ,iBAAiB,CAAC,sBAAsB,CAAE,EAAA;AAC9D,GAAE;AACF;AACA,EAAE,MAAM,IAAK,GAAE,yBAAyB,CAAC,OAAO,CAAC,CAAA;AACjD,EAAE,OAAO,cAAc,CAAkB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AACzD,CAAA;AACA;AACA,SAAS,yBAAyB,CAAC,OAAO,EAAkC;AAC5E,EAAE,MAAM,cAAc,GAAmB;AACzC,IAAI,IAAI,EAAE,UAAU;AACpB,GAAG,CAAA;AACH,EAAE,OAAO,CAAC,cAAc,EAAE,OAAO,CAAC,CAAA;AAClC;;;;"}
|
||||
4
node_modules/@sentry/core/esm/constants.js
generated
vendored
Normal file
4
node_modules/@sentry/core/esm/constants.js
generated
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
const DEFAULT_ENVIRONMENT = 'production';
|
||||
|
||||
export { DEFAULT_ENVIRONMENT };
|
||||
//# sourceMappingURL=constants.js.map
|
||||
1
node_modules/@sentry/core/esm/constants.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/constants.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"constants.js","sources":["../../src/constants.ts"],"sourcesContent":["export const DEFAULT_ENVIRONMENT = 'production';\n"],"names":[],"mappings":"AAAO,MAAM,mBAAoB,GAAE;;;;"}
|
||||
9
node_modules/@sentry/core/esm/debug-build.js
generated
vendored
Normal file
9
node_modules/@sentry/core/esm/debug-build.js
generated
vendored
Normal file
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.
|
||||
*
|
||||
* ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.
|
||||
*/
|
||||
const DEBUG_BUILD = (typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__);
|
||||
|
||||
export { DEBUG_BUILD };
|
||||
//# sourceMappingURL=debug-build.js.map
|
||||
1
node_modules/@sentry/core/esm/debug-build.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/debug-build.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"debug-build.js","sources":["../../src/debug-build.ts"],"sourcesContent":["declare const __DEBUG_BUILD__: boolean;\n\n/**\n * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code.\n *\n * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking.\n */\nexport const DEBUG_BUILD = __DEBUG_BUILD__;\n"],"names":[],"mappings":"AAEA;AACA;AACA;AACA;AACA;AACO,MAAM,WAAY,IAAE,OAAA,gBAAA,KAAA,WAAA,IAAA,gBAAA;;;;"}
|
||||
74
node_modules/@sentry/core/esm/envelope.js
generated
vendored
Normal file
74
node_modules/@sentry/core/esm/envelope.js
generated
vendored
Normal file
@@ -0,0 +1,74 @@
|
||||
import { getSdkMetadataForEnvelopeHeader, dsnToString, createEnvelope, createEventEnvelopeHeaders } from '@sentry/utils';
|
||||
|
||||
/**
|
||||
* Apply SdkInfo (name, version, packages, integrations) to the corresponding event key.
|
||||
* Merge with existing data if any.
|
||||
**/
|
||||
function enhanceEventWithSdkInfo(event, sdkInfo) {
|
||||
if (!sdkInfo) {
|
||||
return event;
|
||||
}
|
||||
event.sdk = event.sdk || {};
|
||||
event.sdk.name = event.sdk.name || sdkInfo.name;
|
||||
event.sdk.version = event.sdk.version || sdkInfo.version;
|
||||
event.sdk.integrations = [...(event.sdk.integrations || []), ...(sdkInfo.integrations || [])];
|
||||
event.sdk.packages = [...(event.sdk.packages || []), ...(sdkInfo.packages || [])];
|
||||
return event;
|
||||
}
|
||||
|
||||
/** Creates an envelope from a Session */
|
||||
function createSessionEnvelope(
|
||||
session,
|
||||
dsn,
|
||||
metadata,
|
||||
tunnel,
|
||||
) {
|
||||
const sdkInfo = getSdkMetadataForEnvelopeHeader(metadata);
|
||||
const envelopeHeaders = {
|
||||
sent_at: new Date().toISOString(),
|
||||
...(sdkInfo && { sdk: sdkInfo }),
|
||||
...(!!tunnel && dsn && { dsn: dsnToString(dsn) }),
|
||||
};
|
||||
|
||||
const envelopeItem =
|
||||
'aggregates' in session ? [{ type: 'sessions' }, session] : [{ type: 'session' }, session.toJSON()];
|
||||
|
||||
return createEnvelope(envelopeHeaders, [envelopeItem]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create an Envelope from an event.
|
||||
*/
|
||||
function createEventEnvelope(
|
||||
event,
|
||||
dsn,
|
||||
metadata,
|
||||
tunnel,
|
||||
) {
|
||||
const sdkInfo = getSdkMetadataForEnvelopeHeader(metadata);
|
||||
|
||||
/*
|
||||
Note: Due to TS, event.type may be `replay_event`, theoretically.
|
||||
In practice, we never call `createEventEnvelope` with `replay_event` type,
|
||||
and we'd have to adjut a looot of types to make this work properly.
|
||||
We want to avoid casting this around, as that could lead to bugs (e.g. when we add another type)
|
||||
So the safe choice is to really guard against the replay_event type here.
|
||||
*/
|
||||
const eventType = event.type && event.type !== 'replay_event' ? event.type : 'event';
|
||||
|
||||
enhanceEventWithSdkInfo(event, metadata && metadata.sdk);
|
||||
|
||||
const envelopeHeaders = createEventEnvelopeHeaders(event, sdkInfo, tunnel, dsn);
|
||||
|
||||
// Prevent this data (which, if it exists, was used in earlier steps in the processing pipeline) from being sent to
|
||||
// sentry. (Note: Our use of this property comes and goes with whatever we might be debugging, whatever hacks we may
|
||||
// have temporarily added, etc. Even if we don't happen to be using it at some point in the future, let's not get rid
|
||||
// of this `delete`, lest we miss putting it back in the next time the property is in use.)
|
||||
delete event.sdkProcessingMetadata;
|
||||
|
||||
const eventItem = [{ type: eventType }, event];
|
||||
return createEnvelope(envelopeHeaders, [eventItem]);
|
||||
}
|
||||
|
||||
export { createEventEnvelope, createSessionEnvelope };
|
||||
//# sourceMappingURL=envelope.js.map
|
||||
1
node_modules/@sentry/core/esm/envelope.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/envelope.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
53
node_modules/@sentry/core/esm/eventProcessors.js
generated
vendored
Normal file
53
node_modules/@sentry/core/esm/eventProcessors.js
generated
vendored
Normal file
@@ -0,0 +1,53 @@
|
||||
import { SyncPromise, logger, isThenable, getGlobalSingleton } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
|
||||
/**
|
||||
* Returns the global event processors.
|
||||
* @deprecated Global event processors will be removed in v8.
|
||||
*/
|
||||
function getGlobalEventProcessors() {
|
||||
return getGlobalSingleton('globalEventProcessors', () => []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a EventProcessor to be kept globally.
|
||||
* @deprecated Use `addEventProcessor` instead. Global event processors will be removed in v8.
|
||||
*/
|
||||
function addGlobalEventProcessor(callback) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getGlobalEventProcessors().push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process an array of event processors, returning the processed event (or `null` if the event was dropped).
|
||||
*/
|
||||
function notifyEventProcessors(
|
||||
processors,
|
||||
event,
|
||||
hint,
|
||||
index = 0,
|
||||
) {
|
||||
return new SyncPromise((resolve, reject) => {
|
||||
const processor = processors[index];
|
||||
if (event === null || typeof processor !== 'function') {
|
||||
resolve(event);
|
||||
} else {
|
||||
const result = processor({ ...event }, hint) ;
|
||||
|
||||
DEBUG_BUILD && processor.id && result === null && logger.log(`Event processor "${processor.id}" dropped event`);
|
||||
|
||||
if (isThenable(result)) {
|
||||
void result
|
||||
.then(final => notifyEventProcessors(processors, final, hint, index + 1).then(resolve))
|
||||
.then(null, reject);
|
||||
} else {
|
||||
void notifyEventProcessors(processors, result, hint, index + 1)
|
||||
.then(resolve)
|
||||
.then(null, reject);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export { addGlobalEventProcessor, getGlobalEventProcessors, notifyEventProcessors };
|
||||
//# sourceMappingURL=eventProcessors.js.map
|
||||
1
node_modules/@sentry/core/esm/eventProcessors.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/eventProcessors.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"eventProcessors.js","sources":["../../src/eventProcessors.ts"],"sourcesContent":["import type { Event, EventHint, EventProcessor } from '@sentry/types';\nimport { SyncPromise, getGlobalSingleton, isThenable, logger } from '@sentry/utils';\n\nimport { DEBUG_BUILD } from './debug-build';\n\n/**\n * Returns the global event processors.\n * @deprecated Global event processors will be removed in v8.\n */\nexport function getGlobalEventProcessors(): EventProcessor[] {\n return getGlobalSingleton<EventProcessor[]>('globalEventProcessors', () => []);\n}\n\n/**\n * Add a EventProcessor to be kept globally.\n * @deprecated Use `addEventProcessor` instead. Global event processors will be removed in v8.\n */\nexport function addGlobalEventProcessor(callback: EventProcessor): void {\n // eslint-disable-next-line deprecation/deprecation\n getGlobalEventProcessors().push(callback);\n}\n\n/**\n * Process an array of event processors, returning the processed event (or `null` if the event was dropped).\n */\nexport function notifyEventProcessors(\n processors: EventProcessor[],\n event: Event | null,\n hint: EventHint,\n index: number = 0,\n): PromiseLike<Event | null> {\n return new SyncPromise<Event | null>((resolve, reject) => {\n const processor = processors[index];\n if (event === null || typeof processor !== 'function') {\n resolve(event);\n } else {\n const result = processor({ ...event }, hint) as Event | null;\n\n DEBUG_BUILD && processor.id && result === null && logger.log(`Event processor \"${processor.id}\" dropped event`);\n\n if (isThenable(result)) {\n void result\n .then(final => notifyEventProcessors(processors, final, hint, index + 1).then(resolve))\n .then(null, reject);\n } else {\n void notifyEventProcessors(processors, result, hint, index + 1)\n .then(resolve)\n .then(null, reject);\n }\n }\n });\n}\n"],"names":[],"mappings":";;;AAKA;AACA;AACA;AACA;AACO,SAAS,wBAAwB,GAAqB;AAC7D,EAAE,OAAO,kBAAkB,CAAmB,uBAAuB,EAAE,MAAM,EAAE,CAAC,CAAA;AAChF,CAAA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,uBAAuB,CAAC,QAAQ,EAAwB;AACxE;AACA,EAAE,wBAAwB,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;AAC3C,CAAA;AACA;AACA;AACA;AACA;AACO,SAAS,qBAAqB;AACrC,EAAE,UAAU;AACZ,EAAE,KAAK;AACP,EAAE,IAAI;AACN,EAAE,KAAK,GAAW,CAAC;AACnB,EAA6B;AAC7B,EAAE,OAAO,IAAI,WAAW,CAAe,CAAC,OAAO,EAAE,MAAM,KAAK;AAC5D,IAAI,MAAM,SAAU,GAAE,UAAU,CAAC,KAAK,CAAC,CAAA;AACvC,IAAI,IAAI,KAAA,KAAU,IAAA,IAAQ,OAAO,SAAA,KAAc,UAAU,EAAE;AAC3D,MAAM,OAAO,CAAC,KAAK,CAAC,CAAA;AACpB,WAAW;AACX,MAAM,MAAM,MAAO,GAAE,SAAS,CAAC,EAAE,GAAG,KAAM,EAAC,EAAE,IAAI,CAAE,EAAA;AACnD;AACA,MAAM,WAAA,IAAe,SAAS,CAAC,MAAM,MAAA,KAAW,IAAA,IAAQ,MAAM,CAAC,GAAG,CAAC,CAAC,iBAAiB,EAAE,SAAS,CAAC,EAAE,CAAC,eAAe,CAAC,CAAC,CAAA;AACrH;AACA,MAAM,IAAI,UAAU,CAAC,MAAM,CAAC,EAAE;AAC9B,QAAQ,KAAK,MAAA;AACb,WAAW,IAAI,CAAC,KAAA,IAAS,qBAAqB,CAAC,UAAU,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;AAChG,WAAW,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAC7B,aAAa;AACb,QAAQ,KAAK,qBAAqB,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE,KAAM,GAAE,CAAC,CAAA;AACtE,WAAW,IAAI,CAAC,OAAO,CAAA;AACvB,WAAW,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;AAC7B,OAAM;AACN,KAAI;AACJ,GAAG,CAAC,CAAA;AACJ;;;;"}
|
||||
485
node_modules/@sentry/core/esm/exports.js
generated
vendored
Normal file
485
node_modules/@sentry/core/esm/exports.js
generated
vendored
Normal file
@@ -0,0 +1,485 @@
|
||||
import { logger, uuid4, timestampInSeconds, isThenable, GLOBAL_OBJ } from '@sentry/utils';
|
||||
import { DEFAULT_ENVIRONMENT } from './constants.js';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
import { getCurrentHub, runWithAsyncContext, getIsolationScope } from './hub.js';
|
||||
import { makeSession, updateSession, closeSession } from './session.js';
|
||||
import { parseEventHintOrCaptureContext } from './utils/prepareEvent.js';
|
||||
|
||||
/**
|
||||
* Captures an exception event and sends it to Sentry.
|
||||
*
|
||||
* @param exception The exception to capture.
|
||||
* @param hint Optional additional data to attach to the Sentry event.
|
||||
* @returns the id of the captured Sentry event.
|
||||
*/
|
||||
function captureException(
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
exception,
|
||||
hint,
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().captureException(exception, parseEventHintOrCaptureContext(hint));
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a message event and sends it to Sentry.
|
||||
*
|
||||
* @param exception The exception to capture.
|
||||
* @param captureContext Define the level of the message or pass in additional data to attach to the message.
|
||||
* @returns the id of the captured message.
|
||||
*/
|
||||
function captureMessage(
|
||||
message,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
captureContext,
|
||||
) {
|
||||
// This is necessary to provide explicit scopes upgrade, without changing the original
|
||||
// arity of the `captureMessage(message, level)` method.
|
||||
const level = typeof captureContext === 'string' ? captureContext : undefined;
|
||||
const context = typeof captureContext !== 'string' ? { captureContext } : undefined;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().captureMessage(message, level, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a manually created event and sends it to Sentry.
|
||||
*
|
||||
* @param exception The event to send to Sentry.
|
||||
* @param hint Optional additional data to attach to the Sentry event.
|
||||
* @returns the id of the captured event.
|
||||
*/
|
||||
function captureEvent(event, hint) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().captureEvent(event, hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Callback to set context information onto the scope.
|
||||
* @param callback Callback function that receives Scope.
|
||||
*
|
||||
* @deprecated Use getCurrentScope() directly.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function configureScope(callback) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().configureScope(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Records a new breadcrumb which will be attached to future events.
|
||||
*
|
||||
* Breadcrumbs will be added to subsequent events to provide more context on
|
||||
* user's actions prior to an error or crash.
|
||||
*
|
||||
* @param breadcrumb The breadcrumb to record.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function addBreadcrumb(breadcrumb, hint) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().addBreadcrumb(breadcrumb, hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets context data with the given name.
|
||||
* @param name of the context
|
||||
* @param context Any kind of data. This data will be normalized.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, deprecation/deprecation
|
||||
function setContext(name, context) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().setContext(name, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an object that will be merged sent as extra data with the event.
|
||||
* @param extras Extras object to merge into current context.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function setExtras(extras) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().setExtras(extras);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set key:value that will be sent as extra data with the event.
|
||||
* @param key String of extra
|
||||
* @param extra Any kind of data. This data will be normalized.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function setExtra(key, extra) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().setExtra(key, extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an object that will be merged sent as tags data with the event.
|
||||
* @param tags Tags context object to merge into current context.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function setTags(tags) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().setTags(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set key:value that will be sent as tags data with the event.
|
||||
*
|
||||
* Can also be used to unset a tag, by passing `undefined`.
|
||||
*
|
||||
* @param key String key of tag
|
||||
* @param value Value of tag
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function setTag(key, value) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().setTag(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates user context information for future events.
|
||||
*
|
||||
* @param user User context object to be set in the current context. Pass `null` to unset the user.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function setUser(user) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getCurrentHub().setUser(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new scope with and executes the given operation within.
|
||||
* The scope is automatically removed once the operation
|
||||
* finishes or throws.
|
||||
*
|
||||
* This is essentially a convenience function for:
|
||||
*
|
||||
* pushScope();
|
||||
* callback();
|
||||
* popScope();
|
||||
*/
|
||||
|
||||
/**
|
||||
* Either creates a new active scope, or sets the given scope as active scope in the given callback.
|
||||
*/
|
||||
function withScope(
|
||||
...rest
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = getCurrentHub();
|
||||
|
||||
// If a scope is defined, we want to make this the active scope instead of the default one
|
||||
if (rest.length === 2) {
|
||||
const [scope, callback] = rest;
|
||||
if (!scope) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return hub.withScope(callback);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return hub.withScope(() => {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
hub.getStackTop().scope = scope ;
|
||||
return callback(scope );
|
||||
});
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return hub.withScope(rest[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to fork the current isolation scope and the current scope based on the current async context strategy. If no
|
||||
* async context strategy is set, the isolation scope and the current scope will not be forked (this is currently the
|
||||
* case, for example, in the browser).
|
||||
*
|
||||
* Usage of this function in environments without async context strategy is discouraged and may lead to unexpected behaviour.
|
||||
*
|
||||
* This function is intended for Sentry SDK and SDK integration development. It is not recommended to be used in "normal"
|
||||
* applications directly because it comes with pitfalls. Use at your own risk!
|
||||
*
|
||||
* @param callback The callback in which the passed isolation scope is active. (Note: In environments without async
|
||||
* context strategy, the currently active isolation scope may change within execution of the callback.)
|
||||
* @returns The same value that `callback` returns.
|
||||
*/
|
||||
function withIsolationScope(callback) {
|
||||
return runWithAsyncContext(() => {
|
||||
return callback(getIsolationScope());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Forks the current scope and sets the provided span as active span in the context of the provided callback.
|
||||
*
|
||||
* @param span Spans started in the context of the provided callback will be children of this span.
|
||||
* @param callback Execution context in which the provided span will be active. Is passed the newly forked scope.
|
||||
* @returns the value returned from the provided callback function.
|
||||
*/
|
||||
function withActiveSpan(span, callback) {
|
||||
return withScope(scope => {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
scope.setSpan(span);
|
||||
return callback(scope);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new `Transaction` and returns it. This is the entry point to manual tracing instrumentation.
|
||||
*
|
||||
* A tree structure can be built by adding child spans to the transaction, and child spans to other spans. To start a
|
||||
* new child span within the transaction or any span, call the respective `.startChild()` method.
|
||||
*
|
||||
* Every child span must be finished before the transaction is finished, otherwise the unfinished spans are discarded.
|
||||
*
|
||||
* The transaction must be finished with a call to its `.end()` method, at which point the transaction with all its
|
||||
* finished child spans will be sent to Sentry.
|
||||
*
|
||||
* NOTE: This function should only be used for *manual* instrumentation. Auto-instrumentation should call
|
||||
* `startTransaction` directly on the hub.
|
||||
*
|
||||
* @param context Properties of the new `Transaction`.
|
||||
* @param customSamplingContext Information given to the transaction sampling function (along with context-dependent
|
||||
* default values). See {@link Options.tracesSampler}.
|
||||
*
|
||||
* @returns The transaction which was just started
|
||||
*
|
||||
* @deprecated Use `startSpan()`, `startSpanManual()` or `startInactiveSpan()` instead.
|
||||
*/
|
||||
function startTransaction(
|
||||
context,
|
||||
customSamplingContext,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().startTransaction({ ...context }, customSamplingContext);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cron monitor check in and send it to Sentry.
|
||||
*
|
||||
* @param checkIn An object that describes a check in.
|
||||
* @param upsertMonitorConfig An optional object that describes a monitor config. Use this if you want
|
||||
* to create a monitor automatically when sending a check in.
|
||||
*/
|
||||
function captureCheckIn(checkIn, upsertMonitorConfig) {
|
||||
const scope = getCurrentScope();
|
||||
const client = getClient();
|
||||
if (!client) {
|
||||
DEBUG_BUILD && logger.warn('Cannot capture check-in. No client defined.');
|
||||
} else if (!client.captureCheckIn) {
|
||||
DEBUG_BUILD && logger.warn('Cannot capture check-in. Client does not support sending check-ins.');
|
||||
} else {
|
||||
return client.captureCheckIn(checkIn, upsertMonitorConfig, scope);
|
||||
}
|
||||
|
||||
return uuid4();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a callback with a cron monitor check in. The check in will be sent to Sentry when the callback finishes.
|
||||
*
|
||||
* @param monitorSlug The distinct slug of the monitor.
|
||||
* @param upsertMonitorConfig An optional object that describes a monitor config. Use this if you want
|
||||
* to create a monitor automatically when sending a check in.
|
||||
*/
|
||||
function withMonitor(
|
||||
monitorSlug,
|
||||
callback,
|
||||
upsertMonitorConfig,
|
||||
) {
|
||||
const checkInId = captureCheckIn({ monitorSlug, status: 'in_progress' }, upsertMonitorConfig);
|
||||
const now = timestampInSeconds();
|
||||
|
||||
function finishCheckIn(status) {
|
||||
captureCheckIn({ monitorSlug, status, checkInId, duration: timestampInSeconds() - now });
|
||||
}
|
||||
|
||||
let maybePromiseResult;
|
||||
try {
|
||||
maybePromiseResult = callback();
|
||||
} catch (e) {
|
||||
finishCheckIn('error');
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (isThenable(maybePromiseResult)) {
|
||||
Promise.resolve(maybePromiseResult).then(
|
||||
() => {
|
||||
finishCheckIn('ok');
|
||||
},
|
||||
() => {
|
||||
finishCheckIn('error');
|
||||
},
|
||||
);
|
||||
} else {
|
||||
finishCheckIn('ok');
|
||||
}
|
||||
|
||||
return maybePromiseResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call `flush()` on the current client, if there is one. See {@link Client.flush}.
|
||||
*
|
||||
* @param timeout Maximum time in ms the client should wait to flush its event queue. Omitting this parameter will cause
|
||||
* the client to wait until all events are sent before resolving the promise.
|
||||
* @returns A promise which resolves to `true` if the queue successfully drains before the timeout, or `false` if it
|
||||
* doesn't (or if there's no client defined).
|
||||
*/
|
||||
async function flush(timeout) {
|
||||
const client = getClient();
|
||||
if (client) {
|
||||
return client.flush(timeout);
|
||||
}
|
||||
DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.');
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call `close()` on the current client, if there is one. See {@link Client.close}.
|
||||
*
|
||||
* @param timeout Maximum time in ms the client should wait to flush its event queue before shutting down. Omitting this
|
||||
* parameter will cause the client to wait until all events are sent before disabling itself.
|
||||
* @returns A promise which resolves to `true` if the queue successfully drains before the timeout, or `false` if it
|
||||
* doesn't (or if there's no client defined).
|
||||
*/
|
||||
async function close(timeout) {
|
||||
const client = getClient();
|
||||
if (client) {
|
||||
return client.close(timeout);
|
||||
}
|
||||
DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.');
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
/**
|
||||
* This is the getter for lastEventId.
|
||||
*
|
||||
* @returns The last event id of a captured event.
|
||||
* @deprecated This function will be removed in the next major version of the Sentry SDK.
|
||||
*/
|
||||
function lastEventId() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().lastEventId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently active client.
|
||||
*/
|
||||
function getClient() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if Sentry has been properly initialized.
|
||||
*/
|
||||
function isInitialized() {
|
||||
return !!getClient();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently active scope.
|
||||
*/
|
||||
function getCurrentScope() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().getScope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Start a session on the current isolation scope.
|
||||
*
|
||||
* @param context (optional) additional properties to be applied to the returned session object
|
||||
*
|
||||
* @returns the new active session
|
||||
*/
|
||||
function startSession(context) {
|
||||
const client = getClient();
|
||||
const isolationScope = getIsolationScope();
|
||||
const currentScope = getCurrentScope();
|
||||
|
||||
const { release, environment = DEFAULT_ENVIRONMENT } = (client && client.getOptions()) || {};
|
||||
|
||||
// Will fetch userAgent if called from browser sdk
|
||||
const { userAgent } = GLOBAL_OBJ.navigator || {};
|
||||
|
||||
const session = makeSession({
|
||||
release,
|
||||
environment,
|
||||
user: currentScope.getUser() || isolationScope.getUser(),
|
||||
...(userAgent && { userAgent }),
|
||||
...context,
|
||||
});
|
||||
|
||||
// End existing session if there's one
|
||||
const currentSession = isolationScope.getSession();
|
||||
if (currentSession && currentSession.status === 'ok') {
|
||||
updateSession(currentSession, { status: 'exited' });
|
||||
}
|
||||
|
||||
endSession();
|
||||
|
||||
// Afterwards we set the new session on the scope
|
||||
isolationScope.setSession(session);
|
||||
|
||||
// TODO (v8): Remove this and only use the isolation scope(?).
|
||||
// For v7 though, we can't "soft-break" people using getCurrentHub().getScope().setSession()
|
||||
currentScope.setSession(session);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* End the session on the current isolation scope.
|
||||
*/
|
||||
function endSession() {
|
||||
const isolationScope = getIsolationScope();
|
||||
const currentScope = getCurrentScope();
|
||||
|
||||
const session = currentScope.getSession() || isolationScope.getSession();
|
||||
if (session) {
|
||||
closeSession(session);
|
||||
}
|
||||
_sendSessionUpdate();
|
||||
|
||||
// the session is over; take it off of the scope
|
||||
isolationScope.setSession();
|
||||
|
||||
// TODO (v8): Remove this and only use the isolation scope(?).
|
||||
// For v7 though, we can't "soft-break" people using getCurrentHub().getScope().setSession()
|
||||
currentScope.setSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the current Session on the scope
|
||||
*/
|
||||
function _sendSessionUpdate() {
|
||||
const isolationScope = getIsolationScope();
|
||||
const currentScope = getCurrentScope();
|
||||
const client = getClient();
|
||||
// TODO (v8): Remove currentScope and only use the isolation scope(?).
|
||||
// For v7 though, we can't "soft-break" people using getCurrentHub().getScope().setSession()
|
||||
const session = currentScope.getSession() || isolationScope.getSession();
|
||||
if (session && client && client.captureSession) {
|
||||
client.captureSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the current session on the scope to Sentry
|
||||
*
|
||||
* @param end If set the session will be marked as exited and removed from the scope.
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
function captureSession(end = false) {
|
||||
// both send the update and pull the session from the scope
|
||||
if (end) {
|
||||
endSession();
|
||||
return;
|
||||
}
|
||||
|
||||
// only send the update
|
||||
_sendSessionUpdate();
|
||||
}
|
||||
|
||||
export { addBreadcrumb, captureCheckIn, captureEvent, captureException, captureMessage, captureSession, close, configureScope, endSession, flush, getClient, getCurrentScope, isInitialized, lastEventId, setContext, setExtra, setExtras, setTag, setTags, setUser, startSession, startTransaction, withActiveSpan, withIsolationScope, withMonitor, withScope };
|
||||
//# sourceMappingURL=exports.js.map
|
||||
1
node_modules/@sentry/core/esm/exports.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/exports.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
817
node_modules/@sentry/core/esm/hub.js
generated
vendored
Normal file
817
node_modules/@sentry/core/esm/hub.js
generated
vendored
Normal file
@@ -0,0 +1,817 @@
|
||||
import { isThenable, uuid4, dateTimestampInSeconds, consoleSandbox, logger, GLOBAL_OBJ, getGlobalSingleton } from '@sentry/utils';
|
||||
import { DEFAULT_ENVIRONMENT } from './constants.js';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
import { Scope } from './scope.js';
|
||||
import { closeSession, makeSession, updateSession } from './session.js';
|
||||
import { SDK_VERSION } from './version.js';
|
||||
|
||||
/**
|
||||
* API compatibility version of this hub.
|
||||
*
|
||||
* WARNING: This number should only be increased when the global interface
|
||||
* changes and new methods are introduced.
|
||||
*
|
||||
* @hidden
|
||||
*/
|
||||
const API_VERSION = parseFloat(SDK_VERSION);
|
||||
|
||||
/**
|
||||
* Default maximum number of breadcrumbs added to an event. Can be overwritten
|
||||
* with {@link Options.maxBreadcrumbs}.
|
||||
*/
|
||||
const DEFAULT_BREADCRUMBS = 100;
|
||||
|
||||
/**
|
||||
* @deprecated The `Hub` class will be removed in version 8 of the SDK in favour of `Scope` and `Client` objects.
|
||||
*
|
||||
* If you previously used the `Hub` class directly, replace it with `Scope` and `Client` objects. More information:
|
||||
* - [Multiple Sentry Instances](https://docs.sentry.io/platforms/javascript/best-practices/multiple-sentry-instances/)
|
||||
* - [Browser Extensions](https://docs.sentry.io/platforms/javascript/best-practices/browser-extensions/)
|
||||
*
|
||||
* Some of our APIs are typed with the Hub class instead of the interface (e.g. `getCurrentHub`). Most of them are deprecated
|
||||
* themselves and will also be removed in version 8. More information:
|
||||
* - [Migration Guide](https://github.com/getsentry/sentry-javascript/blob/develop/MIGRATION.md#deprecate-hub)
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
class Hub {
|
||||
/** Is a {@link Layer}[] containing the client and scope */
|
||||
|
||||
/** Contains the last event id of a captured event. */
|
||||
|
||||
/**
|
||||
* Creates a new instance of the hub, will push one {@link Layer} into the
|
||||
* internal stack on creation.
|
||||
*
|
||||
* @param client bound to the hub.
|
||||
* @param scope bound to the hub.
|
||||
* @param version number, higher number means higher priority.
|
||||
*
|
||||
* @deprecated Instantiation of Hub objects is deprecated and the constructor will be removed in version 8 of the SDK.
|
||||
*
|
||||
* If you are currently using the Hub for multi-client use like so:
|
||||
*
|
||||
* ```
|
||||
* // OLD
|
||||
* const hub = new Hub();
|
||||
* hub.bindClient(client);
|
||||
* makeMain(hub)
|
||||
* ```
|
||||
*
|
||||
* instead initialize the client as follows:
|
||||
*
|
||||
* ```
|
||||
* // NEW
|
||||
* Sentry.withIsolationScope(() => {
|
||||
* Sentry.setCurrentClient(client);
|
||||
* client.init();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* If you are using the Hub to capture events like so:
|
||||
*
|
||||
* ```
|
||||
* // OLD
|
||||
* const client = new Client();
|
||||
* const hub = new Hub(client);
|
||||
* hub.captureException()
|
||||
* ```
|
||||
*
|
||||
* instead capture isolated events as follows:
|
||||
*
|
||||
* ```
|
||||
* // NEW
|
||||
* const client = new Client();
|
||||
* const scope = new Scope();
|
||||
* scope.setClient(client);
|
||||
* scope.captureException();
|
||||
* ```
|
||||
*/
|
||||
constructor(
|
||||
client,
|
||||
scope,
|
||||
isolationScope,
|
||||
_version = API_VERSION,
|
||||
) {this._version = _version;
|
||||
let assignedScope;
|
||||
if (!scope) {
|
||||
assignedScope = new Scope();
|
||||
assignedScope.setClient(client);
|
||||
} else {
|
||||
assignedScope = scope;
|
||||
}
|
||||
|
||||
let assignedIsolationScope;
|
||||
if (!isolationScope) {
|
||||
assignedIsolationScope = new Scope();
|
||||
assignedIsolationScope.setClient(client);
|
||||
} else {
|
||||
assignedIsolationScope = isolationScope;
|
||||
}
|
||||
|
||||
this._stack = [{ scope: assignedScope }];
|
||||
|
||||
if (client) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.bindClient(client);
|
||||
}
|
||||
|
||||
this._isolationScope = assignedIsolationScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if this hub's version is older than the given version.
|
||||
*
|
||||
* @param version A version number to compare to.
|
||||
* @return True if the given version is newer; otherwise false.
|
||||
*
|
||||
* @deprecated This will be removed in v8.
|
||||
*/
|
||||
isOlderThan(version) {
|
||||
return this._version < version;
|
||||
}
|
||||
|
||||
/**
|
||||
* This binds the given client to the current scope.
|
||||
* @param client An SDK client (client) instance.
|
||||
*
|
||||
* @deprecated Use `initAndBind()` directly, or `setCurrentClient()` and/or `client.init()` instead.
|
||||
*/
|
||||
bindClient(client) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const top = this.getStackTop();
|
||||
top.client = client;
|
||||
top.scope.setClient(client);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (client && client.setupIntegrations) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
client.setupIntegrations();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `withScope` instead.
|
||||
*/
|
||||
pushScope() {
|
||||
// We want to clone the content of prev scope
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const scope = this.getScope().clone();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getStack().push({
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
client: this.getClient(),
|
||||
scope,
|
||||
});
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `withScope` instead.
|
||||
*/
|
||||
popScope() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (this.getStack().length <= 1) return false;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return !!this.getStack().pop();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `Sentry.withScope()` instead.
|
||||
*/
|
||||
withScope(callback) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const scope = this.pushScope();
|
||||
|
||||
let maybePromiseResult;
|
||||
try {
|
||||
maybePromiseResult = callback(scope);
|
||||
} catch (e) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.popScope();
|
||||
throw e;
|
||||
}
|
||||
|
||||
if (isThenable(maybePromiseResult)) {
|
||||
// @ts-expect-error - isThenable returns the wrong type
|
||||
return maybePromiseResult.then(
|
||||
res => {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.popScope();
|
||||
return res;
|
||||
},
|
||||
e => {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.popScope();
|
||||
throw e;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.popScope();
|
||||
return maybePromiseResult;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `Sentry.getClient()` instead.
|
||||
*/
|
||||
getClient() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return this.getStackTop().client ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scope of the top stack.
|
||||
*
|
||||
* @deprecated Use `Sentry.getCurrentScope()` instead.
|
||||
*/
|
||||
getScope() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return this.getStackTop().scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use `Sentry.getIsolationScope()` instead.
|
||||
*/
|
||||
getIsolationScope() {
|
||||
return this._isolationScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scope stack for domains or the process.
|
||||
* @deprecated This will be removed in v8.
|
||||
*/
|
||||
getStack() {
|
||||
return this._stack;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the topmost scope layer in the order domain > local > process.
|
||||
* @deprecated This will be removed in v8.
|
||||
*/
|
||||
getStackTop() {
|
||||
return this._stack[this._stack.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `Sentry.captureException()` instead.
|
||||
*/
|
||||
captureException(exception, hint) {
|
||||
const eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : uuid4());
|
||||
const syntheticException = new Error('Sentry syntheticException');
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().captureException(exception, {
|
||||
originalException: exception,
|
||||
syntheticException,
|
||||
...hint,
|
||||
event_id: eventId,
|
||||
});
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `Sentry.captureMessage()` instead.
|
||||
*/
|
||||
captureMessage(
|
||||
message,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
level,
|
||||
hint,
|
||||
) {
|
||||
const eventId = (this._lastEventId = hint && hint.event_id ? hint.event_id : uuid4());
|
||||
const syntheticException = new Error(message);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().captureMessage(message, level, {
|
||||
originalException: message,
|
||||
syntheticException,
|
||||
...hint,
|
||||
event_id: eventId,
|
||||
});
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `Sentry.captureEvent()` instead.
|
||||
*/
|
||||
captureEvent(event, hint) {
|
||||
const eventId = hint && hint.event_id ? hint.event_id : uuid4();
|
||||
if (!event.type) {
|
||||
this._lastEventId = eventId;
|
||||
}
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().captureEvent(event, { ...hint, event_id: eventId });
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated This will be removed in v8.
|
||||
*/
|
||||
lastEventId() {
|
||||
return this._lastEventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `Sentry.addBreadcrumb()` instead.
|
||||
*/
|
||||
addBreadcrumb(breadcrumb, hint) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { scope, client } = this.getStackTop();
|
||||
|
||||
if (!client) return;
|
||||
|
||||
const { beforeBreadcrumb = null, maxBreadcrumbs = DEFAULT_BREADCRUMBS } =
|
||||
(client.getOptions && client.getOptions()) || {};
|
||||
|
||||
if (maxBreadcrumbs <= 0) return;
|
||||
|
||||
const timestamp = dateTimestampInSeconds();
|
||||
const mergedBreadcrumb = { timestamp, ...breadcrumb };
|
||||
const finalBreadcrumb = beforeBreadcrumb
|
||||
? (consoleSandbox(() => beforeBreadcrumb(mergedBreadcrumb, hint)) )
|
||||
: mergedBreadcrumb;
|
||||
|
||||
if (finalBreadcrumb === null) return;
|
||||
|
||||
if (client.emit) {
|
||||
client.emit('beforeAddBreadcrumb', finalBreadcrumb, hint);
|
||||
}
|
||||
|
||||
// TODO(v8): I know this comment doesn't make much sense because the hub will be deprecated but I still wanted to
|
||||
// write it down. In theory, we would have to add the breadcrumbs to the isolation scope here, however, that would
|
||||
// duplicate all of the breadcrumbs. There was the possibility of adding breadcrumbs to both, the isolation scope
|
||||
// and the normal scope, and deduplicating it down the line in the event processing pipeline. However, that would
|
||||
// have been very fragile, because the breadcrumb objects would have needed to keep their identity all throughout
|
||||
// the event processing pipeline.
|
||||
// In the new implementation, the top level `Sentry.addBreadcrumb()` should ONLY write to the isolation scope.
|
||||
|
||||
scope.addBreadcrumb(finalBreadcrumb, maxBreadcrumbs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.setUser()` instead.
|
||||
*/
|
||||
setUser(user) {
|
||||
// TODO(v8): The top level `Sentry.setUser()` function should write ONLY to the isolation scope.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().setUser(user);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getIsolationScope().setUser(user);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.setTags()` instead.
|
||||
*/
|
||||
setTags(tags) {
|
||||
// TODO(v8): The top level `Sentry.setTags()` function should write ONLY to the isolation scope.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().setTags(tags);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getIsolationScope().setTags(tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.setExtras()` instead.
|
||||
*/
|
||||
setExtras(extras) {
|
||||
// TODO(v8): The top level `Sentry.setExtras()` function should write ONLY to the isolation scope.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().setExtras(extras);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getIsolationScope().setExtras(extras);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.setTag()` instead.
|
||||
*/
|
||||
setTag(key, value) {
|
||||
// TODO(v8): The top level `Sentry.setTag()` function should write ONLY to the isolation scope.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().setTag(key, value);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getIsolationScope().setTag(key, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.setExtra()` instead.
|
||||
*/
|
||||
setExtra(key, extra) {
|
||||
// TODO(v8): The top level `Sentry.setExtra()` function should write ONLY to the isolation scope.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().setExtra(key, extra);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getIsolationScope().setExtra(key, extra);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.setContext()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
setContext(name, context) {
|
||||
// TODO(v8): The top level `Sentry.setContext()` function should write ONLY to the isolation scope.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getScope().setContext(name, context);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.getIsolationScope().setContext(name, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `getScope()` directly.
|
||||
*/
|
||||
configureScope(callback) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { scope, client } = this.getStackTop();
|
||||
if (client) {
|
||||
callback(scope);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
run(callback) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const oldHub = makeMain(this);
|
||||
try {
|
||||
callback(this);
|
||||
} finally {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
makeMain(oldHub);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `Sentry.getClient().getIntegrationByName()` instead.
|
||||
*/
|
||||
getIntegration(integration) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = this.getClient();
|
||||
if (!client) return null;
|
||||
try {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return client.getIntegration(integration);
|
||||
} catch (_oO) {
|
||||
DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts a new `Transaction` and returns it. This is the entry point to manual tracing instrumentation.
|
||||
*
|
||||
* A tree structure can be built by adding child spans to the transaction, and child spans to other spans. To start a
|
||||
* new child span within the transaction or any span, call the respective `.startChild()` method.
|
||||
*
|
||||
* Every child span must be finished before the transaction is finished, otherwise the unfinished spans are discarded.
|
||||
*
|
||||
* The transaction must be finished with a call to its `.end()` method, at which point the transaction with all its
|
||||
* finished child spans will be sent to Sentry.
|
||||
*
|
||||
* @param context Properties of the new `Transaction`.
|
||||
* @param customSamplingContext Information given to the transaction sampling function (along with context-dependent
|
||||
* default values). See {@link Options.tracesSampler}.
|
||||
*
|
||||
* @returns The transaction which was just started
|
||||
*
|
||||
* @deprecated Use `startSpan()`, `startSpanManual()` or `startInactiveSpan()` instead.
|
||||
*/
|
||||
startTransaction(context, customSamplingContext) {
|
||||
const result = this._callExtensionMethod('startTransaction', context, customSamplingContext);
|
||||
|
||||
if (DEBUG_BUILD && !result) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = this.getClient();
|
||||
if (!client) {
|
||||
logger.warn(
|
||||
"Tracing extension 'startTransaction' is missing. You should 'init' the SDK before calling 'startTransaction'",
|
||||
);
|
||||
} else {
|
||||
logger.warn(`Tracing extension 'startTransaction' has not been added. Call 'addTracingExtensions' before calling 'init':
|
||||
Sentry.addTracingExtensions();
|
||||
Sentry.init({...});
|
||||
`);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `spanToTraceHeader()` instead.
|
||||
*/
|
||||
traceHeaders() {
|
||||
return this._callExtensionMethod('traceHeaders');
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use top level `captureSession` instead.
|
||||
*/
|
||||
captureSession(endSession = false) {
|
||||
// both send the update and pull the session from the scope
|
||||
if (endSession) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return this.endSession();
|
||||
}
|
||||
|
||||
// only send the update
|
||||
this._sendSessionUpdate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use top level `endSession` instead.
|
||||
*/
|
||||
endSession() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const layer = this.getStackTop();
|
||||
const scope = layer.scope;
|
||||
const session = scope.getSession();
|
||||
if (session) {
|
||||
closeSession(session);
|
||||
}
|
||||
this._sendSessionUpdate();
|
||||
|
||||
// the session is over; take it off of the scope
|
||||
scope.setSession();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use top level `startSession` instead.
|
||||
*/
|
||||
startSession(context) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { scope, client } = this.getStackTop();
|
||||
const { release, environment = DEFAULT_ENVIRONMENT } = (client && client.getOptions()) || {};
|
||||
|
||||
// Will fetch userAgent if called from browser sdk
|
||||
const { userAgent } = GLOBAL_OBJ.navigator || {};
|
||||
|
||||
const session = makeSession({
|
||||
release,
|
||||
environment,
|
||||
user: scope.getUser(),
|
||||
...(userAgent && { userAgent }),
|
||||
...context,
|
||||
});
|
||||
|
||||
// End existing session if there's one
|
||||
const currentSession = scope.getSession && scope.getSession();
|
||||
if (currentSession && currentSession.status === 'ok') {
|
||||
updateSession(currentSession, { status: 'exited' });
|
||||
}
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.endSession();
|
||||
|
||||
// Afterwards we set the new session on the scope
|
||||
scope.setSession(session);
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns if default PII should be sent to Sentry and propagated in ourgoing requests
|
||||
* when Tracing is used.
|
||||
*
|
||||
* @deprecated Use top-level `getClient().getOptions().sendDefaultPii` instead. This function
|
||||
* only unnecessarily increased API surface but only wrapped accessing the option.
|
||||
*/
|
||||
shouldSendDefaultPii() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = this.getClient();
|
||||
const options = client && client.getOptions();
|
||||
return Boolean(options && options.sendDefaultPii);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the current Session on the scope
|
||||
*/
|
||||
_sendSessionUpdate() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { scope, client } = this.getStackTop();
|
||||
|
||||
const session = scope.getSession();
|
||||
if (session && client && client.captureSession) {
|
||||
client.captureSession(session);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls global extension method and binding current instance to the function call
|
||||
*/
|
||||
// @ts-expect-error Function lacks ending return statement and return type does not include 'undefined'. ts(2366)
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
_callExtensionMethod(method, ...args) {
|
||||
const carrier = getMainCarrier();
|
||||
const sentry = carrier.__SENTRY__;
|
||||
if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') {
|
||||
return sentry.extensions[method].apply(this, args);
|
||||
}
|
||||
DEBUG_BUILD && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the global shim registry.
|
||||
*
|
||||
* FIXME: This function is problematic, because despite always returning a valid Carrier,
|
||||
* it has an optional `__SENTRY__` property, which then in turn requires us to always perform an unnecessary check
|
||||
* at the call-site. We always access the carrier through this function, so we can guarantee that `__SENTRY__` is there.
|
||||
**/
|
||||
function getMainCarrier() {
|
||||
GLOBAL_OBJ.__SENTRY__ = GLOBAL_OBJ.__SENTRY__ || {
|
||||
extensions: {},
|
||||
hub: undefined,
|
||||
};
|
||||
return GLOBAL_OBJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replaces the current main hub with the passed one on the global object
|
||||
*
|
||||
* @returns The old replaced hub
|
||||
*
|
||||
* @deprecated Use `setCurrentClient()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function makeMain(hub) {
|
||||
const registry = getMainCarrier();
|
||||
const oldHub = getHubFromCarrier(registry);
|
||||
setHubOnCarrier(registry, hub);
|
||||
return oldHub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default hub instance.
|
||||
*
|
||||
* If a hub is already registered in the global carrier but this module
|
||||
* contains a more recent version, it replaces the registered version.
|
||||
* Otherwise, the currently registered hub will be returned.
|
||||
*
|
||||
* @deprecated Use the respective replacement method directly instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function getCurrentHub() {
|
||||
// Get main carrier (global for every environment)
|
||||
const registry = getMainCarrier();
|
||||
|
||||
if (registry.__SENTRY__ && registry.__SENTRY__.acs) {
|
||||
const hub = registry.__SENTRY__.acs.getCurrentHub();
|
||||
|
||||
if (hub) {
|
||||
return hub;
|
||||
}
|
||||
}
|
||||
|
||||
// Return hub that lives on a global object
|
||||
return getGlobalHub(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the currently active isolation scope.
|
||||
* The isolation scope is active for the current exection context,
|
||||
* meaning that it will remain stable for the same Hub.
|
||||
*/
|
||||
function getIsolationScope() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentHub().getIsolationScope();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function getGlobalHub(registry = getMainCarrier()) {
|
||||
// If there's no hub, or its an old API, assign a new one
|
||||
|
||||
if (
|
||||
!hasHubOnCarrier(registry) ||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getHubFromCarrier(registry).isOlderThan(API_VERSION)
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
setHubOnCarrier(registry, new Hub());
|
||||
}
|
||||
|
||||
// Return hub that lives on a global object
|
||||
return getHubFromCarrier(registry);
|
||||
}
|
||||
|
||||
/**
|
||||
* @private Private API with no semver guarantees!
|
||||
*
|
||||
* If the carrier does not contain a hub, a new hub is created with the global hub client and scope.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function ensureHubOnCarrier(carrier, parent = getGlobalHub()) {
|
||||
// If there's no hub on current domain, or it's an old API, assign a new one
|
||||
if (
|
||||
!hasHubOnCarrier(carrier) ||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
getHubFromCarrier(carrier).isOlderThan(API_VERSION)
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = parent.getClient();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const scope = parent.getScope();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const isolationScope = parent.getIsolationScope();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
setHubOnCarrier(carrier, new Hub(client, scope.clone(), isolationScope.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private Private API with no semver guarantees!
|
||||
*
|
||||
* Sets the global async context strategy
|
||||
*/
|
||||
function setAsyncContextStrategy(strategy) {
|
||||
// Get main carrier (global for every environment)
|
||||
const registry = getMainCarrier();
|
||||
registry.__SENTRY__ = registry.__SENTRY__ || {};
|
||||
registry.__SENTRY__.acs = strategy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs the supplied callback in its own async context. Async Context strategies are defined per SDK.
|
||||
*
|
||||
* @param callback The callback to run in its own async context
|
||||
* @param options Options to pass to the async context strategy
|
||||
* @returns The result of the callback
|
||||
*/
|
||||
function runWithAsyncContext(callback, options = {}) {
|
||||
const registry = getMainCarrier();
|
||||
|
||||
if (registry.__SENTRY__ && registry.__SENTRY__.acs) {
|
||||
return registry.__SENTRY__.acs.runWithAsyncContext(callback, options);
|
||||
}
|
||||
|
||||
// if there was no strategy, fallback to just calling the callback
|
||||
return callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* This will tell whether a carrier has a hub on it or not
|
||||
* @param carrier object
|
||||
*/
|
||||
function hasHubOnCarrier(carrier) {
|
||||
return !!(carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will create a new {@link Hub} and add to the passed object on
|
||||
* __SENTRY__.hub.
|
||||
* @param carrier object
|
||||
* @hidden
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function getHubFromCarrier(carrier) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getGlobalSingleton('hub', () => new Hub(), carrier);
|
||||
}
|
||||
|
||||
/**
|
||||
* This will set passed {@link Hub} on the passed object's __SENTRY__.hub attribute
|
||||
* @param carrier object
|
||||
* @param hub Hub
|
||||
* @returns A boolean indicating success or failure
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function setHubOnCarrier(carrier, hub) {
|
||||
if (!carrier) return false;
|
||||
const __SENTRY__ = (carrier.__SENTRY__ = carrier.__SENTRY__ || {});
|
||||
__SENTRY__.hub = hub;
|
||||
return true;
|
||||
}
|
||||
|
||||
export { API_VERSION, Hub, ensureHubOnCarrier, getCurrentHub, getHubFromCarrier, getIsolationScope, getMainCarrier, makeMain, runWithAsyncContext, setAsyncContextStrategy, setHubOnCarrier };
|
||||
//# sourceMappingURL=hub.js.map
|
||||
1
node_modules/@sentry/core/esm/hub.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/hub.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
52
node_modules/@sentry/core/esm/index.js
generated
vendored
Normal file
52
node_modules/@sentry/core/esm/index.js
generated
vendored
Normal file
@@ -0,0 +1,52 @@
|
||||
export { addTracingExtensions, startIdleTransaction } from './tracing/hubextensions.js';
|
||||
export { IdleTransaction, TRACING_DEFAULTS } from './tracing/idletransaction.js';
|
||||
export { Span } from './tracing/span.js';
|
||||
export { Transaction } from './tracing/transaction.js';
|
||||
export { extractTraceparentData, getActiveTransaction } from './tracing/utils.js';
|
||||
export { SpanStatus, getSpanStatusFromHttpCode, setHttpStatus, spanStatusfromHttpCode } from './tracing/spanstatus.js';
|
||||
export { continueTrace, getActiveSpan, startActiveSpan, startInactiveSpan, startSpan, startSpanManual, trace } from './tracing/trace.js';
|
||||
export { getDynamicSamplingContextFromClient, getDynamicSamplingContextFromSpan } from './tracing/dynamicSamplingContext.js';
|
||||
export { setMeasurement } from './tracing/measurement.js';
|
||||
export { isValidSampleRate } from './tracing/sampling.js';
|
||||
export { SEMANTIC_ATTRIBUTE_PROFILE_ID, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE } from './semanticAttributes.js';
|
||||
export { createEventEnvelope, createSessionEnvelope } from './envelope.js';
|
||||
export { addBreadcrumb, captureCheckIn, captureEvent, captureException, captureMessage, captureSession, close, configureScope, endSession, flush, getClient, getCurrentScope, isInitialized, lastEventId, setContext, setExtra, setExtras, setTag, setTags, setUser, startSession, startTransaction, withActiveSpan, withIsolationScope, withMonitor, withScope } from './exports.js';
|
||||
export { Hub, ensureHubOnCarrier, getCurrentHub, getHubFromCarrier, getIsolationScope, getMainCarrier, makeMain, runWithAsyncContext, setAsyncContextStrategy, setHubOnCarrier } from './hub.js';
|
||||
export { closeSession, makeSession, updateSession } from './session.js';
|
||||
export { SessionFlusher } from './sessionflusher.js';
|
||||
export { Scope, getGlobalScope, setGlobalScope } from './scope.js';
|
||||
export { addGlobalEventProcessor, notifyEventProcessors } from './eventProcessors.js';
|
||||
export { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint } from './api.js';
|
||||
export { BaseClient, addEventProcessor } from './baseclient.js';
|
||||
export { ServerRuntimeClient } from './server-runtime-client.js';
|
||||
export { initAndBind, setCurrentClient } from './sdk.js';
|
||||
export { createTransport } from './transports/base.js';
|
||||
export { makeOfflineTransport } from './transports/offline.js';
|
||||
export { makeMultiplexedTransport } from './transports/multiplexed.js';
|
||||
export { SDK_VERSION } from './version.js';
|
||||
export { addIntegration, convertIntegrationFnToClass, defineIntegration, getIntegrationsToSetup } from './integration.js';
|
||||
export { applyScopeDataToEvent, mergeScopeData } from './utils/applyScopeDataToEvent.js';
|
||||
export { prepareEvent } from './utils/prepareEvent.js';
|
||||
export { createCheckInEnvelope } from './checkin.js';
|
||||
export { createSpanEnvelope } from './span.js';
|
||||
export { hasTracingEnabled } from './utils/hasTracingEnabled.js';
|
||||
export { isSentryRequestUrl } from './utils/isSentryRequestUrl.js';
|
||||
export { handleCallbackErrors } from './utils/handleCallbackErrors.js';
|
||||
export { parameterize } from './utils/parameterize.js';
|
||||
export { spanIsSampled, spanToJSON, spanToTraceContext, spanToTraceHeader } from './utils/spanUtils.js';
|
||||
export { getRootSpan } from './utils/getRootSpan.js';
|
||||
export { applySdkMetadata } from './utils/sdkMetadata.js';
|
||||
export { DEFAULT_ENVIRONMENT } from './constants.js';
|
||||
export { ModuleMetadata, moduleMetadataIntegration } from './integrations/metadata.js';
|
||||
export { RequestData, requestDataIntegration } from './integrations/requestdata.js';
|
||||
export { InboundFilters, inboundFiltersIntegration } from './integrations/inboundfilters.js';
|
||||
export { FunctionToString, functionToStringIntegration } from './integrations/functiontostring.js';
|
||||
export { LinkedErrors, linkedErrorsIntegration } from './integrations/linkederrors.js';
|
||||
import * as index from './integrations/index.js';
|
||||
export { metrics } from './metrics/exports.js';
|
||||
|
||||
/** @deprecated Import the integration function directly, e.g. `inboundFiltersIntegration()` instead of `new Integrations.InboundFilter(). */
|
||||
const Integrations = index;
|
||||
|
||||
export { Integrations };
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@sentry/core/esm/index.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/index.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sources":["../../src/index.ts"],"sourcesContent":["export type { ClientClass } from './sdk';\nexport type { AsyncContextStrategy, Carrier, Layer, RunWithAsyncContextOptions } from './hub';\nexport type { OfflineStore, OfflineTransportOptions } from './transports/offline';\nexport type { ServerRuntimeClientOptions } from './server-runtime-client';\nexport type { RequestDataIntegrationOptions } from './integrations/requestdata';\nexport type { IntegrationIndex } from './integration';\n\nexport * from './tracing';\nexport * from './semanticAttributes';\nexport { createEventEnvelope, createSessionEnvelope } from './envelope';\nexport {\n addBreadcrumb,\n captureCheckIn,\n withMonitor,\n captureException,\n captureEvent,\n captureMessage,\n close,\n // eslint-disable-next-line deprecation/deprecation\n configureScope,\n flush,\n // eslint-disable-next-line deprecation/deprecation\n lastEventId,\n // eslint-disable-next-line deprecation/deprecation\n startTransaction,\n setContext,\n setExtra,\n setExtras,\n setTag,\n setTags,\n setUser,\n withScope,\n withIsolationScope,\n getClient,\n isInitialized,\n getCurrentScope,\n startSession,\n endSession,\n captureSession,\n withActiveSpan,\n} from './exports';\nexport {\n // eslint-disable-next-line deprecation/deprecation\n getCurrentHub,\n getIsolationScope,\n getHubFromCarrier,\n // eslint-disable-next-line deprecation/deprecation\n Hub,\n // eslint-disable-next-line deprecation/deprecation\n makeMain,\n getMainCarrier,\n runWithAsyncContext,\n setHubOnCarrier,\n ensureHubOnCarrier,\n setAsyncContextStrategy,\n} from './hub';\nexport { makeSession, closeSession, updateSession } from './session';\nexport { SessionFlusher } from './sessionflusher';\nexport { Scope, getGlobalScope, setGlobalScope } from './scope';\nexport {\n notifyEventProcessors,\n // eslint-disable-next-line deprecation/deprecation\n addGlobalEventProcessor,\n} from './eventProcessors';\nexport { getEnvelopeEndpointWithUrlEncodedAuth, getReportDialogEndpoint } from './api';\nexport { BaseClient, addEventProcessor } from './baseclient';\nexport { ServerRuntimeClient } from './server-runtime-client';\nexport { initAndBind, setCurrentClient } from './sdk';\nexport { createTransport } from './transports/base';\nexport { makeOfflineTransport } from './transports/offline';\nexport { makeMultiplexedTransport } from './transports/multiplexed';\nexport { SDK_VERSION } from './version';\nexport {\n getIntegrationsToSetup,\n addIntegration,\n defineIntegration,\n // eslint-disable-next-line deprecation/deprecation\n convertIntegrationFnToClass,\n} from './integration';\nexport { applyScopeDataToEvent, mergeScopeData } from './utils/applyScopeDataToEvent';\nexport { prepareEvent } from './utils/prepareEvent';\nexport { createCheckInEnvelope } from './checkin';\nexport { createSpanEnvelope } from './span';\nexport { hasTracingEnabled } from './utils/hasTracingEnabled';\nexport { isSentryRequestUrl } from './utils/isSentryRequestUrl';\nexport { handleCallbackErrors } from './utils/handleCallbackErrors';\nexport { parameterize } from './utils/parameterize';\nexport { spanToTraceHeader, spanToJSON, spanIsSampled, spanToTraceContext } from './utils/spanUtils';\nexport { getRootSpan } from './utils/getRootSpan';\nexport { applySdkMetadata } from './utils/sdkMetadata';\nexport { DEFAULT_ENVIRONMENT } from './constants';\n/* eslint-disable deprecation/deprecation */\nexport { ModuleMetadata } from './integrations/metadata';\nexport { RequestData } from './integrations/requestdata';\nexport { InboundFilters } from './integrations/inboundfilters';\nexport { FunctionToString } from './integrations/functiontostring';\nexport { LinkedErrors } from './integrations/linkederrors';\n/* eslint-enable deprecation/deprecation */\nimport * as INTEGRATIONS from './integrations';\nexport { functionToStringIntegration } from './integrations/functiontostring';\nexport { inboundFiltersIntegration } from './integrations/inboundfilters';\nexport { linkedErrorsIntegration } from './integrations/linkederrors';\nexport { moduleMetadataIntegration } from './integrations/metadata';\nexport { requestDataIntegration } from './integrations/requestdata';\nexport { metrics } from './metrics/exports';\n\n/** @deprecated Import the integration function directly, e.g. `inboundFiltersIntegration()` instead of `new Integrations.InboundFilter(). */\nconst Integrations = INTEGRATIONS;\n\n// eslint-disable-next-line deprecation/deprecation\nexport { Integrations };\n"],"names":["INTEGRATIONS"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA0GA;AACM,MAAA,YAAA,GAAeA;;;;"}
|
||||
191
node_modules/@sentry/core/esm/integration.js
generated
vendored
Normal file
191
node_modules/@sentry/core/esm/integration.js
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
import { arrayify, logger } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
import { addGlobalEventProcessor } from './eventProcessors.js';
|
||||
import { getClient } from './exports.js';
|
||||
import { getCurrentHub } from './hub.js';
|
||||
|
||||
const installedIntegrations = [];
|
||||
|
||||
/** Map of integrations assigned to a client */
|
||||
|
||||
/**
|
||||
* Remove duplicates from the given array, preferring the last instance of any duplicate. Not guaranteed to
|
||||
* preseve the order of integrations in the array.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
function filterDuplicates(integrations) {
|
||||
const integrationsByName = {};
|
||||
|
||||
integrations.forEach(currentInstance => {
|
||||
const { name } = currentInstance;
|
||||
|
||||
const existingInstance = integrationsByName[name];
|
||||
|
||||
// We want integrations later in the array to overwrite earlier ones of the same type, except that we never want a
|
||||
// default instance to overwrite an existing user instance
|
||||
if (existingInstance && !existingInstance.isDefaultInstance && currentInstance.isDefaultInstance) {
|
||||
return;
|
||||
}
|
||||
|
||||
integrationsByName[name] = currentInstance;
|
||||
});
|
||||
|
||||
return Object.keys(integrationsByName).map(k => integrationsByName[k]);
|
||||
}
|
||||
|
||||
/** Gets integrations to install */
|
||||
function getIntegrationsToSetup(options) {
|
||||
const defaultIntegrations = options.defaultIntegrations || [];
|
||||
const userIntegrations = options.integrations;
|
||||
|
||||
// We flag default instances, so that later we can tell them apart from any user-created instances of the same class
|
||||
defaultIntegrations.forEach(integration => {
|
||||
integration.isDefaultInstance = true;
|
||||
});
|
||||
|
||||
let integrations;
|
||||
|
||||
if (Array.isArray(userIntegrations)) {
|
||||
integrations = [...defaultIntegrations, ...userIntegrations];
|
||||
} else if (typeof userIntegrations === 'function') {
|
||||
integrations = arrayify(userIntegrations(defaultIntegrations));
|
||||
} else {
|
||||
integrations = defaultIntegrations;
|
||||
}
|
||||
|
||||
const finalIntegrations = filterDuplicates(integrations);
|
||||
|
||||
// The `Debug` integration prints copies of the `event` and `hint` which will be passed to `beforeSend` or
|
||||
// `beforeSendTransaction`. It therefore has to run after all other integrations, so that the changes of all event
|
||||
// processors will be reflected in the printed values. For lack of a more elegant way to guarantee that, we therefore
|
||||
// locate it and, assuming it exists, pop it out of its current spot and shove it onto the end of the array.
|
||||
const debugIndex = findIndex(finalIntegrations, integration => integration.name === 'Debug');
|
||||
if (debugIndex !== -1) {
|
||||
const [debugInstance] = finalIntegrations.splice(debugIndex, 1);
|
||||
finalIntegrations.push(debugInstance);
|
||||
}
|
||||
|
||||
return finalIntegrations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of integration instances this installs them all. When `withDefaults` is set to `true` then all default
|
||||
* integrations are added unless they were already provided before.
|
||||
* @param integrations array of integration instances
|
||||
* @param withDefault should enable default integrations
|
||||
*/
|
||||
function setupIntegrations(client, integrations) {
|
||||
const integrationIndex = {};
|
||||
|
||||
integrations.forEach(integration => {
|
||||
// guard against empty provided integrations
|
||||
if (integration) {
|
||||
setupIntegration(client, integration, integrationIndex);
|
||||
}
|
||||
});
|
||||
|
||||
return integrationIndex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the `afterAllSetup` hooks of the given integrations.
|
||||
*/
|
||||
function afterSetupIntegrations(client, integrations) {
|
||||
for (const integration of integrations) {
|
||||
// guard against empty provided integrations
|
||||
if (integration && integration.afterAllSetup) {
|
||||
integration.afterAllSetup(client);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Setup a single integration. */
|
||||
function setupIntegration(client, integration, integrationIndex) {
|
||||
if (integrationIndex[integration.name]) {
|
||||
DEBUG_BUILD && logger.log(`Integration skipped because it was already installed: ${integration.name}`);
|
||||
return;
|
||||
}
|
||||
integrationIndex[integration.name] = integration;
|
||||
|
||||
// `setupOnce` is only called the first time
|
||||
if (installedIntegrations.indexOf(integration.name) === -1) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
integration.setupOnce(addGlobalEventProcessor, getCurrentHub);
|
||||
installedIntegrations.push(integration.name);
|
||||
}
|
||||
|
||||
// `setup` is run for each client
|
||||
if (integration.setup && typeof integration.setup === 'function') {
|
||||
integration.setup(client);
|
||||
}
|
||||
|
||||
if (client.on && typeof integration.preprocessEvent === 'function') {
|
||||
const callback = integration.preprocessEvent.bind(integration) ;
|
||||
client.on('preprocessEvent', (event, hint) => callback(event, hint, client));
|
||||
}
|
||||
|
||||
if (client.addEventProcessor && typeof integration.processEvent === 'function') {
|
||||
const callback = integration.processEvent.bind(integration) ;
|
||||
|
||||
const processor = Object.assign((event, hint) => callback(event, hint, client), {
|
||||
id: integration.name,
|
||||
});
|
||||
|
||||
client.addEventProcessor(processor);
|
||||
}
|
||||
|
||||
DEBUG_BUILD && logger.log(`Integration installed: ${integration.name}`);
|
||||
}
|
||||
|
||||
/** Add an integration to the current hub's client. */
|
||||
function addIntegration(integration) {
|
||||
const client = getClient();
|
||||
|
||||
if (!client || !client.addIntegration) {
|
||||
DEBUG_BUILD && logger.warn(`Cannot add integration "${integration.name}" because no SDK Client is available.`);
|
||||
return;
|
||||
}
|
||||
|
||||
client.addIntegration(integration);
|
||||
}
|
||||
|
||||
// Polyfill for Array.findIndex(), which is not supported in ES5
|
||||
function findIndex(arr, callback) {
|
||||
for (let i = 0; i < arr.length; i++) {
|
||||
if (callback(arr[i]) === true) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a new integration function to the legacy class syntax.
|
||||
* In v8, we can remove this and instead export the integration functions directly.
|
||||
*
|
||||
* @deprecated This will be removed in v8!
|
||||
*/
|
||||
function convertIntegrationFnToClass(
|
||||
name,
|
||||
fn,
|
||||
) {
|
||||
return Object.assign(
|
||||
function ConvertedIntegration(...args) {
|
||||
return fn(...args);
|
||||
},
|
||||
{ id: name },
|
||||
) ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Define an integration function that can be used to create an integration instance.
|
||||
* Note that this by design hides the implementation details of the integration, as they are considered internal.
|
||||
*/
|
||||
function defineIntegration(fn) {
|
||||
return fn;
|
||||
}
|
||||
|
||||
export { addIntegration, afterSetupIntegrations, convertIntegrationFnToClass, defineIntegration, getIntegrationsToSetup, installedIntegrations, setupIntegration, setupIntegrations };
|
||||
//# sourceMappingURL=integration.js.map
|
||||
1
node_modules/@sentry/core/esm/integration.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integration.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
65
node_modules/@sentry/core/esm/integrations/functiontostring.js
generated
vendored
Normal file
65
node_modules/@sentry/core/esm/integrations/functiontostring.js
generated
vendored
Normal file
@@ -0,0 +1,65 @@
|
||||
import { getOriginalFunction } from '@sentry/utils';
|
||||
import { getClient } from '../exports.js';
|
||||
import { convertIntegrationFnToClass, defineIntegration } from '../integration.js';
|
||||
|
||||
let originalFunctionToString;
|
||||
|
||||
const INTEGRATION_NAME = 'FunctionToString';
|
||||
|
||||
const SETUP_CLIENTS = new WeakMap();
|
||||
|
||||
const _functionToStringIntegration = (() => {
|
||||
return {
|
||||
name: INTEGRATION_NAME,
|
||||
setupOnce() {
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
originalFunctionToString = Function.prototype.toString;
|
||||
|
||||
// intrinsics (like Function.prototype) might be immutable in some environments
|
||||
// e.g. Node with --frozen-intrinsics, XS (an embedded JavaScript engine) or SES (a JavaScript proposal)
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
Function.prototype.toString = function ( ...args) {
|
||||
const originalFunction = getOriginalFunction(this);
|
||||
const context =
|
||||
SETUP_CLIENTS.has(getClient() ) && originalFunction !== undefined ? originalFunction : this;
|
||||
return originalFunctionToString.apply(context, args);
|
||||
};
|
||||
} catch (e) {
|
||||
// ignore errors here, just don't patch this
|
||||
}
|
||||
},
|
||||
setup(client) {
|
||||
SETUP_CLIENTS.set(client, true);
|
||||
},
|
||||
};
|
||||
}) ;
|
||||
|
||||
/**
|
||||
* Patch toString calls to return proper name for wrapped functions.
|
||||
*
|
||||
* ```js
|
||||
* Sentry.init({
|
||||
* integrations: [
|
||||
* functionToStringIntegration(),
|
||||
* ],
|
||||
* });
|
||||
* ```
|
||||
*/
|
||||
const functionToStringIntegration = defineIntegration(_functionToStringIntegration);
|
||||
|
||||
/**
|
||||
* Patch toString calls to return proper name for wrapped functions.
|
||||
*
|
||||
* @deprecated Use `functionToStringIntegration()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const FunctionToString = convertIntegrationFnToClass(
|
||||
INTEGRATION_NAME,
|
||||
functionToStringIntegration,
|
||||
) ;
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
|
||||
export { FunctionToString, functionToStringIntegration };
|
||||
//# sourceMappingURL=functiontostring.js.map
|
||||
1
node_modules/@sentry/core/esm/integrations/functiontostring.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integrations/functiontostring.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"functiontostring.js","sources":["../../../src/integrations/functiontostring.ts"],"sourcesContent":["import type { Client, Integration, IntegrationClass, IntegrationFn, WrappedFunction } from '@sentry/types';\nimport { getOriginalFunction } from '@sentry/utils';\nimport { getClient } from '../exports';\nimport { convertIntegrationFnToClass, defineIntegration } from '../integration';\n\nlet originalFunctionToString: () => void;\n\nconst INTEGRATION_NAME = 'FunctionToString';\n\nconst SETUP_CLIENTS = new WeakMap<Client, boolean>();\n\nconst _functionToStringIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n setupOnce() {\n // eslint-disable-next-line @typescript-eslint/unbound-method\n originalFunctionToString = Function.prototype.toString;\n\n // intrinsics (like Function.prototype) might be immutable in some environments\n // e.g. Node with --frozen-intrinsics, XS (an embedded JavaScript engine) or SES (a JavaScript proposal)\n try {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n Function.prototype.toString = function (this: WrappedFunction, ...args: any[]): string {\n const originalFunction = getOriginalFunction(this);\n const context =\n SETUP_CLIENTS.has(getClient() as Client) && originalFunction !== undefined ? originalFunction : this;\n return originalFunctionToString.apply(context, args);\n };\n } catch {\n // ignore errors here, just don't patch this\n }\n },\n setup(client) {\n SETUP_CLIENTS.set(client, true);\n },\n };\n}) satisfies IntegrationFn;\n\n/**\n * Patch toString calls to return proper name for wrapped functions.\n *\n * ```js\n * Sentry.init({\n * integrations: [\n * functionToStringIntegration(),\n * ],\n * });\n * ```\n */\nexport const functionToStringIntegration = defineIntegration(_functionToStringIntegration);\n\n/**\n * Patch toString calls to return proper name for wrapped functions.\n *\n * @deprecated Use `functionToStringIntegration()` instead.\n */\n// eslint-disable-next-line deprecation/deprecation\nexport const FunctionToString = convertIntegrationFnToClass(\n INTEGRATION_NAME,\n functionToStringIntegration,\n) as IntegrationClass<Integration & { setupOnce: () => void }>;\n\n// eslint-disable-next-line deprecation/deprecation\nexport type FunctionToString = typeof FunctionToString;\n"],"names":[],"mappings":";;;;AAKA,IAAI,wBAAwB,CAAA;AAC5B;AACA,MAAM,gBAAA,GAAmB,kBAAkB,CAAA;AAC3C;AACA,MAAM,aAAc,GAAE,IAAI,OAAO,EAAmB,CAAA;AACpD;AACA,MAAM,4BAA6B,IAAG,MAAM;AAC5C,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B,IAAI,SAAS,GAAG;AAChB;AACA,MAAM,2BAA2B,QAAQ,CAAC,SAAS,CAAC,QAAQ,CAAA;AAC5D;AACA;AACA;AACA,MAAM,IAAI;AACV;AACA,QAAQ,QAAQ,CAAC,SAAS,CAAC,QAAS,GAAE,WAAiC,GAAG,IAAI,EAAiB;AAC/F,UAAU,MAAM,gBAAiB,GAAE,mBAAmB,CAAC,IAAI,CAAC,CAAA;AAC5D,UAAU,MAAM,OAAQ;AACxB,YAAY,aAAa,CAAC,GAAG,CAAC,SAAS,EAAC,EAAa,IAAG,qBAAqB,SAAA,GAAY,gBAAA,GAAmB,IAAI,CAAA;AAChH,UAAU,OAAO,wBAAwB,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAA;AAC9D,SAAS,CAAA;AACT,QAAQ,OAAM,CAAA,EAAA;AACd;AACA,OAAM;AACN,KAAK;AACL,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,aAAa,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;AACrC,KAAK;AACL,GAAG,CAAA;AACH,CAAC,CAAE,EAAA;AACH;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;MACa,2BAA4B,GAAE,iBAAiB,CAAC,4BAA4B,EAAC;AAC1F;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,gBAAiB,GAAE,2BAA2B;AAC3D,EAAE,gBAAgB;AAClB,EAAE,2BAA2B;AAC7B,CAAE,EAAA;AACF;AACA;;;;"}
|
||||
224
node_modules/@sentry/core/esm/integrations/inboundfilters.js
generated
vendored
Normal file
224
node_modules/@sentry/core/esm/integrations/inboundfilters.js
generated
vendored
Normal file
@@ -0,0 +1,224 @@
|
||||
import { logger, getEventDescription, stringMatchesSomePattern } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { convertIntegrationFnToClass, defineIntegration } from '../integration.js';
|
||||
|
||||
// "Script error." is hard coded into browsers for errors that it can't read.
|
||||
// this is the result of a script being pulled in from an external domain and CORS.
|
||||
const DEFAULT_IGNORE_ERRORS = [
|
||||
/^Script error\.?$/,
|
||||
/^Javascript error: Script error\.? on line 0$/,
|
||||
/^ResizeObserver loop completed with undelivered notifications.$/,
|
||||
/^Cannot redefine property: googletag$/,
|
||||
];
|
||||
|
||||
const DEFAULT_IGNORE_TRANSACTIONS = [
|
||||
/^.*\/healthcheck$/,
|
||||
/^.*\/healthy$/,
|
||||
/^.*\/live$/,
|
||||
/^.*\/ready$/,
|
||||
/^.*\/heartbeat$/,
|
||||
/^.*\/health$/,
|
||||
/^.*\/healthz$/,
|
||||
];
|
||||
|
||||
/** Options for the InboundFilters integration */
|
||||
|
||||
const INTEGRATION_NAME = 'InboundFilters';
|
||||
const _inboundFiltersIntegration = ((options = {}) => {
|
||||
return {
|
||||
name: INTEGRATION_NAME,
|
||||
// TODO v8: Remove this
|
||||
setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
processEvent(event, _hint, client) {
|
||||
const clientOptions = client.getOptions();
|
||||
const mergedOptions = _mergeOptions(options, clientOptions);
|
||||
return _shouldDropEvent(event, mergedOptions) ? null : event;
|
||||
},
|
||||
};
|
||||
}) ;
|
||||
|
||||
const inboundFiltersIntegration = defineIntegration(_inboundFiltersIntegration);
|
||||
|
||||
/**
|
||||
* Inbound filters configurable by the user.
|
||||
* @deprecated Use `inboundFiltersIntegration()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const InboundFilters = convertIntegrationFnToClass(
|
||||
INTEGRATION_NAME,
|
||||
inboundFiltersIntegration,
|
||||
)
|
||||
|
||||
;
|
||||
|
||||
function _mergeOptions(
|
||||
internalOptions = {},
|
||||
clientOptions = {},
|
||||
) {
|
||||
return {
|
||||
allowUrls: [...(internalOptions.allowUrls || []), ...(clientOptions.allowUrls || [])],
|
||||
denyUrls: [...(internalOptions.denyUrls || []), ...(clientOptions.denyUrls || [])],
|
||||
ignoreErrors: [
|
||||
...(internalOptions.ignoreErrors || []),
|
||||
...(clientOptions.ignoreErrors || []),
|
||||
...(internalOptions.disableErrorDefaults ? [] : DEFAULT_IGNORE_ERRORS),
|
||||
],
|
||||
ignoreTransactions: [
|
||||
...(internalOptions.ignoreTransactions || []),
|
||||
...(clientOptions.ignoreTransactions || []),
|
||||
...(internalOptions.disableTransactionDefaults ? [] : DEFAULT_IGNORE_TRANSACTIONS),
|
||||
],
|
||||
ignoreInternal: internalOptions.ignoreInternal !== undefined ? internalOptions.ignoreInternal : true,
|
||||
};
|
||||
}
|
||||
|
||||
function _shouldDropEvent(event, options) {
|
||||
if (options.ignoreInternal && _isSentryError(event)) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`);
|
||||
return true;
|
||||
}
|
||||
if (_isIgnoredError(event, options.ignoreErrors)) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(
|
||||
`Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
if (_isIgnoredTransaction(event, options.ignoreTransactions)) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(
|
||||
`Event dropped due to being matched by \`ignoreTransactions\` option.\nEvent: ${getEventDescription(event)}`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
if (_isDeniedUrl(event, options.denyUrls)) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(
|
||||
`Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription(
|
||||
event,
|
||||
)}.\nUrl: ${_getEventFilterUrl(event)}`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
if (!_isAllowedUrl(event, options.allowUrls)) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(
|
||||
`Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription(
|
||||
event,
|
||||
)}.\nUrl: ${_getEventFilterUrl(event)}`,
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function _isIgnoredError(event, ignoreErrors) {
|
||||
// If event.type, this is not an error
|
||||
if (event.type || !ignoreErrors || !ignoreErrors.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return _getPossibleEventMessages(event).some(message => stringMatchesSomePattern(message, ignoreErrors));
|
||||
}
|
||||
|
||||
function _isIgnoredTransaction(event, ignoreTransactions) {
|
||||
if (event.type !== 'transaction' || !ignoreTransactions || !ignoreTransactions.length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const name = event.transaction;
|
||||
return name ? stringMatchesSomePattern(name, ignoreTransactions) : false;
|
||||
}
|
||||
|
||||
function _isDeniedUrl(event, denyUrls) {
|
||||
// TODO: Use Glob instead?
|
||||
if (!denyUrls || !denyUrls.length) {
|
||||
return false;
|
||||
}
|
||||
const url = _getEventFilterUrl(event);
|
||||
return !url ? false : stringMatchesSomePattern(url, denyUrls);
|
||||
}
|
||||
|
||||
function _isAllowedUrl(event, allowUrls) {
|
||||
// TODO: Use Glob instead?
|
||||
if (!allowUrls || !allowUrls.length) {
|
||||
return true;
|
||||
}
|
||||
const url = _getEventFilterUrl(event);
|
||||
return !url ? true : stringMatchesSomePattern(url, allowUrls);
|
||||
}
|
||||
|
||||
function _getPossibleEventMessages(event) {
|
||||
const possibleMessages = [];
|
||||
|
||||
if (event.message) {
|
||||
possibleMessages.push(event.message);
|
||||
}
|
||||
|
||||
let lastException;
|
||||
try {
|
||||
// @ts-expect-error Try catching to save bundle size
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
lastException = event.exception.values[event.exception.values.length - 1];
|
||||
} catch (e) {
|
||||
// try catching to save bundle size checking existence of variables
|
||||
}
|
||||
|
||||
if (lastException) {
|
||||
if (lastException.value) {
|
||||
possibleMessages.push(lastException.value);
|
||||
if (lastException.type) {
|
||||
possibleMessages.push(`${lastException.type}: ${lastException.value}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (DEBUG_BUILD && possibleMessages.length === 0) {
|
||||
logger.error(`Could not extract message for event ${getEventDescription(event)}`);
|
||||
}
|
||||
|
||||
return possibleMessages;
|
||||
}
|
||||
|
||||
function _isSentryError(event) {
|
||||
try {
|
||||
// @ts-expect-error can't be a sentry error if undefined
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
return event.exception.values[0].type === 'SentryError';
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function _getLastValidUrl(frames = []) {
|
||||
for (let i = frames.length - 1; i >= 0; i--) {
|
||||
const frame = frames[i];
|
||||
|
||||
if (frame && frame.filename !== '<anonymous>' && frame.filename !== '[native code]') {
|
||||
return frame.filename || null;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
function _getEventFilterUrl(event) {
|
||||
try {
|
||||
let frames;
|
||||
try {
|
||||
// @ts-expect-error we only care about frames if the whole thing here is defined
|
||||
frames = event.exception.values[0].stacktrace.frames;
|
||||
} catch (e) {
|
||||
// ignore
|
||||
}
|
||||
return frames ? _getLastValidUrl(frames) : null;
|
||||
} catch (oO) {
|
||||
DEBUG_BUILD && logger.error(`Cannot extract url for event ${getEventDescription(event)}`);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
export { InboundFilters, inboundFiltersIntegration };
|
||||
//# sourceMappingURL=inboundfilters.js.map
|
||||
1
node_modules/@sentry/core/esm/integrations/inboundfilters.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integrations/inboundfilters.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
6
node_modules/@sentry/core/esm/integrations/index.js
generated
vendored
Normal file
6
node_modules/@sentry/core/esm/integrations/index.js
generated
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
export { FunctionToString } from './functiontostring.js';
|
||||
export { InboundFilters } from './inboundfilters.js';
|
||||
export { LinkedErrors } from './linkederrors.js';
|
||||
|
||||
/* eslint-disable deprecation/deprecation */
|
||||
//# sourceMappingURL=index.js.map
|
||||
1
node_modules/@sentry/core/esm/integrations/index.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integrations/index.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"index.js","sources":["../../../src/integrations/index.ts"],"sourcesContent":["/* eslint-disable deprecation/deprecation */\nexport { FunctionToString } from './functiontostring';\nexport { InboundFilters } from './inboundfilters';\nexport { LinkedErrors } from './linkederrors';\n"],"names":[],"mappings":";;;;AAAA"}
|
||||
45
node_modules/@sentry/core/esm/integrations/linkederrors.js
generated
vendored
Normal file
45
node_modules/@sentry/core/esm/integrations/linkederrors.js
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
import { applyAggregateErrorsToEvent, exceptionFromError } from '@sentry/utils';
|
||||
import { convertIntegrationFnToClass, defineIntegration } from '../integration.js';
|
||||
|
||||
const DEFAULT_KEY = 'cause';
|
||||
const DEFAULT_LIMIT = 5;
|
||||
|
||||
const INTEGRATION_NAME = 'LinkedErrors';
|
||||
|
||||
const _linkedErrorsIntegration = ((options = {}) => {
|
||||
const limit = options.limit || DEFAULT_LIMIT;
|
||||
const key = options.key || DEFAULT_KEY;
|
||||
|
||||
return {
|
||||
name: INTEGRATION_NAME,
|
||||
// TODO v8: Remove this
|
||||
setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
preprocessEvent(event, hint, client) {
|
||||
const options = client.getOptions();
|
||||
|
||||
applyAggregateErrorsToEvent(
|
||||
exceptionFromError,
|
||||
options.stackParser,
|
||||
options.maxValueLength,
|
||||
key,
|
||||
limit,
|
||||
event,
|
||||
hint,
|
||||
);
|
||||
},
|
||||
};
|
||||
}) ;
|
||||
|
||||
const linkedErrorsIntegration = defineIntegration(_linkedErrorsIntegration);
|
||||
|
||||
/**
|
||||
* Adds SDK info to an event.
|
||||
* @deprecated Use `linkedErrorsIntegration()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const LinkedErrors = convertIntegrationFnToClass(INTEGRATION_NAME, linkedErrorsIntegration)
|
||||
|
||||
;
|
||||
|
||||
export { LinkedErrors, linkedErrorsIntegration };
|
||||
//# sourceMappingURL=linkederrors.js.map
|
||||
1
node_modules/@sentry/core/esm/integrations/linkederrors.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integrations/linkederrors.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"linkederrors.js","sources":["../../../src/integrations/linkederrors.ts"],"sourcesContent":["import type { Client, Event, EventHint, Integration, IntegrationClass, IntegrationFn } from '@sentry/types';\nimport { applyAggregateErrorsToEvent, exceptionFromError } from '@sentry/utils';\nimport { convertIntegrationFnToClass, defineIntegration } from '../integration';\n\ninterface LinkedErrorsOptions {\n key?: string;\n limit?: number;\n}\n\nconst DEFAULT_KEY = 'cause';\nconst DEFAULT_LIMIT = 5;\n\nconst INTEGRATION_NAME = 'LinkedErrors';\n\nconst _linkedErrorsIntegration = ((options: LinkedErrorsOptions = {}) => {\n const limit = options.limit || DEFAULT_LIMIT;\n const key = options.key || DEFAULT_KEY;\n\n return {\n name: INTEGRATION_NAME,\n // TODO v8: Remove this\n setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function\n preprocessEvent(event, hint, client) {\n const options = client.getOptions();\n\n applyAggregateErrorsToEvent(\n exceptionFromError,\n options.stackParser,\n options.maxValueLength,\n key,\n limit,\n event,\n hint,\n );\n },\n };\n}) satisfies IntegrationFn;\n\nexport const linkedErrorsIntegration = defineIntegration(_linkedErrorsIntegration);\n\n/**\n * Adds SDK info to an event.\n * @deprecated Use `linkedErrorsIntegration()` instead.\n */\n// eslint-disable-next-line deprecation/deprecation\nexport const LinkedErrors = convertIntegrationFnToClass(INTEGRATION_NAME, linkedErrorsIntegration) as IntegrationClass<\n Integration & { preprocessEvent: (event: Event, hint: EventHint, client: Client) => void }\n> & { new (options?: { key?: string; limit?: number }): Integration };\n"],"names":[],"mappings":";;;AASA,MAAM,WAAA,GAAc,OAAO,CAAA;AAC3B,MAAM,aAAA,GAAgB,CAAC,CAAA;AACvB;AACA,MAAM,gBAAA,GAAmB,cAAc,CAAA;AACvC;AACA,MAAM,wBAAA,IAA4B,CAAC,OAAO,GAAwB,EAAE,KAAK;AACzE,EAAE,MAAM,KAAM,GAAE,OAAO,CAAC,KAAA,IAAS,aAAa,CAAA;AAC9C,EAAE,MAAM,GAAI,GAAE,OAAO,CAAC,GAAA,IAAO,WAAW,CAAA;AACxC;AACA,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B;AACA,IAAI,SAAS,GAAG,EAAE;AAClB,IAAI,eAAe,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE;AACzC,MAAM,MAAM,OAAQ,GAAE,MAAM,CAAC,UAAU,EAAE,CAAA;AACzC;AACA,MAAM,2BAA2B;AACjC,QAAQ,kBAAkB;AAC1B,QAAQ,OAAO,CAAC,WAAW;AAC3B,QAAQ,OAAO,CAAC,cAAc;AAC9B,QAAQ,GAAG;AACX,QAAQ,KAAK;AACb,QAAQ,KAAK;AACb,QAAQ,IAAI;AACZ,OAAO,CAAA;AACP,KAAK;AACL,GAAG,CAAA;AACH,CAAC,CAAE,EAAA;AACH;MACa,uBAAwB,GAAE,iBAAiB,CAAC,wBAAwB,EAAC;AAClF;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,eAAe,2BAA2B,CAAC,gBAAgB,EAAE,uBAAuB,CAAE;;;;;;"}
|
||||
62
node_modules/@sentry/core/esm/integrations/metadata.js
generated
vendored
Normal file
62
node_modules/@sentry/core/esm/integrations/metadata.js
generated
vendored
Normal file
@@ -0,0 +1,62 @@
|
||||
import { forEachEnvelopeItem } from '@sentry/utils';
|
||||
import { convertIntegrationFnToClass, defineIntegration } from '../integration.js';
|
||||
import { stripMetadataFromStackFrames, addMetadataToStackFrames } from '../metadata.js';
|
||||
|
||||
const INTEGRATION_NAME = 'ModuleMetadata';
|
||||
|
||||
const _moduleMetadataIntegration = (() => {
|
||||
return {
|
||||
name: INTEGRATION_NAME,
|
||||
// TODO v8: Remove this
|
||||
setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
setup(client) {
|
||||
if (typeof client.on !== 'function') {
|
||||
return;
|
||||
}
|
||||
|
||||
// We need to strip metadata from stack frames before sending them to Sentry since these are client side only.
|
||||
client.on('beforeEnvelope', envelope => {
|
||||
forEachEnvelopeItem(envelope, (item, type) => {
|
||||
if (type === 'event') {
|
||||
const event = Array.isArray(item) ? (item )[1] : undefined;
|
||||
|
||||
if (event) {
|
||||
stripMetadataFromStackFrames(event);
|
||||
item[1] = event;
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
processEvent(event, _hint, client) {
|
||||
const stackParser = client.getOptions().stackParser;
|
||||
addMetadataToStackFrames(stackParser, event);
|
||||
return event;
|
||||
},
|
||||
};
|
||||
}) ;
|
||||
|
||||
const moduleMetadataIntegration = defineIntegration(_moduleMetadataIntegration);
|
||||
|
||||
/**
|
||||
* Adds module metadata to stack frames.
|
||||
*
|
||||
* Metadata can be injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.
|
||||
*
|
||||
* When this integration is added, the metadata passed to the bundler plugin is added to the stack frames of all events
|
||||
* under the `module_metadata` property. This can be used to help in tagging or routing of events from different teams
|
||||
* our sources
|
||||
*
|
||||
* @deprecated Use `moduleMetadataIntegration()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const ModuleMetadata = convertIntegrationFnToClass(
|
||||
INTEGRATION_NAME,
|
||||
moduleMetadataIntegration,
|
||||
)
|
||||
|
||||
;
|
||||
|
||||
export { ModuleMetadata, moduleMetadataIntegration };
|
||||
//# sourceMappingURL=metadata.js.map
|
||||
1
node_modules/@sentry/core/esm/integrations/metadata.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integrations/metadata.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"metadata.js","sources":["../../../src/integrations/metadata.ts"],"sourcesContent":["import type { Client, Event, EventHint, EventItem, Integration, IntegrationClass, IntegrationFn } from '@sentry/types';\nimport { forEachEnvelopeItem } from '@sentry/utils';\nimport { convertIntegrationFnToClass, defineIntegration } from '../integration';\n\nimport { addMetadataToStackFrames, stripMetadataFromStackFrames } from '../metadata';\n\nconst INTEGRATION_NAME = 'ModuleMetadata';\n\nconst _moduleMetadataIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n // TODO v8: Remove this\n setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function\n setup(client) {\n if (typeof client.on !== 'function') {\n return;\n }\n\n // We need to strip metadata from stack frames before sending them to Sentry since these are client side only.\n client.on('beforeEnvelope', envelope => {\n forEachEnvelopeItem(envelope, (item, type) => {\n if (type === 'event') {\n const event = Array.isArray(item) ? (item as EventItem)[1] : undefined;\n\n if (event) {\n stripMetadataFromStackFrames(event);\n item[1] = event;\n }\n }\n });\n });\n },\n\n processEvent(event, _hint, client) {\n const stackParser = client.getOptions().stackParser;\n addMetadataToStackFrames(stackParser, event);\n return event;\n },\n };\n}) satisfies IntegrationFn;\n\nexport const moduleMetadataIntegration = defineIntegration(_moduleMetadataIntegration);\n\n/**\n * Adds module metadata to stack frames.\n *\n * Metadata can be injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.\n *\n * When this integration is added, the metadata passed to the bundler plugin is added to the stack frames of all events\n * under the `module_metadata` property. This can be used to help in tagging or routing of events from different teams\n * our sources\n *\n * @deprecated Use `moduleMetadataIntegration()` instead.\n */\n// eslint-disable-next-line deprecation/deprecation\nexport const ModuleMetadata = convertIntegrationFnToClass(\n INTEGRATION_NAME,\n moduleMetadataIntegration,\n) as IntegrationClass<\n Integration & {\n setup: (client: Client) => void;\n processEvent: (event: Event, hint: EventHint, client: Client) => Event;\n }\n>;\n"],"names":[],"mappings":";;;;AAMA,MAAM,gBAAA,GAAmB,gBAAgB,CAAA;AACzC;AACA,MAAM,0BAA2B,IAAG,MAAM;AAC1C,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B;AACA,IAAI,SAAS,GAAG,EAAE;AAClB,IAAI,KAAK,CAAC,MAAM,EAAE;AAClB,MAAM,IAAI,OAAO,MAAM,CAAC,EAAG,KAAI,UAAU,EAAE;AAC3C,QAAQ,OAAM;AACd,OAAM;AACN;AACA;AACA,MAAM,MAAM,CAAC,EAAE,CAAC,gBAAgB,EAAE,YAAY;AAC9C,QAAQ,mBAAmB,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK;AACtD,UAAU,IAAI,IAAK,KAAI,OAAO,EAAE;AAChC,YAAY,MAAM,KAAM,GAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAE,GAAE,CAAC,IAAK,GAAc,CAAC,CAAA,GAAI,SAAS,CAAA;AAClF;AACA,YAAY,IAAI,KAAK,EAAE;AACvB,cAAc,4BAA4B,CAAC,KAAK,CAAC,CAAA;AACjD,cAAc,IAAI,CAAC,CAAC,CAAA,GAAI,KAAK,CAAA;AAC7B,aAAY;AACZ,WAAU;AACV,SAAS,CAAC,CAAA;AACV,OAAO,CAAC,CAAA;AACR,KAAK;AACL;AACA,IAAI,YAAY,CAAC,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE;AACvC,MAAM,MAAM,cAAc,MAAM,CAAC,UAAU,EAAE,CAAC,WAAW,CAAA;AACzD,MAAM,wBAAwB,CAAC,WAAW,EAAE,KAAK,CAAC,CAAA;AAClD,MAAM,OAAO,KAAK,CAAA;AAClB,KAAK;AACL,GAAG,CAAA;AACH,CAAC,CAAE,EAAA;AACH;MACa,yBAA0B,GAAE,iBAAiB,CAAC,0BAA0B,EAAC;AACtF;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,cAAe,GAAE,2BAA2B;AACzD,EAAE,gBAAgB;AAClB,EAAE,yBAAyB;AAC3B,CAAE;;;;;;"}
|
||||
175
node_modules/@sentry/core/esm/integrations/requestdata.js
generated
vendored
Normal file
175
node_modules/@sentry/core/esm/integrations/requestdata.js
generated
vendored
Normal file
@@ -0,0 +1,175 @@
|
||||
import { extractPathForTransaction, addRequestDataToEvent } from '@sentry/utils';
|
||||
import { convertIntegrationFnToClass, defineIntegration } from '../integration.js';
|
||||
import { spanToJSON } from '../utils/spanUtils.js';
|
||||
|
||||
const DEFAULT_OPTIONS = {
|
||||
include: {
|
||||
cookies: true,
|
||||
data: true,
|
||||
headers: true,
|
||||
ip: false,
|
||||
query_string: true,
|
||||
url: true,
|
||||
user: {
|
||||
id: true,
|
||||
username: true,
|
||||
email: true,
|
||||
},
|
||||
},
|
||||
transactionNamingScheme: 'methodPath',
|
||||
};
|
||||
|
||||
const INTEGRATION_NAME = 'RequestData';
|
||||
|
||||
const _requestDataIntegration = ((options = {}) => {
|
||||
const _addRequestData = addRequestDataToEvent;
|
||||
const _options = {
|
||||
...DEFAULT_OPTIONS,
|
||||
...options,
|
||||
include: {
|
||||
// @ts-expect-error It's mad because `method` isn't a known `include` key. (It's only here and not set by default in
|
||||
// `addRequestDataToEvent` for legacy reasons. TODO (v8): Change that.)
|
||||
method: true,
|
||||
...DEFAULT_OPTIONS.include,
|
||||
...options.include,
|
||||
user:
|
||||
options.include && typeof options.include.user === 'boolean'
|
||||
? options.include.user
|
||||
: {
|
||||
...DEFAULT_OPTIONS.include.user,
|
||||
// Unclear why TS still thinks `options.include.user` could be a boolean at this point
|
||||
...((options.include || {}).user ),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
return {
|
||||
name: INTEGRATION_NAME,
|
||||
// TODO v8: Remove this
|
||||
setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
processEvent(event, _hint, client) {
|
||||
// Note: In the long run, most of the logic here should probably move into the request data utility functions. For
|
||||
// the moment it lives here, though, until https://github.com/getsentry/sentry-javascript/issues/5718 is addressed.
|
||||
// (TL;DR: Those functions touch many parts of the repo in many different ways, and need to be clened up. Once
|
||||
// that's happened, it will be easier to add this logic in without worrying about unexpected side effects.)
|
||||
const { transactionNamingScheme } = _options;
|
||||
|
||||
const { sdkProcessingMetadata = {} } = event;
|
||||
const req = sdkProcessingMetadata.request;
|
||||
|
||||
if (!req) {
|
||||
return event;
|
||||
}
|
||||
|
||||
// The Express request handler takes a similar `include` option to that which can be passed to this integration.
|
||||
// If passed there, we store it in `sdkProcessingMetadata`. TODO(v8): Force express and GCP people to use this
|
||||
// integration, so that all of this passing and conversion isn't necessary
|
||||
const addRequestDataOptions =
|
||||
sdkProcessingMetadata.requestDataOptionsFromExpressHandler ||
|
||||
sdkProcessingMetadata.requestDataOptionsFromGCPWrapper ||
|
||||
convertReqDataIntegrationOptsToAddReqDataOpts(_options);
|
||||
|
||||
const processedEvent = _addRequestData(event, req, addRequestDataOptions);
|
||||
|
||||
// Transaction events already have the right `transaction` value
|
||||
if (event.type === 'transaction' || transactionNamingScheme === 'handler') {
|
||||
return processedEvent;
|
||||
}
|
||||
|
||||
// In all other cases, use the request's associated transaction (if any) to overwrite the event's `transaction`
|
||||
// value with a high-quality one
|
||||
const reqWithTransaction = req ;
|
||||
const transaction = reqWithTransaction._sentryTransaction;
|
||||
if (transaction) {
|
||||
const name = spanToJSON(transaction).description || '';
|
||||
|
||||
// TODO (v8): Remove the nextjs check and just base it on `transactionNamingScheme` for all SDKs. (We have to
|
||||
// keep it the way it is for the moment, because changing the names of transactions in Sentry has the potential
|
||||
// to break things like alert rules.)
|
||||
const shouldIncludeMethodInTransactionName =
|
||||
getSDKName(client) === 'sentry.javascript.nextjs'
|
||||
? name.startsWith('/api')
|
||||
: transactionNamingScheme !== 'path';
|
||||
|
||||
const [transactionValue] = extractPathForTransaction(req, {
|
||||
path: true,
|
||||
method: shouldIncludeMethodInTransactionName,
|
||||
customRoute: name,
|
||||
});
|
||||
|
||||
processedEvent.transaction = transactionValue;
|
||||
}
|
||||
|
||||
return processedEvent;
|
||||
},
|
||||
};
|
||||
}) ;
|
||||
|
||||
const requestDataIntegration = defineIntegration(_requestDataIntegration);
|
||||
|
||||
/**
|
||||
* Add data about a request to an event. Primarily for use in Node-based SDKs, but included in `@sentry/integrations`
|
||||
* so it can be used in cross-platform SDKs like `@sentry/nextjs`.
|
||||
* @deprecated Use `requestDataIntegration()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const RequestData = convertIntegrationFnToClass(INTEGRATION_NAME, requestDataIntegration)
|
||||
|
||||
;
|
||||
|
||||
/** Convert this integration's options to match what `addRequestDataToEvent` expects */
|
||||
/** TODO: Can possibly be deleted once https://github.com/getsentry/sentry-javascript/issues/5718 is fixed */
|
||||
function convertReqDataIntegrationOptsToAddReqDataOpts(
|
||||
integrationOptions,
|
||||
) {
|
||||
const {
|
||||
transactionNamingScheme,
|
||||
include: { ip, user, ...requestOptions },
|
||||
} = integrationOptions;
|
||||
|
||||
const requestIncludeKeys = [];
|
||||
for (const [key, value] of Object.entries(requestOptions)) {
|
||||
if (value) {
|
||||
requestIncludeKeys.push(key);
|
||||
}
|
||||
}
|
||||
|
||||
let addReqDataUserOpt;
|
||||
if (user === undefined) {
|
||||
addReqDataUserOpt = true;
|
||||
} else if (typeof user === 'boolean') {
|
||||
addReqDataUserOpt = user;
|
||||
} else {
|
||||
const userIncludeKeys = [];
|
||||
for (const [key, value] of Object.entries(user)) {
|
||||
if (value) {
|
||||
userIncludeKeys.push(key);
|
||||
}
|
||||
}
|
||||
addReqDataUserOpt = userIncludeKeys;
|
||||
}
|
||||
|
||||
return {
|
||||
include: {
|
||||
ip,
|
||||
user: addReqDataUserOpt,
|
||||
request: requestIncludeKeys.length !== 0 ? requestIncludeKeys : undefined,
|
||||
transaction: transactionNamingScheme,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function getSDKName(client) {
|
||||
try {
|
||||
// For a long chain like this, it's fewer bytes to combine a try-catch with assuming everything is there than to
|
||||
// write out a long chain of `a && a.b && a.b.c && ...`
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
return client.getOptions()._metadata.sdk.name;
|
||||
} catch (err) {
|
||||
// In theory we should never get here
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export { RequestData, requestDataIntegration };
|
||||
//# sourceMappingURL=requestdata.js.map
|
||||
1
node_modules/@sentry/core/esm/integrations/requestdata.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/integrations/requestdata.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
99
node_modules/@sentry/core/esm/metadata.js
generated
vendored
Normal file
99
node_modules/@sentry/core/esm/metadata.js
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
import { GLOBAL_OBJ } from '@sentry/utils';
|
||||
|
||||
/** Keys are source filename/url, values are metadata objects. */
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const filenameMetadataMap = new Map();
|
||||
/** Set of stack strings that have already been parsed. */
|
||||
const parsedStacks = new Set();
|
||||
|
||||
function ensureMetadataStacksAreParsed(parser) {
|
||||
if (!GLOBAL_OBJ._sentryModuleMetadata) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const stack of Object.keys(GLOBAL_OBJ._sentryModuleMetadata)) {
|
||||
const metadata = GLOBAL_OBJ._sentryModuleMetadata[stack];
|
||||
|
||||
if (parsedStacks.has(stack)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Ensure this stack doesn't get parsed again
|
||||
parsedStacks.add(stack);
|
||||
|
||||
const frames = parser(stack);
|
||||
|
||||
// Go through the frames starting from the top of the stack and find the first one with a filename
|
||||
for (const frame of frames.reverse()) {
|
||||
if (frame.filename) {
|
||||
// Save the metadata for this filename
|
||||
filenameMetadataMap.set(frame.filename, metadata);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve metadata for a specific JavaScript file URL.
|
||||
*
|
||||
* Metadata is injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
function getMetadataForUrl(parser, filename) {
|
||||
ensureMetadataStacksAreParsed(parser);
|
||||
return filenameMetadataMap.get(filename);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds metadata to stack frames.
|
||||
*
|
||||
* Metadata is injected by the Sentry bundler plugins using the `_experiments.moduleMetadata` config option.
|
||||
*/
|
||||
function addMetadataToStackFrames(parser, event) {
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
event.exception.values.forEach(exception => {
|
||||
if (!exception.stacktrace) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const frame of exception.stacktrace.frames || []) {
|
||||
if (!frame.filename) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const metadata = getMetadataForUrl(parser, frame.filename);
|
||||
|
||||
if (metadata) {
|
||||
frame.module_metadata = metadata;
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
// To save bundle size we're just try catching here instead of checking for the existence of all the different objects.
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Strips metadata from stack frames.
|
||||
*/
|
||||
function stripMetadataFromStackFrames(event) {
|
||||
try {
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
event.exception.values.forEach(exception => {
|
||||
if (!exception.stacktrace) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const frame of exception.stacktrace.frames || []) {
|
||||
delete frame.module_metadata;
|
||||
}
|
||||
});
|
||||
} catch (_) {
|
||||
// To save bundle size we're just try catching here instead of checking for the existence of all the different objects.
|
||||
}
|
||||
}
|
||||
|
||||
export { addMetadataToStackFrames, getMetadataForUrl, stripMetadataFromStackFrames };
|
||||
//# sourceMappingURL=metadata.js.map
|
||||
1
node_modules/@sentry/core/esm/metadata.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metadata.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
172
node_modules/@sentry/core/esm/metrics/aggregator.js
generated
vendored
Normal file
172
node_modules/@sentry/core/esm/metrics/aggregator.js
generated
vendored
Normal file
@@ -0,0 +1,172 @@
|
||||
import { timestampInSeconds } from '@sentry/utils';
|
||||
import { DEFAULT_FLUSH_INTERVAL, SET_METRIC_TYPE, MAX_WEIGHT } from './constants.js';
|
||||
import { METRIC_MAP } from './instance.js';
|
||||
import { updateMetricSummaryOnActiveSpan } from './metric-summary.js';
|
||||
import { sanitizeMetricKey, sanitizeTags, sanitizeUnit, getBucketKey } from './utils.js';
|
||||
|
||||
/**
|
||||
* A metrics aggregator that aggregates metrics in memory and flushes them periodically.
|
||||
*/
|
||||
class MetricsAggregator {
|
||||
// TODO(@anonrig): Use FinalizationRegistry to have a proper way of flushing the buckets
|
||||
// when the aggregator is garbage collected.
|
||||
// Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
|
||||
|
||||
// Different metrics have different weights. We use this to limit the number of metrics
|
||||
// that we store in memory.
|
||||
|
||||
// Cast to any so that it can use Node.js timeout
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
// SDKs are required to shift the flush interval by random() * rollup_in_seconds.
|
||||
// That shift is determined once per startup to create jittering.
|
||||
|
||||
// An SDK is required to perform force flushing ahead of scheduled time if the memory
|
||||
// pressure is too high. There is no rule for this other than that SDKs should be tracking
|
||||
// abstract aggregation complexity (eg: a counter only carries a single float, whereas a
|
||||
// distribution is a float per emission).
|
||||
//
|
||||
// Force flush is used on either shutdown, flush() or when we exceed the max weight.
|
||||
|
||||
constructor( _client) {this._client = _client;
|
||||
this._buckets = new Map();
|
||||
this._bucketsTotalWeight = 0;
|
||||
|
||||
this._interval = setInterval(() => this._flush(), DEFAULT_FLUSH_INTERVAL) ;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (this._interval.unref) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
this._interval.unref();
|
||||
}
|
||||
|
||||
this._flushShift = Math.floor((Math.random() * DEFAULT_FLUSH_INTERVAL) / 1000);
|
||||
this._forceFlush = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
add(
|
||||
metricType,
|
||||
unsanitizedName,
|
||||
value,
|
||||
unsanitizedUnit = 'none',
|
||||
unsanitizedTags = {},
|
||||
maybeFloatTimestamp = timestampInSeconds(),
|
||||
) {
|
||||
const timestamp = Math.floor(maybeFloatTimestamp);
|
||||
const name = sanitizeMetricKey(unsanitizedName);
|
||||
const tags = sanitizeTags(unsanitizedTags);
|
||||
const unit = sanitizeUnit(unsanitizedUnit );
|
||||
|
||||
const bucketKey = getBucketKey(metricType, name, unit, tags);
|
||||
|
||||
let bucketItem = this._buckets.get(bucketKey);
|
||||
// If this is a set metric, we need to calculate the delta from the previous weight.
|
||||
const previousWeight = bucketItem && metricType === SET_METRIC_TYPE ? bucketItem.metric.weight : 0;
|
||||
|
||||
if (bucketItem) {
|
||||
bucketItem.metric.add(value);
|
||||
// TODO(abhi): Do we need this check?
|
||||
if (bucketItem.timestamp < timestamp) {
|
||||
bucketItem.timestamp = timestamp;
|
||||
}
|
||||
} else {
|
||||
bucketItem = {
|
||||
// @ts-expect-error we don't need to narrow down the type of value here, saves bundle size.
|
||||
metric: new METRIC_MAP[metricType](value),
|
||||
timestamp,
|
||||
metricType,
|
||||
name,
|
||||
unit,
|
||||
tags,
|
||||
};
|
||||
this._buckets.set(bucketKey, bucketItem);
|
||||
}
|
||||
|
||||
// If value is a string, it's a set metric so calculate the delta from the previous weight.
|
||||
const val = typeof value === 'string' ? bucketItem.metric.weight - previousWeight : value;
|
||||
updateMetricSummaryOnActiveSpan(metricType, name, val, unit, unsanitizedTags, bucketKey);
|
||||
|
||||
// We need to keep track of the total weight of the buckets so that we can
|
||||
// flush them when we exceed the max weight.
|
||||
this._bucketsTotalWeight += bucketItem.metric.weight;
|
||||
|
||||
if (this._bucketsTotalWeight >= MAX_WEIGHT) {
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the current metrics to the transport via the transport.
|
||||
*/
|
||||
flush() {
|
||||
this._forceFlush = true;
|
||||
this._flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Shuts down metrics aggregator and clears all metrics.
|
||||
*/
|
||||
close() {
|
||||
this._forceFlush = true;
|
||||
clearInterval(this._interval);
|
||||
this._flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Flushes the buckets according to the internal state of the aggregator.
|
||||
* If it is a force flush, which happens on shutdown, it will flush all buckets.
|
||||
* Otherwise, it will only flush buckets that are older than the flush interval,
|
||||
* and according to the flush shift.
|
||||
*
|
||||
* This function mutates `_forceFlush` and `_bucketsTotalWeight` properties.
|
||||
*/
|
||||
_flush() {
|
||||
// TODO(@anonrig): Add Atomics for locking to avoid having force flush and regular flush
|
||||
// running at the same time.
|
||||
// Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Atomics
|
||||
|
||||
// This path eliminates the need for checking for timestamps since we're forcing a flush.
|
||||
// Remember to reset the flag, or it will always flush all metrics.
|
||||
if (this._forceFlush) {
|
||||
this._forceFlush = false;
|
||||
this._bucketsTotalWeight = 0;
|
||||
this._captureMetrics(this._buckets);
|
||||
this._buckets.clear();
|
||||
return;
|
||||
}
|
||||
const cutoffSeconds = Math.floor(timestampInSeconds()) - DEFAULT_FLUSH_INTERVAL / 1000 - this._flushShift;
|
||||
// TODO(@anonrig): Optimization opportunity.
|
||||
// Convert this map to an array and store key in the bucketItem.
|
||||
const flushedBuckets = new Map();
|
||||
for (const [key, bucket] of this._buckets) {
|
||||
if (bucket.timestamp <= cutoffSeconds) {
|
||||
flushedBuckets.set(key, bucket);
|
||||
this._bucketsTotalWeight -= bucket.metric.weight;
|
||||
}
|
||||
}
|
||||
|
||||
for (const [key] of flushedBuckets) {
|
||||
this._buckets.delete(key);
|
||||
}
|
||||
|
||||
this._captureMetrics(flushedBuckets);
|
||||
}
|
||||
|
||||
/**
|
||||
* Only captures a subset of the buckets passed to this function.
|
||||
* @param flushedBuckets
|
||||
*/
|
||||
_captureMetrics(flushedBuckets) {
|
||||
if (flushedBuckets.size > 0 && this._client.captureAggregateMetrics) {
|
||||
// TODO(@anonrig): Optimization opportunity.
|
||||
// This copy operation can be avoided if we store the key in the bucketItem.
|
||||
const buckets = Array.from(flushedBuckets).map(([, bucketItem]) => bucketItem);
|
||||
this._client.captureAggregateMetrics(buckets);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { MetricsAggregator };
|
||||
//# sourceMappingURL=aggregator.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/aggregator.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/aggregator.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
97
node_modules/@sentry/core/esm/metrics/browser-aggregator.js
generated
vendored
Normal file
97
node_modules/@sentry/core/esm/metrics/browser-aggregator.js
generated
vendored
Normal file
@@ -0,0 +1,97 @@
|
||||
import { timestampInSeconds } from '@sentry/utils';
|
||||
import { DEFAULT_BROWSER_FLUSH_INTERVAL, SET_METRIC_TYPE } from './constants.js';
|
||||
import { METRIC_MAP } from './instance.js';
|
||||
import { updateMetricSummaryOnActiveSpan } from './metric-summary.js';
|
||||
import { sanitizeMetricKey, sanitizeTags, sanitizeUnit, getBucketKey } from './utils.js';
|
||||
|
||||
/**
|
||||
* A simple metrics aggregator that aggregates metrics in memory and flushes them periodically.
|
||||
* Default flush interval is 5 seconds.
|
||||
*
|
||||
* @experimental This API is experimental and might change in the future.
|
||||
*/
|
||||
class BrowserMetricsAggregator {
|
||||
// TODO(@anonrig): Use FinalizationRegistry to have a proper way of flushing the buckets
|
||||
// when the aggregator is garbage collected.
|
||||
// Ref: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/FinalizationRegistry
|
||||
|
||||
constructor( _client) {this._client = _client;
|
||||
this._buckets = new Map();
|
||||
this._interval = setInterval(() => this.flush(), DEFAULT_BROWSER_FLUSH_INTERVAL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
add(
|
||||
metricType,
|
||||
unsanitizedName,
|
||||
value,
|
||||
unsanitizedUnit = 'none',
|
||||
unsanitizedTags = {},
|
||||
maybeFloatTimestamp = timestampInSeconds(),
|
||||
) {
|
||||
const timestamp = Math.floor(maybeFloatTimestamp);
|
||||
const name = sanitizeMetricKey(unsanitizedName);
|
||||
const tags = sanitizeTags(unsanitizedTags);
|
||||
const unit = sanitizeUnit(unsanitizedUnit );
|
||||
|
||||
const bucketKey = getBucketKey(metricType, name, unit, tags);
|
||||
|
||||
let bucketItem = this._buckets.get(bucketKey);
|
||||
// If this is a set metric, we need to calculate the delta from the previous weight.
|
||||
const previousWeight = bucketItem && metricType === SET_METRIC_TYPE ? bucketItem.metric.weight : 0;
|
||||
|
||||
if (bucketItem) {
|
||||
bucketItem.metric.add(value);
|
||||
// TODO(abhi): Do we need this check?
|
||||
if (bucketItem.timestamp < timestamp) {
|
||||
bucketItem.timestamp = timestamp;
|
||||
}
|
||||
} else {
|
||||
bucketItem = {
|
||||
// @ts-expect-error we don't need to narrow down the type of value here, saves bundle size.
|
||||
metric: new METRIC_MAP[metricType](value),
|
||||
timestamp,
|
||||
metricType,
|
||||
name,
|
||||
unit,
|
||||
tags,
|
||||
};
|
||||
this._buckets.set(bucketKey, bucketItem);
|
||||
}
|
||||
|
||||
// If value is a string, it's a set metric so calculate the delta from the previous weight.
|
||||
const val = typeof value === 'string' ? bucketItem.metric.weight - previousWeight : value;
|
||||
updateMetricSummaryOnActiveSpan(metricType, name, val, unit, unsanitizedTags, bucketKey);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
flush() {
|
||||
// short circuit if buckets are empty.
|
||||
if (this._buckets.size === 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._client.captureAggregateMetrics) {
|
||||
// TODO(@anonrig): Use Object.values() when we support ES6+
|
||||
const metricBuckets = Array.from(this._buckets).map(([, bucketItem]) => bucketItem);
|
||||
this._client.captureAggregateMetrics(metricBuckets);
|
||||
}
|
||||
|
||||
this._buckets.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
close() {
|
||||
clearInterval(this._interval);
|
||||
this.flush();
|
||||
}
|
||||
}
|
||||
|
||||
export { BrowserMetricsAggregator };
|
||||
//# sourceMappingURL=browser-aggregator.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/browser-aggregator.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/browser-aggregator.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
24
node_modules/@sentry/core/esm/metrics/constants.js
generated
vendored
Normal file
24
node_modules/@sentry/core/esm/metrics/constants.js
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
const COUNTER_METRIC_TYPE = 'c' ;
|
||||
const GAUGE_METRIC_TYPE = 'g' ;
|
||||
const SET_METRIC_TYPE = 's' ;
|
||||
const DISTRIBUTION_METRIC_TYPE = 'd' ;
|
||||
|
||||
/**
|
||||
* This does not match spec in https://develop.sentry.dev/sdk/metrics
|
||||
* but was chosen to optimize for the most common case in browser environments.
|
||||
*/
|
||||
const DEFAULT_BROWSER_FLUSH_INTERVAL = 5000;
|
||||
|
||||
/**
|
||||
* SDKs are required to bucket into 10 second intervals (rollup in seconds)
|
||||
* which is the current lower bound of metric accuracy.
|
||||
*/
|
||||
const DEFAULT_FLUSH_INTERVAL = 10000;
|
||||
|
||||
/**
|
||||
* The maximum number of metrics that should be stored in memory.
|
||||
*/
|
||||
const MAX_WEIGHT = 10000;
|
||||
|
||||
export { COUNTER_METRIC_TYPE, DEFAULT_BROWSER_FLUSH_INTERVAL, DEFAULT_FLUSH_INTERVAL, DISTRIBUTION_METRIC_TYPE, GAUGE_METRIC_TYPE, MAX_WEIGHT, SET_METRIC_TYPE };
|
||||
//# sourceMappingURL=constants.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/constants.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/constants.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"constants.js","sources":["../../../src/metrics/constants.ts"],"sourcesContent":["export const COUNTER_METRIC_TYPE = 'c' as const;\nexport const GAUGE_METRIC_TYPE = 'g' as const;\nexport const SET_METRIC_TYPE = 's' as const;\nexport const DISTRIBUTION_METRIC_TYPE = 'd' as const;\n\n/**\n * This does not match spec in https://develop.sentry.dev/sdk/metrics\n * but was chosen to optimize for the most common case in browser environments.\n */\nexport const DEFAULT_BROWSER_FLUSH_INTERVAL = 5000;\n\n/**\n * SDKs are required to bucket into 10 second intervals (rollup in seconds)\n * which is the current lower bound of metric accuracy.\n */\nexport const DEFAULT_FLUSH_INTERVAL = 10000;\n\n/**\n * The maximum number of metrics that should be stored in memory.\n */\nexport const MAX_WEIGHT = 10000;\n"],"names":[],"mappings":"AAAO,MAAM,mBAAoB,GAAE,GAAI,EAAA;AAChC,MAAM,iBAAkB,GAAE,GAAI,EAAA;AAC9B,MAAM,eAAgB,GAAE,GAAI,EAAA;AAC5B,MAAM,wBAAyB,GAAE,GAAI,EAAA;AAC5C;AACA;AACA;AACA;AACA;AACO,MAAM,8BAA+B,GAAE,KAAI;AAClD;AACA;AACA;AACA;AACA;AACO,MAAM,sBAAuB,GAAE,MAAK;AAC3C;AACA;AACA;AACA;AACO,MAAM,UAAW,GAAE;;;;"}
|
||||
42
node_modules/@sentry/core/esm/metrics/envelope.js
generated
vendored
Normal file
42
node_modules/@sentry/core/esm/metrics/envelope.js
generated
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
import { dsnToString, createEnvelope } from '@sentry/utils';
|
||||
import { serializeMetricBuckets } from './utils.js';
|
||||
|
||||
/**
|
||||
* Create envelope from a metric aggregate.
|
||||
*/
|
||||
function createMetricEnvelope(
|
||||
metricBucketItems,
|
||||
dsn,
|
||||
metadata,
|
||||
tunnel,
|
||||
) {
|
||||
const headers = {
|
||||
sent_at: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (metadata && metadata.sdk) {
|
||||
headers.sdk = {
|
||||
name: metadata.sdk.name,
|
||||
version: metadata.sdk.version,
|
||||
};
|
||||
}
|
||||
|
||||
if (!!tunnel && dsn) {
|
||||
headers.dsn = dsnToString(dsn);
|
||||
}
|
||||
|
||||
const item = createMetricEnvelopeItem(metricBucketItems);
|
||||
return createEnvelope(headers, [item]);
|
||||
}
|
||||
|
||||
function createMetricEnvelopeItem(metricBucketItems) {
|
||||
const payload = serializeMetricBuckets(metricBucketItems);
|
||||
const metricHeaders = {
|
||||
type: 'statsd',
|
||||
length: payload.length,
|
||||
};
|
||||
return [metricHeaders, payload];
|
||||
}
|
||||
|
||||
export { createMetricEnvelope };
|
||||
//# sourceMappingURL=envelope.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/envelope.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/envelope.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"envelope.js","sources":["../../../src/metrics/envelope.ts"],"sourcesContent":["import type { DsnComponents, MetricBucketItem, SdkMetadata, StatsdEnvelope, StatsdItem } from '@sentry/types';\nimport { createEnvelope, dsnToString } from '@sentry/utils';\nimport { serializeMetricBuckets } from './utils';\n\n/**\n * Create envelope from a metric aggregate.\n */\nexport function createMetricEnvelope(\n metricBucketItems: Array<MetricBucketItem>,\n dsn?: DsnComponents,\n metadata?: SdkMetadata,\n tunnel?: string,\n): StatsdEnvelope {\n const headers: StatsdEnvelope[0] = {\n sent_at: new Date().toISOString(),\n };\n\n if (metadata && metadata.sdk) {\n headers.sdk = {\n name: metadata.sdk.name,\n version: metadata.sdk.version,\n };\n }\n\n if (!!tunnel && dsn) {\n headers.dsn = dsnToString(dsn);\n }\n\n const item = createMetricEnvelopeItem(metricBucketItems);\n return createEnvelope<StatsdEnvelope>(headers, [item]);\n}\n\nfunction createMetricEnvelopeItem(metricBucketItems: MetricBucketItem[]): StatsdItem {\n const payload = serializeMetricBuckets(metricBucketItems);\n const metricHeaders: StatsdItem[0] = {\n type: 'statsd',\n length: payload.length,\n };\n return [metricHeaders, payload];\n}\n"],"names":[],"mappings":";;;AAIA;AACA;AACA;AACO,SAAS,oBAAoB;AACpC,EAAE,iBAAiB;AACnB,EAAE,GAAG;AACL,EAAE,QAAQ;AACV,EAAE,MAAM;AACR,EAAkB;AAClB,EAAE,MAAM,OAAO,GAAsB;AACrC,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACrC,GAAG,CAAA;AACH;AACA,EAAE,IAAI,QAAA,IAAY,QAAQ,CAAC,GAAG,EAAE;AAChC,IAAI,OAAO,CAAC,GAAA,GAAM;AAClB,MAAM,IAAI,EAAE,QAAQ,CAAC,GAAG,CAAC,IAAI;AAC7B,MAAM,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,OAAO;AACnC,KAAK,CAAA;AACL,GAAE;AACF;AACA,EAAE,IAAI,CAAC,CAAC,MAAO,IAAG,GAAG,EAAE;AACvB,IAAI,OAAO,CAAC,GAAA,GAAM,WAAW,CAAC,GAAG,CAAC,CAAA;AAClC,GAAE;AACF;AACA,EAAE,MAAM,IAAK,GAAE,wBAAwB,CAAC,iBAAiB,CAAC,CAAA;AAC1D,EAAE,OAAO,cAAc,CAAiB,OAAO,EAAE,CAAC,IAAI,CAAC,CAAC,CAAA;AACxD,CAAA;AACA;AACA,SAAS,wBAAwB,CAAC,iBAAiB,EAAkC;AACrF,EAAE,MAAM,OAAQ,GAAE,sBAAsB,CAAC,iBAAiB,CAAC,CAAA;AAC3D,EAAE,MAAM,aAAa,GAAkB;AACvC,IAAI,IAAI,EAAE,QAAQ;AAClB,IAAI,MAAM,EAAE,OAAO,CAAC,MAAM;AAC1B,GAAG,CAAA;AACH,EAAE,OAAO,CAAC,aAAa,EAAE,OAAO,CAAC,CAAA;AACjC;;;;"}
|
||||
90
node_modules/@sentry/core/esm/metrics/exports.js
generated
vendored
Normal file
90
node_modules/@sentry/core/esm/metrics/exports.js
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
import { logger } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { getClient, getCurrentScope } from '../exports.js';
|
||||
import { spanToJSON } from '../utils/spanUtils.js';
|
||||
import { COUNTER_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, SET_METRIC_TYPE, GAUGE_METRIC_TYPE } from './constants.js';
|
||||
import { MetricsAggregator, metricsAggregatorIntegration } from './integration.js';
|
||||
|
||||
function addToMetricsAggregator(
|
||||
metricType,
|
||||
name,
|
||||
value,
|
||||
data = {},
|
||||
) {
|
||||
const client = getClient();
|
||||
const scope = getCurrentScope();
|
||||
if (client) {
|
||||
if (!client.metricsAggregator) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn('No metrics aggregator enabled. Please add the MetricsAggregator integration to use metrics APIs');
|
||||
return;
|
||||
}
|
||||
const { unit, tags, timestamp } = data;
|
||||
const { release, environment } = client.getOptions();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const transaction = scope.getTransaction();
|
||||
const metricTags = {};
|
||||
if (release) {
|
||||
metricTags.release = release;
|
||||
}
|
||||
if (environment) {
|
||||
metricTags.environment = environment;
|
||||
}
|
||||
if (transaction) {
|
||||
metricTags.transaction = spanToJSON(transaction).description || '';
|
||||
}
|
||||
|
||||
DEBUG_BUILD && logger.log(`Adding value of ${value} to ${metricType} metric ${name}`);
|
||||
client.metricsAggregator.add(metricType, name, value, unit, { ...metricTags, ...tags }, timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to a counter metric
|
||||
*
|
||||
* @experimental This API is experimental and might have breaking changes in the future.
|
||||
*/
|
||||
function increment(name, value = 1, data) {
|
||||
addToMetricsAggregator(COUNTER_METRIC_TYPE, name, value, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to a distribution metric
|
||||
*
|
||||
* @experimental This API is experimental and might have breaking changes in the future.
|
||||
*/
|
||||
function distribution(name, value, data) {
|
||||
addToMetricsAggregator(DISTRIBUTION_METRIC_TYPE, name, value, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to a set metric. Value must be a string or integer.
|
||||
*
|
||||
* @experimental This API is experimental and might have breaking changes in the future.
|
||||
*/
|
||||
function set(name, value, data) {
|
||||
addToMetricsAggregator(SET_METRIC_TYPE, name, value, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a value to a gauge metric
|
||||
*
|
||||
* @experimental This API is experimental and might have breaking changes in the future.
|
||||
*/
|
||||
function gauge(name, value, data) {
|
||||
addToMetricsAggregator(GAUGE_METRIC_TYPE, name, value, data);
|
||||
}
|
||||
|
||||
const metrics = {
|
||||
increment,
|
||||
distribution,
|
||||
set,
|
||||
gauge,
|
||||
/** @deprecated Use `metrics.metricsAggregratorIntegration()` instead. */
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
MetricsAggregator,
|
||||
metricsAggregatorIntegration,
|
||||
};
|
||||
|
||||
export { distribution, gauge, increment, metrics, set };
|
||||
//# sourceMappingURL=exports.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/exports.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/exports.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
123
node_modules/@sentry/core/esm/metrics/instance.js
generated
vendored
Normal file
123
node_modules/@sentry/core/esm/metrics/instance.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
import { COUNTER_METRIC_TYPE, GAUGE_METRIC_TYPE, DISTRIBUTION_METRIC_TYPE, SET_METRIC_TYPE } from './constants.js';
|
||||
import { simpleHash } from './utils.js';
|
||||
|
||||
/**
|
||||
* A metric instance representing a counter.
|
||||
*/
|
||||
class CounterMetric {
|
||||
constructor( _value) {this._value = _value;}
|
||||
|
||||
/** @inheritDoc */
|
||||
get weight() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
add(value) {
|
||||
this._value += value;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
toString() {
|
||||
return `${this._value}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A metric instance representing a gauge.
|
||||
*/
|
||||
class GaugeMetric {
|
||||
|
||||
constructor(value) {
|
||||
this._last = value;
|
||||
this._min = value;
|
||||
this._max = value;
|
||||
this._sum = value;
|
||||
this._count = 1;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
get weight() {
|
||||
return 5;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
add(value) {
|
||||
this._last = value;
|
||||
if (value < this._min) {
|
||||
this._min = value;
|
||||
}
|
||||
if (value > this._max) {
|
||||
this._max = value;
|
||||
}
|
||||
this._sum += value;
|
||||
this._count++;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
toString() {
|
||||
return `${this._last}:${this._min}:${this._max}:${this._sum}:${this._count}`;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A metric instance representing a distribution.
|
||||
*/
|
||||
class DistributionMetric {
|
||||
|
||||
constructor(first) {
|
||||
this._value = [first];
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
get weight() {
|
||||
return this._value.length;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
add(value) {
|
||||
this._value.push(value);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
toString() {
|
||||
return this._value.join(':');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A metric instance representing a set.
|
||||
*/
|
||||
class SetMetric {
|
||||
|
||||
constructor( first) {this.first = first;
|
||||
this._value = new Set([first]);
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
get weight() {
|
||||
return this._value.size;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
add(value) {
|
||||
this._value.add(value);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
toString() {
|
||||
return Array.from(this._value)
|
||||
.map(val => (typeof val === 'string' ? simpleHash(val) : val))
|
||||
.join(':');
|
||||
}
|
||||
}
|
||||
|
||||
const METRIC_MAP = {
|
||||
[COUNTER_METRIC_TYPE]: CounterMetric,
|
||||
[GAUGE_METRIC_TYPE]: GaugeMetric,
|
||||
[DISTRIBUTION_METRIC_TYPE]: DistributionMetric,
|
||||
[SET_METRIC_TYPE]: SetMetric,
|
||||
};
|
||||
|
||||
export { CounterMetric, DistributionMetric, GaugeMetric, METRIC_MAP, SetMetric };
|
||||
//# sourceMappingURL=instance.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/instance.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/instance.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
32
node_modules/@sentry/core/esm/metrics/integration.js
generated
vendored
Normal file
32
node_modules/@sentry/core/esm/metrics/integration.js
generated
vendored
Normal file
@@ -0,0 +1,32 @@
|
||||
import { convertIntegrationFnToClass, defineIntegration } from '../integration.js';
|
||||
import { BrowserMetricsAggregator } from './browser-aggregator.js';
|
||||
|
||||
const INTEGRATION_NAME = 'MetricsAggregator';
|
||||
|
||||
const _metricsAggregatorIntegration = (() => {
|
||||
return {
|
||||
name: INTEGRATION_NAME,
|
||||
// TODO v8: Remove this
|
||||
setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function
|
||||
setup(client) {
|
||||
client.metricsAggregator = new BrowserMetricsAggregator(client);
|
||||
},
|
||||
};
|
||||
}) ;
|
||||
|
||||
const metricsAggregatorIntegration = defineIntegration(_metricsAggregatorIntegration);
|
||||
|
||||
/**
|
||||
* Enables Sentry metrics monitoring.
|
||||
*
|
||||
* @experimental This API is experimental and might having breaking changes in the future.
|
||||
* @deprecated Use `metricsAggegratorIntegration()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const MetricsAggregator = convertIntegrationFnToClass(
|
||||
INTEGRATION_NAME,
|
||||
metricsAggregatorIntegration,
|
||||
) ;
|
||||
|
||||
export { MetricsAggregator, metricsAggregatorIntegration };
|
||||
//# sourceMappingURL=integration.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/integration.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/integration.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"integration.js","sources":["../../../src/metrics/integration.ts"],"sourcesContent":["import type { Client, ClientOptions, Integration, IntegrationClass, IntegrationFn } from '@sentry/types';\nimport type { BaseClient } from '../baseclient';\nimport { convertIntegrationFnToClass, defineIntegration } from '../integration';\nimport { BrowserMetricsAggregator } from './browser-aggregator';\n\nconst INTEGRATION_NAME = 'MetricsAggregator';\n\nconst _metricsAggregatorIntegration = (() => {\n return {\n name: INTEGRATION_NAME,\n // TODO v8: Remove this\n setupOnce() {}, // eslint-disable-line @typescript-eslint/no-empty-function\n setup(client: BaseClient<ClientOptions>) {\n client.metricsAggregator = new BrowserMetricsAggregator(client);\n },\n };\n}) satisfies IntegrationFn;\n\nexport const metricsAggregatorIntegration = defineIntegration(_metricsAggregatorIntegration);\n\n/**\n * Enables Sentry metrics monitoring.\n *\n * @experimental This API is experimental and might having breaking changes in the future.\n * @deprecated Use `metricsAggegratorIntegration()` instead.\n */\n// eslint-disable-next-line deprecation/deprecation\nexport const MetricsAggregator = convertIntegrationFnToClass(\n INTEGRATION_NAME,\n metricsAggregatorIntegration,\n) as IntegrationClass<Integration & { setup: (client: Client) => void }>;\n"],"names":[],"mappings":";;;AAKA,MAAM,gBAAA,GAAmB,mBAAmB,CAAA;AAC5C;AACA,MAAM,6BAA8B,IAAG,MAAM;AAC7C,EAAE,OAAO;AACT,IAAI,IAAI,EAAE,gBAAgB;AAC1B;AACA,IAAI,SAAS,GAAG,EAAE;AAClB,IAAI,KAAK,CAAC,MAAM,EAA6B;AAC7C,MAAM,MAAM,CAAC,iBAAkB,GAAE,IAAI,wBAAwB,CAAC,MAAM,CAAC,CAAA;AACrE,KAAK;AACL,GAAG,CAAA;AACH,CAAC,CAAE,EAAA;AACH;MACa,4BAA6B,GAAE,iBAAiB,CAAC,6BAA6B,EAAC;AAC5F;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,iBAAkB,GAAE,2BAA2B;AAC5D,EAAE,gBAAgB;AAClB,EAAE,4BAA4B;AAC9B,CAAE;;;;"}
|
||||
92
node_modules/@sentry/core/esm/metrics/metric-summary.js
generated
vendored
Normal file
92
node_modules/@sentry/core/esm/metrics/metric-summary.js
generated
vendored
Normal file
@@ -0,0 +1,92 @@
|
||||
import { dropUndefinedKeys } from '@sentry/utils';
|
||||
import '../debug-build.js';
|
||||
import '../tracing/errors.js';
|
||||
import '../tracing/spanstatus.js';
|
||||
import { getActiveSpan } from '../tracing/trace.js';
|
||||
|
||||
/**
|
||||
* key: bucketKey
|
||||
* value: [exportKey, MetricSummary]
|
||||
*/
|
||||
|
||||
let SPAN_METRIC_SUMMARY;
|
||||
|
||||
function getMetricStorageForSpan(span) {
|
||||
return SPAN_METRIC_SUMMARY ? SPAN_METRIC_SUMMARY.get(span) : undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches the metric summary if it exists for the passed span
|
||||
*/
|
||||
function getMetricSummaryJsonForSpan(span) {
|
||||
const storage = getMetricStorageForSpan(span);
|
||||
|
||||
if (!storage) {
|
||||
return undefined;
|
||||
}
|
||||
const output = {};
|
||||
|
||||
for (const [, [exportKey, summary]] of storage) {
|
||||
if (!output[exportKey]) {
|
||||
output[exportKey] = [];
|
||||
}
|
||||
|
||||
output[exportKey].push(dropUndefinedKeys(summary));
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the metric summary on the currently active span
|
||||
*/
|
||||
function updateMetricSummaryOnActiveSpan(
|
||||
metricType,
|
||||
sanitizedName,
|
||||
value,
|
||||
unit,
|
||||
tags,
|
||||
bucketKey,
|
||||
) {
|
||||
const span = getActiveSpan();
|
||||
if (span) {
|
||||
const storage = getMetricStorageForSpan(span) || new Map();
|
||||
|
||||
const exportKey = `${metricType}:${sanitizedName}@${unit}`;
|
||||
const bucketItem = storage.get(bucketKey);
|
||||
|
||||
if (bucketItem) {
|
||||
const [, summary] = bucketItem;
|
||||
storage.set(bucketKey, [
|
||||
exportKey,
|
||||
{
|
||||
min: Math.min(summary.min, value),
|
||||
max: Math.max(summary.max, value),
|
||||
count: (summary.count += 1),
|
||||
sum: (summary.sum += value),
|
||||
tags: summary.tags,
|
||||
},
|
||||
]);
|
||||
} else {
|
||||
storage.set(bucketKey, [
|
||||
exportKey,
|
||||
{
|
||||
min: value,
|
||||
max: value,
|
||||
count: 1,
|
||||
sum: value,
|
||||
tags,
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
if (!SPAN_METRIC_SUMMARY) {
|
||||
SPAN_METRIC_SUMMARY = new WeakMap();
|
||||
}
|
||||
|
||||
SPAN_METRIC_SUMMARY.set(span, storage);
|
||||
}
|
||||
}
|
||||
|
||||
export { getMetricSummaryJsonForSpan, updateMetricSummaryOnActiveSpan };
|
||||
//# sourceMappingURL=metric-summary.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/metric-summary.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/metric-summary.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"metric-summary.js","sources":["../../../src/metrics/metric-summary.ts"],"sourcesContent":["import type { MeasurementUnit, Span } from '@sentry/types';\nimport type { MetricSummary } from '@sentry/types';\nimport type { Primitive } from '@sentry/types';\nimport { dropUndefinedKeys } from '@sentry/utils';\nimport { getActiveSpan } from '../tracing';\nimport type { MetricType } from './types';\n\n/**\n * key: bucketKey\n * value: [exportKey, MetricSummary]\n */\ntype MetricSummaryStorage = Map<string, [string, MetricSummary]>;\n\nlet SPAN_METRIC_SUMMARY: WeakMap<Span, MetricSummaryStorage> | undefined;\n\nfunction getMetricStorageForSpan(span: Span): MetricSummaryStorage | undefined {\n return SPAN_METRIC_SUMMARY ? SPAN_METRIC_SUMMARY.get(span) : undefined;\n}\n\n/**\n * Fetches the metric summary if it exists for the passed span\n */\nexport function getMetricSummaryJsonForSpan(span: Span): Record<string, Array<MetricSummary>> | undefined {\n const storage = getMetricStorageForSpan(span);\n\n if (!storage) {\n return undefined;\n }\n const output: Record<string, Array<MetricSummary>> = {};\n\n for (const [, [exportKey, summary]] of storage) {\n if (!output[exportKey]) {\n output[exportKey] = [];\n }\n\n output[exportKey].push(dropUndefinedKeys(summary));\n }\n\n return output;\n}\n\n/**\n * Updates the metric summary on the currently active span\n */\nexport function updateMetricSummaryOnActiveSpan(\n metricType: MetricType,\n sanitizedName: string,\n value: number,\n unit: MeasurementUnit,\n tags: Record<string, Primitive>,\n bucketKey: string,\n): void {\n const span = getActiveSpan();\n if (span) {\n const storage = getMetricStorageForSpan(span) || new Map<string, [string, MetricSummary]>();\n\n const exportKey = `${metricType}:${sanitizedName}@${unit}`;\n const bucketItem = storage.get(bucketKey);\n\n if (bucketItem) {\n const [, summary] = bucketItem;\n storage.set(bucketKey, [\n exportKey,\n {\n min: Math.min(summary.min, value),\n max: Math.max(summary.max, value),\n count: (summary.count += 1),\n sum: (summary.sum += value),\n tags: summary.tags,\n },\n ]);\n } else {\n storage.set(bucketKey, [\n exportKey,\n {\n min: value,\n max: value,\n count: 1,\n sum: value,\n tags,\n },\n ]);\n }\n\n if (!SPAN_METRIC_SUMMARY) {\n SPAN_METRIC_SUMMARY = new WeakMap();\n }\n\n SPAN_METRIC_SUMMARY.set(span, storage);\n }\n}\n"],"names":[],"mappings":";;;;;;AAOA;AACA;AACA;AACA;;AAGA,IAAI,mBAAmB,CAAA;AACvB;AACA,SAAS,uBAAuB,CAAC,IAAI,EAA0C;AAC/E,EAAE,OAAO,mBAAoB,GAAE,mBAAmB,CAAC,GAAG,CAAC,IAAI,CAAE,GAAE,SAAS,CAAA;AACxE,CAAA;AACA;AACA;AACA;AACA;AACO,SAAS,2BAA2B,CAAC,IAAI,EAA0D;AAC1G,EAAE,MAAM,OAAQ,GAAE,uBAAuB,CAAC,IAAI,CAAC,CAAA;AAC/C;AACA,EAAE,IAAI,CAAC,OAAO,EAAE;AAChB,IAAI,OAAO,SAAS,CAAA;AACpB,GAAE;AACF,EAAE,MAAM,MAAM,GAAyC,EAAE,CAAA;AACzD;AACA,EAAE,KAAK,MAAM,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAE,IAAG,OAAO,EAAE;AAClD,IAAI,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE;AAC5B,MAAM,MAAM,CAAC,SAAS,CAAE,GAAE,EAAE,CAAA;AAC5B,KAAI;AACJ;AACA,IAAI,MAAM,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAA;AACtD,GAAE;AACF;AACA,EAAE,OAAO,MAAM,CAAA;AACf,CAAA;AACA;AACA;AACA;AACA;AACO,SAAS,+BAA+B;AAC/C,EAAE,UAAU;AACZ,EAAE,aAAa;AACf,EAAE,KAAK;AACP,EAAE,IAAI;AACN,EAAE,IAAI;AACN,EAAE,SAAS;AACX,EAAQ;AACR,EAAE,MAAM,IAAA,GAAO,aAAa,EAAE,CAAA;AAC9B,EAAE,IAAI,IAAI,EAAE;AACZ,IAAI,MAAM,OAAQ,GAAE,uBAAuB,CAAC,IAAI,CAAA,IAAK,IAAI,GAAG,EAAmC,CAAA;AAC/F;AACA,IAAI,MAAM,SAAA,GAAY,CAAC,EAAA,UAAA,CAAA,CAAA,EAAA,aAAA,CAAA,CAAA,EAAA,IAAA,CAAA,CAAA,CAAA;AACA,IAAA,MAAA,UAAA,GAAA,OAAA,CAAA,GAAA,CAAA,SAAA,CAAA,CAAA;AACA;AACA,IAAA,IAAA,UAAA,EAAA;AACA,MAAA,MAAA,GAAA,OAAA,CAAA,GAAA,UAAA,CAAA;AACA,MAAA,OAAA,CAAA,GAAA,CAAA,SAAA,EAAA;AACA,QAAA,SAAA;AACA,QAAA;AACA,UAAA,GAAA,EAAA,IAAA,CAAA,GAAA,CAAA,OAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AACA,UAAA,GAAA,EAAA,IAAA,CAAA,GAAA,CAAA,OAAA,CAAA,GAAA,EAAA,KAAA,CAAA;AACA,UAAA,KAAA,GAAA,OAAA,CAAA,KAAA,IAAA,CAAA,CAAA;AACA,UAAA,GAAA,GAAA,OAAA,CAAA,GAAA,IAAA,KAAA,CAAA;AACA,UAAA,IAAA,EAAA,OAAA,CAAA,IAAA;AACA,SAAA;AACA,OAAA,CAAA,CAAA;AACA,KAAA,MAAA;AACA,MAAA,OAAA,CAAA,GAAA,CAAA,SAAA,EAAA;AACA,QAAA,SAAA;AACA,QAAA;AACA,UAAA,GAAA,EAAA,KAAA;AACA,UAAA,GAAA,EAAA,KAAA;AACA,UAAA,KAAA,EAAA,CAAA;AACA,UAAA,GAAA,EAAA,KAAA;AACA,UAAA,IAAA;AACA,SAAA;AACA,OAAA,CAAA,CAAA;AACA,KAAA;AACA;AACA,IAAA,IAAA,CAAA,mBAAA,EAAA;AACA,MAAA,mBAAA,GAAA,IAAA,OAAA,EAAA,CAAA;AACA,KAAA;AACA;AACA,IAAA,mBAAA,CAAA,GAAA,CAAA,IAAA,EAAA,OAAA,CAAA,CAAA;AACA,GAAA;AACA;;;;"}
|
||||
106
node_modules/@sentry/core/esm/metrics/utils.js
generated
vendored
Normal file
106
node_modules/@sentry/core/esm/metrics/utils.js
generated
vendored
Normal file
@@ -0,0 +1,106 @@
|
||||
import { dropUndefinedKeys } from '@sentry/utils';
|
||||
|
||||
/**
|
||||
* Generate bucket key from metric properties.
|
||||
*/
|
||||
function getBucketKey(
|
||||
metricType,
|
||||
name,
|
||||
unit,
|
||||
tags,
|
||||
) {
|
||||
const stringifiedTags = Object.entries(dropUndefinedKeys(tags)).sort((a, b) => a[0].localeCompare(b[0]));
|
||||
return `${metricType}${name}${unit}${stringifiedTags}`;
|
||||
}
|
||||
|
||||
/* eslint-disable no-bitwise */
|
||||
/**
|
||||
* Simple hash function for strings.
|
||||
*/
|
||||
function simpleHash(s) {
|
||||
let rv = 0;
|
||||
for (let i = 0; i < s.length; i++) {
|
||||
const c = s.charCodeAt(i);
|
||||
rv = (rv << 5) - rv + c;
|
||||
rv &= rv;
|
||||
}
|
||||
return rv >>> 0;
|
||||
}
|
||||
/* eslint-enable no-bitwise */
|
||||
|
||||
/**
|
||||
* Serialize metrics buckets into a string based on statsd format.
|
||||
*
|
||||
* Example of format:
|
||||
* metric.name@second:1:1.2|d|#a:value,b:anothervalue|T12345677
|
||||
* Segments:
|
||||
* name: metric.name
|
||||
* unit: second
|
||||
* value: [1, 1.2]
|
||||
* type of metric: d (distribution)
|
||||
* tags: { a: value, b: anothervalue }
|
||||
* timestamp: 12345677
|
||||
*/
|
||||
function serializeMetricBuckets(metricBucketItems) {
|
||||
let out = '';
|
||||
for (const item of metricBucketItems) {
|
||||
const tagEntries = Object.entries(item.tags);
|
||||
const maybeTags = tagEntries.length > 0 ? `|#${tagEntries.map(([key, value]) => `${key}:${value}`).join(',')}` : '';
|
||||
out += `${item.name}@${item.unit}:${item.metric}|${item.metricType}${maybeTags}|T${item.timestamp}\n`;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/** Sanitizes units */
|
||||
function sanitizeUnit(unit) {
|
||||
return unit.replace(/[^\w]+/gi, '_');
|
||||
}
|
||||
|
||||
/** Sanitizes metric keys */
|
||||
function sanitizeMetricKey(key) {
|
||||
return key.replace(/[^\w\-.]+/gi, '_');
|
||||
}
|
||||
|
||||
function sanitizeTagKey(key) {
|
||||
return key.replace(/[^\w\-./]+/gi, '');
|
||||
}
|
||||
|
||||
const tagValueReplacements = [
|
||||
['\n', '\\n'],
|
||||
['\r', '\\r'],
|
||||
['\t', '\\t'],
|
||||
['\\', '\\\\'],
|
||||
['|', '\\u{7c}'],
|
||||
[',', '\\u{2c}'],
|
||||
];
|
||||
|
||||
function getCharOrReplacement(input) {
|
||||
for (const [search, replacement] of tagValueReplacements) {
|
||||
if (input === search) {
|
||||
return replacement;
|
||||
}
|
||||
}
|
||||
|
||||
return input;
|
||||
}
|
||||
|
||||
function sanitizeTagValue(value) {
|
||||
return [...value].reduce((acc, char) => acc + getCharOrReplacement(char), '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Sanitizes tags.
|
||||
*/
|
||||
function sanitizeTags(unsanitizedTags) {
|
||||
const tags = {};
|
||||
for (const key in unsanitizedTags) {
|
||||
if (Object.prototype.hasOwnProperty.call(unsanitizedTags, key)) {
|
||||
const sanitizedKey = sanitizeTagKey(key);
|
||||
tags[sanitizedKey] = sanitizeTagValue(String(unsanitizedTags[key]));
|
||||
}
|
||||
}
|
||||
return tags;
|
||||
}
|
||||
|
||||
export { getBucketKey, sanitizeMetricKey, sanitizeTags, sanitizeUnit, serializeMetricBuckets, simpleHash };
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@sentry/core/esm/metrics/utils.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/metrics/utils.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
686
node_modules/@sentry/core/esm/scope.js
generated
vendored
Normal file
686
node_modules/@sentry/core/esm/scope.js
generated
vendored
Normal file
@@ -0,0 +1,686 @@
|
||||
import { isPlainObject, dateTimestampInSeconds, uuid4, logger } from '@sentry/utils';
|
||||
import { getGlobalEventProcessors, notifyEventProcessors } from './eventProcessors.js';
|
||||
import { updateSession } from './session.js';
|
||||
import { applyScopeDataToEvent } from './utils/applyScopeDataToEvent.js';
|
||||
|
||||
/**
|
||||
* Default value for maximum number of breadcrumbs added to an event.
|
||||
*/
|
||||
const DEFAULT_MAX_BREADCRUMBS = 100;
|
||||
|
||||
/**
|
||||
* The global scope is kept in this module.
|
||||
* When accessing this via `getGlobalScope()` we'll make sure to set one if none is currently present.
|
||||
*/
|
||||
let globalScope;
|
||||
|
||||
/**
|
||||
* Holds additional event information. {@link Scope.applyToEvent} will be
|
||||
* called by the client before an event will be sent.
|
||||
*/
|
||||
class Scope {
|
||||
/** Flag if notifying is happening. */
|
||||
|
||||
/** Callback for client to receive scope changes. */
|
||||
|
||||
/** Callback list that will be called after {@link applyToEvent}. */
|
||||
|
||||
/** Array of breadcrumbs. */
|
||||
|
||||
/** User */
|
||||
|
||||
/** Tags */
|
||||
|
||||
/** Extra */
|
||||
|
||||
/** Contexts */
|
||||
|
||||
/** Attachments */
|
||||
|
||||
/** Propagation Context for distributed tracing */
|
||||
|
||||
/**
|
||||
* A place to stash data which is needed at some point in the SDK's event processing pipeline but which shouldn't get
|
||||
* sent to Sentry
|
||||
*/
|
||||
|
||||
/** Fingerprint */
|
||||
|
||||
/** Severity */
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
|
||||
/**
|
||||
* Transaction Name
|
||||
*/
|
||||
|
||||
/** Span */
|
||||
|
||||
/** Session */
|
||||
|
||||
/** Request Mode Session Status */
|
||||
|
||||
/** The client on this scope */
|
||||
|
||||
// NOTE: Any field which gets added here should get added not only to the constructor but also to the `clone` method.
|
||||
|
||||
constructor() {
|
||||
this._notifyingListeners = false;
|
||||
this._scopeListeners = [];
|
||||
this._eventProcessors = [];
|
||||
this._breadcrumbs = [];
|
||||
this._attachments = [];
|
||||
this._user = {};
|
||||
this._tags = {};
|
||||
this._extra = {};
|
||||
this._contexts = {};
|
||||
this._sdkProcessingMetadata = {};
|
||||
this._propagationContext = generatePropagationContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit values from the parent scope.
|
||||
* @deprecated Use `scope.clone()` and `new Scope()` instead.
|
||||
*/
|
||||
static clone(scope) {
|
||||
return scope ? scope.clone() : new Scope();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clone this scope instance.
|
||||
*/
|
||||
clone() {
|
||||
const newScope = new Scope();
|
||||
newScope._breadcrumbs = [...this._breadcrumbs];
|
||||
newScope._tags = { ...this._tags };
|
||||
newScope._extra = { ...this._extra };
|
||||
newScope._contexts = { ...this._contexts };
|
||||
newScope._user = this._user;
|
||||
newScope._level = this._level;
|
||||
newScope._span = this._span;
|
||||
newScope._session = this._session;
|
||||
newScope._transactionName = this._transactionName;
|
||||
newScope._fingerprint = this._fingerprint;
|
||||
newScope._eventProcessors = [...this._eventProcessors];
|
||||
newScope._requestSession = this._requestSession;
|
||||
newScope._attachments = [...this._attachments];
|
||||
newScope._sdkProcessingMetadata = { ...this._sdkProcessingMetadata };
|
||||
newScope._propagationContext = { ...this._propagationContext };
|
||||
newScope._client = this._client;
|
||||
|
||||
return newScope;
|
||||
}
|
||||
|
||||
/** Update the client on the scope. */
|
||||
setClient(client) {
|
||||
this._client = client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the client assigned to this scope.
|
||||
*
|
||||
* It is generally recommended to use the global function `Sentry.getClient()` instead, unless you know what you are doing.
|
||||
*/
|
||||
getClient() {
|
||||
return this._client;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add internal on change listener. Used for sub SDKs that need to store the scope.
|
||||
* @hidden
|
||||
*/
|
||||
addScopeListener(callback) {
|
||||
this._scopeListeners.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
addEventProcessor(callback) {
|
||||
this._eventProcessors.push(callback);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setUser(user) {
|
||||
// If null is passed we want to unset everything, but still define keys,
|
||||
// so that later down in the pipeline any existing values are cleared.
|
||||
this._user = user || {
|
||||
email: undefined,
|
||||
id: undefined,
|
||||
ip_address: undefined,
|
||||
segment: undefined,
|
||||
username: undefined,
|
||||
};
|
||||
|
||||
if (this._session) {
|
||||
updateSession(this._session, { user });
|
||||
}
|
||||
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getUser() {
|
||||
return this._user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getRequestSession() {
|
||||
return this._requestSession;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setRequestSession(requestSession) {
|
||||
this._requestSession = requestSession;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setTags(tags) {
|
||||
this._tags = {
|
||||
...this._tags,
|
||||
...tags,
|
||||
};
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setTag(key, value) {
|
||||
this._tags = { ...this._tags, [key]: value };
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setExtras(extras) {
|
||||
this._extra = {
|
||||
...this._extra,
|
||||
...extras,
|
||||
};
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setExtra(key, extra) {
|
||||
this._extra = { ...this._extra, [key]: extra };
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setFingerprint(fingerprint) {
|
||||
this._fingerprint = fingerprint;
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setLevel(
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
level,
|
||||
) {
|
||||
this._level = level;
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the transaction name on the scope for future events.
|
||||
*/
|
||||
setTransactionName(name) {
|
||||
this._transactionName = name;
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setContext(key, context) {
|
||||
if (context === null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete this._contexts[key];
|
||||
} else {
|
||||
this._contexts[key] = context;
|
||||
}
|
||||
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Span on the scope.
|
||||
* @param span Span
|
||||
* @deprecated Instead of setting a span on a scope, use `startSpan()`/`startSpanManual()` instead.
|
||||
*/
|
||||
setSpan(span) {
|
||||
this._span = span;
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `Span` if there is one.
|
||||
* @deprecated Use `getActiveSpan()` instead.
|
||||
*/
|
||||
getSpan() {
|
||||
return this._span;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the `Transaction` attached to the scope (if there is one).
|
||||
* @deprecated You should not rely on the transaction, but just use `startSpan()` APIs instead.
|
||||
*/
|
||||
getTransaction() {
|
||||
// Often, this span (if it exists at all) will be a transaction, but it's not guaranteed to be. Regardless, it will
|
||||
// have a pointer to the currently-active transaction.
|
||||
const span = this._span;
|
||||
// Cannot replace with getRootSpan because getRootSpan returns a span, not a transaction
|
||||
// Also, this method will be removed anyway.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return span && span.transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setSession(session) {
|
||||
if (!session) {
|
||||
delete this._session;
|
||||
} else {
|
||||
this._session = session;
|
||||
}
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getSession() {
|
||||
return this._session;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
update(captureContext) {
|
||||
if (!captureContext) {
|
||||
return this;
|
||||
}
|
||||
|
||||
const scopeToMerge = typeof captureContext === 'function' ? captureContext(this) : captureContext;
|
||||
|
||||
if (scopeToMerge instanceof Scope) {
|
||||
const scopeData = scopeToMerge.getScopeData();
|
||||
|
||||
this._tags = { ...this._tags, ...scopeData.tags };
|
||||
this._extra = { ...this._extra, ...scopeData.extra };
|
||||
this._contexts = { ...this._contexts, ...scopeData.contexts };
|
||||
if (scopeData.user && Object.keys(scopeData.user).length) {
|
||||
this._user = scopeData.user;
|
||||
}
|
||||
if (scopeData.level) {
|
||||
this._level = scopeData.level;
|
||||
}
|
||||
if (scopeData.fingerprint.length) {
|
||||
this._fingerprint = scopeData.fingerprint;
|
||||
}
|
||||
if (scopeToMerge.getRequestSession()) {
|
||||
this._requestSession = scopeToMerge.getRequestSession();
|
||||
}
|
||||
if (scopeData.propagationContext) {
|
||||
this._propagationContext = scopeData.propagationContext;
|
||||
}
|
||||
} else if (isPlainObject(scopeToMerge)) {
|
||||
const scopeContext = captureContext ;
|
||||
this._tags = { ...this._tags, ...scopeContext.tags };
|
||||
this._extra = { ...this._extra, ...scopeContext.extra };
|
||||
this._contexts = { ...this._contexts, ...scopeContext.contexts };
|
||||
if (scopeContext.user) {
|
||||
this._user = scopeContext.user;
|
||||
}
|
||||
if (scopeContext.level) {
|
||||
this._level = scopeContext.level;
|
||||
}
|
||||
if (scopeContext.fingerprint) {
|
||||
this._fingerprint = scopeContext.fingerprint;
|
||||
}
|
||||
if (scopeContext.requestSession) {
|
||||
this._requestSession = scopeContext.requestSession;
|
||||
}
|
||||
if (scopeContext.propagationContext) {
|
||||
this._propagationContext = scopeContext.propagationContext;
|
||||
}
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
clear() {
|
||||
this._breadcrumbs = [];
|
||||
this._tags = {};
|
||||
this._extra = {};
|
||||
this._user = {};
|
||||
this._contexts = {};
|
||||
this._level = undefined;
|
||||
this._transactionName = undefined;
|
||||
this._fingerprint = undefined;
|
||||
this._requestSession = undefined;
|
||||
this._span = undefined;
|
||||
this._session = undefined;
|
||||
this._notifyScopeListeners();
|
||||
this._attachments = [];
|
||||
this._propagationContext = generatePropagationContext();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
addBreadcrumb(breadcrumb, maxBreadcrumbs) {
|
||||
const maxCrumbs = typeof maxBreadcrumbs === 'number' ? maxBreadcrumbs : DEFAULT_MAX_BREADCRUMBS;
|
||||
|
||||
// No data has been changed, so don't notify scope listeners
|
||||
if (maxCrumbs <= 0) {
|
||||
return this;
|
||||
}
|
||||
|
||||
const mergedBreadcrumb = {
|
||||
timestamp: dateTimestampInSeconds(),
|
||||
...breadcrumb,
|
||||
};
|
||||
|
||||
const breadcrumbs = this._breadcrumbs;
|
||||
breadcrumbs.push(mergedBreadcrumb);
|
||||
this._breadcrumbs = breadcrumbs.length > maxCrumbs ? breadcrumbs.slice(-maxCrumbs) : breadcrumbs;
|
||||
|
||||
this._notifyScopeListeners();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getLastBreadcrumb() {
|
||||
return this._breadcrumbs[this._breadcrumbs.length - 1];
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
clearBreadcrumbs() {
|
||||
this._breadcrumbs = [];
|
||||
this._notifyScopeListeners();
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
addAttachment(attachment) {
|
||||
this._attachments.push(attachment);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use `getScopeData()` instead.
|
||||
*/
|
||||
getAttachments() {
|
||||
const data = this.getScopeData();
|
||||
|
||||
return data.attachments;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
clearAttachments() {
|
||||
this._attachments = [];
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @inheritDoc */
|
||||
getScopeData() {
|
||||
const {
|
||||
_breadcrumbs,
|
||||
_attachments,
|
||||
_contexts,
|
||||
_tags,
|
||||
_extra,
|
||||
_user,
|
||||
_level,
|
||||
_fingerprint,
|
||||
_eventProcessors,
|
||||
_propagationContext,
|
||||
_sdkProcessingMetadata,
|
||||
_transactionName,
|
||||
_span,
|
||||
} = this;
|
||||
|
||||
return {
|
||||
breadcrumbs: _breadcrumbs,
|
||||
attachments: _attachments,
|
||||
contexts: _contexts,
|
||||
tags: _tags,
|
||||
extra: _extra,
|
||||
user: _user,
|
||||
level: _level,
|
||||
fingerprint: _fingerprint || [],
|
||||
eventProcessors: _eventProcessors,
|
||||
propagationContext: _propagationContext,
|
||||
sdkProcessingMetadata: _sdkProcessingMetadata,
|
||||
transactionName: _transactionName,
|
||||
span: _span,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies data from the scope to the event and runs all event processors on it.
|
||||
*
|
||||
* @param event Event
|
||||
* @param hint Object containing additional information about the original exception, for use by the event processors.
|
||||
* @hidden
|
||||
* @deprecated Use `applyScopeDataToEvent()` directly
|
||||
*/
|
||||
applyToEvent(
|
||||
event,
|
||||
hint = {},
|
||||
additionalEventProcessors = [],
|
||||
) {
|
||||
applyScopeDataToEvent(event, this.getScopeData());
|
||||
|
||||
// TODO (v8): Update this order to be: Global > Client > Scope
|
||||
const eventProcessors = [
|
||||
...additionalEventProcessors,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
...getGlobalEventProcessors(),
|
||||
...this._eventProcessors,
|
||||
];
|
||||
|
||||
return notifyEventProcessors(eventProcessors, event, hint);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add data which will be accessible during event processing but won't get sent to Sentry
|
||||
*/
|
||||
setSDKProcessingMetadata(newData) {
|
||||
this._sdkProcessingMetadata = { ...this._sdkProcessingMetadata, ...newData };
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setPropagationContext(context) {
|
||||
this._propagationContext = context;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
getPropagationContext() {
|
||||
return this._propagationContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture an exception for this scope.
|
||||
*
|
||||
* @param exception The exception to capture.
|
||||
* @param hint Optinal additional data to attach to the Sentry event.
|
||||
* @returns the id of the captured Sentry event.
|
||||
*/
|
||||
captureException(exception, hint) {
|
||||
const eventId = hint && hint.event_id ? hint.event_id : uuid4();
|
||||
|
||||
if (!this._client) {
|
||||
logger.warn('No client configured on scope - will not capture exception!');
|
||||
return eventId;
|
||||
}
|
||||
|
||||
const syntheticException = new Error('Sentry syntheticException');
|
||||
|
||||
this._client.captureException(
|
||||
exception,
|
||||
{
|
||||
originalException: exception,
|
||||
syntheticException,
|
||||
...hint,
|
||||
event_id: eventId,
|
||||
},
|
||||
this,
|
||||
);
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Capture a message for this scope.
|
||||
*
|
||||
* @param message The message to capture.
|
||||
* @param level An optional severity level to report the message with.
|
||||
* @param hint Optional additional data to attach to the Sentry event.
|
||||
* @returns the id of the captured message.
|
||||
*/
|
||||
captureMessage(message, level, hint) {
|
||||
const eventId = hint && hint.event_id ? hint.event_id : uuid4();
|
||||
|
||||
if (!this._client) {
|
||||
logger.warn('No client configured on scope - will not capture message!');
|
||||
return eventId;
|
||||
}
|
||||
|
||||
const syntheticException = new Error(message);
|
||||
|
||||
this._client.captureMessage(
|
||||
message,
|
||||
level,
|
||||
{
|
||||
originalException: message,
|
||||
syntheticException,
|
||||
...hint,
|
||||
event_id: eventId,
|
||||
},
|
||||
this,
|
||||
);
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Captures a manually created event for this scope and sends it to Sentry.
|
||||
*
|
||||
* @param exception The event to capture.
|
||||
* @param hint Optional additional data to attach to the Sentry event.
|
||||
* @returns the id of the captured event.
|
||||
*/
|
||||
captureEvent(event, hint) {
|
||||
const eventId = hint && hint.event_id ? hint.event_id : uuid4();
|
||||
|
||||
if (!this._client) {
|
||||
logger.warn('No client configured on scope - will not capture event!');
|
||||
return eventId;
|
||||
}
|
||||
|
||||
this._client.captureEvent(event, { ...hint, event_id: eventId }, this);
|
||||
|
||||
return eventId;
|
||||
}
|
||||
|
||||
/**
|
||||
* This will be called on every set call.
|
||||
*/
|
||||
_notifyScopeListeners() {
|
||||
// We need this check for this._notifyingListeners to be able to work on scope during updates
|
||||
// If this check is not here we'll produce endless recursion when something is done with the scope
|
||||
// during the callback.
|
||||
if (!this._notifyingListeners) {
|
||||
this._notifyingListeners = true;
|
||||
this._scopeListeners.forEach(callback => {
|
||||
callback(this);
|
||||
});
|
||||
this._notifyingListeners = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the global scope.
|
||||
* This scope is applied to _all_ events.
|
||||
*/
|
||||
function getGlobalScope() {
|
||||
if (!globalScope) {
|
||||
globalScope = new Scope();
|
||||
}
|
||||
|
||||
return globalScope;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is mainly needed for tests.
|
||||
* DO NOT USE this, as this is an internal API and subject to change.
|
||||
* @hidden
|
||||
*/
|
||||
function setGlobalScope(scope) {
|
||||
globalScope = scope;
|
||||
}
|
||||
|
||||
function generatePropagationContext() {
|
||||
return {
|
||||
traceId: uuid4(),
|
||||
spanId: uuid4().substring(16),
|
||||
};
|
||||
}
|
||||
|
||||
export { Scope, getGlobalScope, setGlobalScope };
|
||||
//# sourceMappingURL=scope.js.map
|
||||
1
node_modules/@sentry/core/esm/scope.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/scope.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
66
node_modules/@sentry/core/esm/sdk.js
generated
vendored
Normal file
66
node_modules/@sentry/core/esm/sdk.js
generated
vendored
Normal file
@@ -0,0 +1,66 @@
|
||||
import { logger, consoleSandbox } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
import { getCurrentScope } from './exports.js';
|
||||
import { getCurrentHub } from './hub.js';
|
||||
|
||||
/** A class object that can instantiate Client objects. */
|
||||
|
||||
/**
|
||||
* Internal function to create a new SDK client instance. The client is
|
||||
* installed and then bound to the current scope.
|
||||
*
|
||||
* @param clientClass The client class to instantiate.
|
||||
* @param options Options to pass to the client.
|
||||
*/
|
||||
function initAndBind(
|
||||
clientClass,
|
||||
options,
|
||||
) {
|
||||
if (options.debug === true) {
|
||||
if (DEBUG_BUILD) {
|
||||
logger.enable();
|
||||
} else {
|
||||
// use `console.warn` rather than `logger.warn` since by non-debug bundles have all `logger.x` statements stripped
|
||||
consoleSandbox(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');
|
||||
});
|
||||
}
|
||||
}
|
||||
const scope = getCurrentScope();
|
||||
scope.update(options.initialScope);
|
||||
|
||||
const client = new clientClass(options);
|
||||
setCurrentClient(client);
|
||||
initializeClient(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Make the given client the current client.
|
||||
*/
|
||||
function setCurrentClient(client) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = getCurrentHub();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const top = hub.getStackTop();
|
||||
top.client = client;
|
||||
top.scope.setClient(client);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the client for the current scope.
|
||||
* Make sure to call this after `setCurrentClient()`.
|
||||
*/
|
||||
function initializeClient(client) {
|
||||
if (client.init) {
|
||||
client.init();
|
||||
// TODO v8: Remove this fallback
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
} else if (client.setupIntegrations) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
client.setupIntegrations();
|
||||
}
|
||||
}
|
||||
|
||||
export { initAndBind, setCurrentClient };
|
||||
//# sourceMappingURL=sdk.js.map
|
||||
1
node_modules/@sentry/core/esm/sdk.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/sdk.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"sdk.js","sources":["../../src/sdk.ts"],"sourcesContent":["import type { Client, ClientOptions } from '@sentry/types';\nimport { consoleSandbox, logger } from '@sentry/utils';\n\nimport { DEBUG_BUILD } from './debug-build';\nimport { getCurrentScope } from './exports';\nimport { getCurrentHub } from './hub';\n\n/** A class object that can instantiate Client objects. */\nexport type ClientClass<F extends Client, O extends ClientOptions> = new (options: O) => F;\n\n/**\n * Internal function to create a new SDK client instance. The client is\n * installed and then bound to the current scope.\n *\n * @param clientClass The client class to instantiate.\n * @param options Options to pass to the client.\n */\nexport function initAndBind<F extends Client, O extends ClientOptions>(\n clientClass: ClientClass<F, O>,\n options: O,\n): void {\n if (options.debug === true) {\n if (DEBUG_BUILD) {\n logger.enable();\n } else {\n // use `console.warn` rather than `logger.warn` since by non-debug bundles have all `logger.x` statements stripped\n consoleSandbox(() => {\n // eslint-disable-next-line no-console\n console.warn('[Sentry] Cannot initialize SDK with `debug` option using a non-debug bundle.');\n });\n }\n }\n const scope = getCurrentScope();\n scope.update(options.initialScope);\n\n const client = new clientClass(options);\n setCurrentClient(client);\n initializeClient(client);\n}\n\n/**\n * Make the given client the current client.\n */\nexport function setCurrentClient(client: Client): void {\n // eslint-disable-next-line deprecation/deprecation\n const hub = getCurrentHub();\n // eslint-disable-next-line deprecation/deprecation\n const top = hub.getStackTop();\n top.client = client;\n top.scope.setClient(client);\n}\n\n/**\n * Initialize the client for the current scope.\n * Make sure to call this after `setCurrentClient()`.\n */\nfunction initializeClient(client: Client): void {\n if (client.init) {\n client.init();\n // TODO v8: Remove this fallback\n // eslint-disable-next-line deprecation/deprecation\n } else if (client.setupIntegrations) {\n // eslint-disable-next-line deprecation/deprecation\n client.setupIntegrations();\n }\n}\n"],"names":[],"mappings":";;;;;AAOA;;AAGA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW;AAC3B,EAAE,WAAW;AACb,EAAE,OAAO;AACT,EAAQ;AACR,EAAE,IAAI,OAAO,CAAC,KAAM,KAAI,IAAI,EAAE;AAC9B,IAAI,IAAI,WAAW,EAAE;AACrB,MAAM,MAAM,CAAC,MAAM,EAAE,CAAA;AACrB,WAAW;AACX;AACA,MAAM,cAAc,CAAC,MAAM;AAC3B;AACA,QAAQ,OAAO,CAAC,IAAI,CAAC,8EAA8E,CAAC,CAAA;AACpG,OAAO,CAAC,CAAA;AACR,KAAI;AACJ,GAAE;AACF,EAAE,MAAM,KAAA,GAAQ,eAAe,EAAE,CAAA;AACjC,EAAE,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;AACpC;AACA,EAAE,MAAM,MAAO,GAAE,IAAI,WAAW,CAAC,OAAO,CAAC,CAAA;AACzC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;AAC1B,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAA;AAC1B,CAAA;AACA;AACA;AACA;AACA;AACO,SAAS,gBAAgB,CAAC,MAAM,EAAgB;AACvD;AACA,EAAE,MAAM,GAAA,GAAM,aAAa,EAAE,CAAA;AAC7B;AACA,EAAE,MAAM,GAAI,GAAE,GAAG,CAAC,WAAW,EAAE,CAAA;AAC/B,EAAE,GAAG,CAAC,MAAO,GAAE,MAAM,CAAA;AACrB,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;AAC7B,CAAA;AACA;AACA;AACA;AACA;AACA;AACA,SAAS,gBAAgB,CAAC,MAAM,EAAgB;AAChD,EAAE,IAAI,MAAM,CAAC,IAAI,EAAE;AACnB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAA;AACjB;AACA;AACA,SAAS,IAAI,MAAM,CAAC,iBAAiB,EAAE;AACvC;AACA,IAAI,MAAM,CAAC,iBAAiB,EAAE,CAAA;AAC9B,GAAE;AACF;;;;"}
|
||||
29
node_modules/@sentry/core/esm/semanticAttributes.js
generated
vendored
Normal file
29
node_modules/@sentry/core/esm/semanticAttributes.js
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
/**
|
||||
* Use this attribute to represent the source of a span.
|
||||
* Should be one of: custom, url, route, view, component, task, unknown
|
||||
*
|
||||
*/
|
||||
const SEMANTIC_ATTRIBUTE_SENTRY_SOURCE = 'sentry.source';
|
||||
|
||||
/**
|
||||
* Use this attribute to represent the sample rate used for a span.
|
||||
*/
|
||||
const SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE = 'sentry.sample_rate';
|
||||
|
||||
/**
|
||||
* Use this attribute to represent the operation of a span.
|
||||
*/
|
||||
const SEMANTIC_ATTRIBUTE_SENTRY_OP = 'sentry.op';
|
||||
|
||||
/**
|
||||
* Use this attribute to represent the origin of a span.
|
||||
*/
|
||||
const SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = 'sentry.origin';
|
||||
|
||||
/**
|
||||
* The id of the profile that this span occured in.
|
||||
*/
|
||||
const SEMANTIC_ATTRIBUTE_PROFILE_ID = 'profile_id';
|
||||
|
||||
export { SEMANTIC_ATTRIBUTE_PROFILE_ID, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, SEMANTIC_ATTRIBUTE_SENTRY_SOURCE };
|
||||
//# sourceMappingURL=semanticAttributes.js.map
|
||||
1
node_modules/@sentry/core/esm/semanticAttributes.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/semanticAttributes.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"semanticAttributes.js","sources":["../../src/semanticAttributes.ts"],"sourcesContent":["/**\n * Use this attribute to represent the source of a span.\n * Should be one of: custom, url, route, view, component, task, unknown\n *\n */\nexport const SEMANTIC_ATTRIBUTE_SENTRY_SOURCE = 'sentry.source';\n\n/**\n * Use this attribute to represent the sample rate used for a span.\n */\nexport const SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE = 'sentry.sample_rate';\n\n/**\n * Use this attribute to represent the operation of a span.\n */\nexport const SEMANTIC_ATTRIBUTE_SENTRY_OP = 'sentry.op';\n\n/**\n * Use this attribute to represent the origin of a span.\n */\nexport const SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN = 'sentry.origin';\n\n/**\n * The id of the profile that this span occured in.\n */\nexport const SEMANTIC_ATTRIBUTE_PROFILE_ID = 'profile_id';\n"],"names":[],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACO,MAAM,gCAAiC,GAAE,gBAAe;AAC/D;AACA;AACA;AACA;AACO,MAAM,qCAAsC,GAAE,qBAAoB;AACzE;AACA;AACA;AACA;AACO,MAAM,4BAA6B,GAAE,YAAW;AACvD;AACA;AACA;AACA;AACO,MAAM,gCAAiC,GAAE,gBAAe;AAC/D;AACA;AACA;AACA;AACO,MAAM,6BAA8B,GAAE;;;;"}
|
||||
260
node_modules/@sentry/core/esm/server-runtime-client.js
generated
vendored
Normal file
260
node_modules/@sentry/core/esm/server-runtime-client.js
generated
vendored
Normal file
@@ -0,0 +1,260 @@
|
||||
import { resolvedSyncPromise, eventFromUnknownInput, eventFromMessage, logger, uuid4 } from '@sentry/utils';
|
||||
import { BaseClient } from './baseclient.js';
|
||||
import { createCheckInEnvelope } from './checkin.js';
|
||||
import { DEBUG_BUILD } from './debug-build.js';
|
||||
import { getClient } from './exports.js';
|
||||
import { MetricsAggregator } from './metrics/aggregator.js';
|
||||
import { SessionFlusher } from './sessionflusher.js';
|
||||
import { addTracingExtensions } from './tracing/hubextensions.js';
|
||||
import { spanToTraceContext } from './utils/spanUtils.js';
|
||||
import { getRootSpan } from './utils/getRootSpan.js';
|
||||
import './tracing/spanstatus.js';
|
||||
import { getDynamicSamplingContextFromSpan, getDynamicSamplingContextFromClient } from './tracing/dynamicSamplingContext.js';
|
||||
|
||||
/**
|
||||
* The Sentry Server Runtime Client SDK.
|
||||
*/
|
||||
class ServerRuntimeClient
|
||||
|
||||
extends BaseClient {
|
||||
|
||||
/**
|
||||
* Creates a new Edge SDK instance.
|
||||
* @param options Configuration options for this SDK.
|
||||
*/
|
||||
constructor(options) {
|
||||
// Server clients always support tracing
|
||||
addTracingExtensions();
|
||||
|
||||
super(options);
|
||||
|
||||
if (options._experiments && options._experiments['metricsAggregator']) {
|
||||
this.metricsAggregator = new MetricsAggregator(this);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
eventFromException(exception, hint) {
|
||||
return resolvedSyncPromise(eventFromUnknownInput(getClient(), this._options.stackParser, exception, hint));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
eventFromMessage(
|
||||
message,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
level = 'info',
|
||||
hint,
|
||||
) {
|
||||
return resolvedSyncPromise(
|
||||
eventFromMessage(this._options.stackParser, message, level, hint, this._options.attachStacktrace),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
|
||||
captureException(exception, hint, scope) {
|
||||
// Check if the flag `autoSessionTracking` is enabled, and if `_sessionFlusher` exists because it is initialised only
|
||||
// when the `requestHandler` middleware is used, and hence the expectation is to have SessionAggregates payload
|
||||
// sent to the Server only when the `requestHandler` middleware is used
|
||||
if (this._options.autoSessionTracking && this._sessionFlusher && scope) {
|
||||
const requestSession = scope.getRequestSession();
|
||||
|
||||
// Necessary checks to ensure this is code block is executed only within a request
|
||||
// Should override the status only if `requestSession.status` is `Ok`, which is its initial stage
|
||||
if (requestSession && requestSession.status === 'ok') {
|
||||
requestSession.status = 'errored';
|
||||
}
|
||||
}
|
||||
|
||||
return super.captureException(exception, hint, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
captureEvent(event, hint, scope) {
|
||||
// Check if the flag `autoSessionTracking` is enabled, and if `_sessionFlusher` exists because it is initialised only
|
||||
// when the `requestHandler` middleware is used, and hence the expectation is to have SessionAggregates payload
|
||||
// sent to the Server only when the `requestHandler` middleware is used
|
||||
if (this._options.autoSessionTracking && this._sessionFlusher && scope) {
|
||||
const eventType = event.type || 'exception';
|
||||
const isException =
|
||||
eventType === 'exception' && event.exception && event.exception.values && event.exception.values.length > 0;
|
||||
|
||||
// If the event is of type Exception, then a request session should be captured
|
||||
if (isException) {
|
||||
const requestSession = scope.getRequestSession();
|
||||
|
||||
// Ensure that this is happening within the bounds of a request, and make sure not to override
|
||||
// Session Status if Errored / Crashed
|
||||
if (requestSession && requestSession.status === 'ok') {
|
||||
requestSession.status = 'errored';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return super.captureEvent(event, hint, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @inheritdoc
|
||||
*/
|
||||
close(timeout) {
|
||||
if (this._sessionFlusher) {
|
||||
this._sessionFlusher.close();
|
||||
}
|
||||
return super.close(timeout);
|
||||
}
|
||||
|
||||
/** Method that initialises an instance of SessionFlusher on Client */
|
||||
initSessionFlusher() {
|
||||
const { release, environment } = this._options;
|
||||
if (!release) {
|
||||
DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!');
|
||||
} else {
|
||||
this._sessionFlusher = new SessionFlusher(this, {
|
||||
release,
|
||||
environment,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a cron monitor check in and send it to Sentry.
|
||||
*
|
||||
* @param checkIn An object that describes a check in.
|
||||
* @param upsertMonitorConfig An optional object that describes a monitor config. Use this if you want
|
||||
* to create a monitor automatically when sending a check in.
|
||||
*/
|
||||
captureCheckIn(checkIn, monitorConfig, scope) {
|
||||
const id = 'checkInId' in checkIn && checkIn.checkInId ? checkIn.checkInId : uuid4();
|
||||
if (!this._isEnabled()) {
|
||||
DEBUG_BUILD && logger.warn('SDK not enabled, will not capture checkin.');
|
||||
return id;
|
||||
}
|
||||
|
||||
const options = this.getOptions();
|
||||
const { release, environment, tunnel } = options;
|
||||
|
||||
const serializedCheckIn = {
|
||||
check_in_id: id,
|
||||
monitor_slug: checkIn.monitorSlug,
|
||||
status: checkIn.status,
|
||||
release,
|
||||
environment,
|
||||
};
|
||||
|
||||
if ('duration' in checkIn) {
|
||||
serializedCheckIn.duration = checkIn.duration;
|
||||
}
|
||||
|
||||
if (monitorConfig) {
|
||||
serializedCheckIn.monitor_config = {
|
||||
schedule: monitorConfig.schedule,
|
||||
checkin_margin: monitorConfig.checkinMargin,
|
||||
max_runtime: monitorConfig.maxRuntime,
|
||||
timezone: monitorConfig.timezone,
|
||||
};
|
||||
}
|
||||
|
||||
const [dynamicSamplingContext, traceContext] = this._getTraceInfoFromScope(scope);
|
||||
if (traceContext) {
|
||||
serializedCheckIn.contexts = {
|
||||
trace: traceContext,
|
||||
};
|
||||
}
|
||||
|
||||
const envelope = createCheckInEnvelope(
|
||||
serializedCheckIn,
|
||||
dynamicSamplingContext,
|
||||
this.getSdkMetadata(),
|
||||
tunnel,
|
||||
this.getDsn(),
|
||||
);
|
||||
|
||||
DEBUG_BUILD && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status);
|
||||
|
||||
// _sendEnvelope should not throw
|
||||
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
||||
this._sendEnvelope(envelope);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Method responsible for capturing/ending a request session by calling `incrementSessionStatusCount` to increment
|
||||
* appropriate session aggregates bucket
|
||||
*/
|
||||
_captureRequestSession() {
|
||||
if (!this._sessionFlusher) {
|
||||
DEBUG_BUILD && logger.warn('Discarded request mode session because autoSessionTracking option was disabled');
|
||||
} else {
|
||||
this._sessionFlusher.incrementSessionStatusCount();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
_prepareEvent(
|
||||
event,
|
||||
hint,
|
||||
scope,
|
||||
isolationScope,
|
||||
) {
|
||||
if (this._options.platform) {
|
||||
event.platform = event.platform || this._options.platform;
|
||||
}
|
||||
|
||||
if (this._options.runtime) {
|
||||
event.contexts = {
|
||||
...event.contexts,
|
||||
runtime: (event.contexts || {}).runtime || this._options.runtime,
|
||||
};
|
||||
}
|
||||
|
||||
if (this._options.serverName) {
|
||||
event.server_name = event.server_name || this._options.serverName;
|
||||
}
|
||||
|
||||
return super._prepareEvent(event, hint, scope, isolationScope);
|
||||
}
|
||||
|
||||
/** Extract trace information from scope */
|
||||
_getTraceInfoFromScope(
|
||||
scope,
|
||||
) {
|
||||
if (!scope) {
|
||||
return [undefined, undefined];
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const span = scope.getSpan();
|
||||
if (span) {
|
||||
const samplingContext = getRootSpan(span) ? getDynamicSamplingContextFromSpan(span) : undefined;
|
||||
return [samplingContext, spanToTraceContext(span)];
|
||||
}
|
||||
|
||||
const { traceId, spanId, parentSpanId, dsc } = scope.getPropagationContext();
|
||||
const traceContext = {
|
||||
trace_id: traceId,
|
||||
span_id: spanId,
|
||||
parent_span_id: parentSpanId,
|
||||
};
|
||||
if (dsc) {
|
||||
return [dsc, traceContext];
|
||||
}
|
||||
|
||||
return [getDynamicSamplingContextFromClient(traceId, this, scope), traceContext];
|
||||
}
|
||||
}
|
||||
|
||||
export { ServerRuntimeClient };
|
||||
//# sourceMappingURL=server-runtime-client.js.map
|
||||
1
node_modules/@sentry/core/esm/server-runtime-client.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/server-runtime-client.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
160
node_modules/@sentry/core/esm/session.js
generated
vendored
Normal file
160
node_modules/@sentry/core/esm/session.js
generated
vendored
Normal file
@@ -0,0 +1,160 @@
|
||||
import { timestampInSeconds, uuid4, dropUndefinedKeys } from '@sentry/utils';
|
||||
|
||||
/**
|
||||
* Creates a new `Session` object by setting certain default parameters. If optional @param context
|
||||
* is passed, the passed properties are applied to the session object.
|
||||
*
|
||||
* @param context (optional) additional properties to be applied to the returned session object
|
||||
*
|
||||
* @returns a new `Session` object
|
||||
*/
|
||||
function makeSession(context) {
|
||||
// Both timestamp and started are in seconds since the UNIX epoch.
|
||||
const startingTime = timestampInSeconds();
|
||||
|
||||
const session = {
|
||||
sid: uuid4(),
|
||||
init: true,
|
||||
timestamp: startingTime,
|
||||
started: startingTime,
|
||||
duration: 0,
|
||||
status: 'ok',
|
||||
errors: 0,
|
||||
ignoreDuration: false,
|
||||
toJSON: () => sessionToJSON(session),
|
||||
};
|
||||
|
||||
if (context) {
|
||||
updateSession(session, context);
|
||||
}
|
||||
|
||||
return session;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates a session object with the properties passed in the context.
|
||||
*
|
||||
* Note that this function mutates the passed object and returns void.
|
||||
* (Had to do this instead of returning a new and updated session because closing and sending a session
|
||||
* makes an update to the session after it was passed to the sending logic.
|
||||
* @see BaseClient.captureSession )
|
||||
*
|
||||
* @param session the `Session` to update
|
||||
* @param context the `SessionContext` holding the properties that should be updated in @param session
|
||||
*/
|
||||
// eslint-disable-next-line complexity
|
||||
function updateSession(session, context = {}) {
|
||||
if (context.user) {
|
||||
if (!session.ipAddress && context.user.ip_address) {
|
||||
session.ipAddress = context.user.ip_address;
|
||||
}
|
||||
|
||||
if (!session.did && !context.did) {
|
||||
session.did = context.user.id || context.user.email || context.user.username;
|
||||
}
|
||||
}
|
||||
|
||||
session.timestamp = context.timestamp || timestampInSeconds();
|
||||
|
||||
if (context.abnormal_mechanism) {
|
||||
session.abnormal_mechanism = context.abnormal_mechanism;
|
||||
}
|
||||
|
||||
if (context.ignoreDuration) {
|
||||
session.ignoreDuration = context.ignoreDuration;
|
||||
}
|
||||
if (context.sid) {
|
||||
// Good enough uuid validation. — Kamil
|
||||
session.sid = context.sid.length === 32 ? context.sid : uuid4();
|
||||
}
|
||||
if (context.init !== undefined) {
|
||||
session.init = context.init;
|
||||
}
|
||||
if (!session.did && context.did) {
|
||||
session.did = `${context.did}`;
|
||||
}
|
||||
if (typeof context.started === 'number') {
|
||||
session.started = context.started;
|
||||
}
|
||||
if (session.ignoreDuration) {
|
||||
session.duration = undefined;
|
||||
} else if (typeof context.duration === 'number') {
|
||||
session.duration = context.duration;
|
||||
} else {
|
||||
const duration = session.timestamp - session.started;
|
||||
session.duration = duration >= 0 ? duration : 0;
|
||||
}
|
||||
if (context.release) {
|
||||
session.release = context.release;
|
||||
}
|
||||
if (context.environment) {
|
||||
session.environment = context.environment;
|
||||
}
|
||||
if (!session.ipAddress && context.ipAddress) {
|
||||
session.ipAddress = context.ipAddress;
|
||||
}
|
||||
if (!session.userAgent && context.userAgent) {
|
||||
session.userAgent = context.userAgent;
|
||||
}
|
||||
if (typeof context.errors === 'number') {
|
||||
session.errors = context.errors;
|
||||
}
|
||||
if (context.status) {
|
||||
session.status = context.status;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes a session by setting its status and updating the session object with it.
|
||||
* Internally calls `updateSession` to update the passed session object.
|
||||
*
|
||||
* Note that this function mutates the passed session (@see updateSession for explanation).
|
||||
*
|
||||
* @param session the `Session` object to be closed
|
||||
* @param status the `SessionStatus` with which the session was closed. If you don't pass a status,
|
||||
* this function will keep the previously set status, unless it was `'ok'` in which case
|
||||
* it is changed to `'exited'`.
|
||||
*/
|
||||
function closeSession(session, status) {
|
||||
let context = {};
|
||||
if (status) {
|
||||
context = { status };
|
||||
} else if (session.status === 'ok') {
|
||||
context = { status: 'exited' };
|
||||
}
|
||||
|
||||
updateSession(session, context);
|
||||
}
|
||||
|
||||
/**
|
||||
* Serializes a passed session object to a JSON object with a slightly different structure.
|
||||
* This is necessary because the Sentry backend requires a slightly different schema of a session
|
||||
* than the one the JS SDKs use internally.
|
||||
*
|
||||
* @param session the session to be converted
|
||||
*
|
||||
* @returns a JSON object of the passed session
|
||||
*/
|
||||
function sessionToJSON(session) {
|
||||
return dropUndefinedKeys({
|
||||
sid: `${session.sid}`,
|
||||
init: session.init,
|
||||
// Make sure that sec is converted to ms for date constructor
|
||||
started: new Date(session.started * 1000).toISOString(),
|
||||
timestamp: new Date(session.timestamp * 1000).toISOString(),
|
||||
status: session.status,
|
||||
errors: session.errors,
|
||||
did: typeof session.did === 'number' || typeof session.did === 'string' ? `${session.did}` : undefined,
|
||||
duration: session.duration,
|
||||
abnormal_mechanism: session.abnormal_mechanism,
|
||||
attrs: {
|
||||
release: session.release,
|
||||
environment: session.environment,
|
||||
ip_address: session.ipAddress,
|
||||
user_agent: session.userAgent,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
export { closeSession, makeSession, updateSession };
|
||||
//# sourceMappingURL=session.js.map
|
||||
1
node_modules/@sentry/core/esm/session.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/session.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
110
node_modules/@sentry/core/esm/sessionflusher.js
generated
vendored
Normal file
110
node_modules/@sentry/core/esm/sessionflusher.js
generated
vendored
Normal file
@@ -0,0 +1,110 @@
|
||||
import { dropUndefinedKeys } from '@sentry/utils';
|
||||
import { getCurrentScope } from './exports.js';
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*/
|
||||
class SessionFlusher {
|
||||
|
||||
// Cast to any so that it can use Node.js timeout
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
constructor(client, attrs) {
|
||||
this._client = client;
|
||||
this.flushTimeout = 60;
|
||||
this._pendingAggregates = {};
|
||||
this._isEnabled = true;
|
||||
|
||||
// Call to setInterval, so that flush is called every 60 seconds.
|
||||
this._intervalId = setInterval(() => this.flush(), this.flushTimeout * 1000);
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
if (this._intervalId.unref) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
|
||||
this._intervalId.unref();
|
||||
}
|
||||
this._sessionAttrs = attrs;
|
||||
}
|
||||
|
||||
/** Checks if `pendingAggregates` has entries, and if it does flushes them by calling `sendSession` */
|
||||
flush() {
|
||||
const sessionAggregates = this.getSessionAggregates();
|
||||
if (sessionAggregates.aggregates.length === 0) {
|
||||
return;
|
||||
}
|
||||
this._pendingAggregates = {};
|
||||
this._client.sendSession(sessionAggregates);
|
||||
}
|
||||
|
||||
/** Massages the entries in `pendingAggregates` and returns aggregated sessions */
|
||||
getSessionAggregates() {
|
||||
const aggregates = Object.keys(this._pendingAggregates).map((key) => {
|
||||
return this._pendingAggregates[parseInt(key)];
|
||||
});
|
||||
|
||||
const sessionAggregates = {
|
||||
attrs: this._sessionAttrs,
|
||||
aggregates,
|
||||
};
|
||||
return dropUndefinedKeys(sessionAggregates);
|
||||
}
|
||||
|
||||
/** JSDoc */
|
||||
close() {
|
||||
clearInterval(this._intervalId);
|
||||
this._isEnabled = false;
|
||||
this.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrapper function for _incrementSessionStatusCount that checks if the instance of SessionFlusher is enabled then
|
||||
* fetches the session status of the request from `Scope.getRequestSession().status` on the scope and passes them to
|
||||
* `_incrementSessionStatusCount` along with the start date
|
||||
*/
|
||||
incrementSessionStatusCount() {
|
||||
if (!this._isEnabled) {
|
||||
return;
|
||||
}
|
||||
const scope = getCurrentScope();
|
||||
const requestSession = scope.getRequestSession();
|
||||
|
||||
if (requestSession && requestSession.status) {
|
||||
this._incrementSessionStatusCount(requestSession.status, new Date());
|
||||
// This is not entirely necessarily but is added as a safe guard to indicate the bounds of a request and so in
|
||||
// case captureRequestSession is called more than once to prevent double count
|
||||
scope.setRequestSession(undefined);
|
||||
/* eslint-enable @typescript-eslint/no-unsafe-member-access */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Increments status bucket in pendingAggregates buffer (internal state) corresponding to status of
|
||||
* the session received
|
||||
*/
|
||||
_incrementSessionStatusCount(status, date) {
|
||||
// Truncate minutes and seconds on Session Started attribute to have one minute bucket keys
|
||||
const sessionStartedTrunc = new Date(date).setSeconds(0, 0);
|
||||
this._pendingAggregates[sessionStartedTrunc] = this._pendingAggregates[sessionStartedTrunc] || {};
|
||||
|
||||
// corresponds to aggregated sessions in one specific minute bucket
|
||||
// for example, {"started":"2021-03-16T08:00:00.000Z","exited":4, "errored": 1}
|
||||
const aggregationCounts = this._pendingAggregates[sessionStartedTrunc];
|
||||
if (!aggregationCounts.started) {
|
||||
aggregationCounts.started = new Date(sessionStartedTrunc).toISOString();
|
||||
}
|
||||
|
||||
switch (status) {
|
||||
case 'errored':
|
||||
aggregationCounts.errored = (aggregationCounts.errored || 0) + 1;
|
||||
return aggregationCounts.errored;
|
||||
case 'ok':
|
||||
aggregationCounts.exited = (aggregationCounts.exited || 0) + 1;
|
||||
return aggregationCounts.exited;
|
||||
default:
|
||||
aggregationCounts.crashed = (aggregationCounts.crashed || 0) + 1;
|
||||
return aggregationCounts.crashed;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { SessionFlusher };
|
||||
//# sourceMappingURL=sessionflusher.js.map
|
||||
1
node_modules/@sentry/core/esm/sessionflusher.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/sessionflusher.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
27
node_modules/@sentry/core/esm/span.js
generated
vendored
Normal file
27
node_modules/@sentry/core/esm/span.js
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
import { dsnToString, createEnvelope } from '@sentry/utils';
|
||||
|
||||
/**
|
||||
* Create envelope from Span item.
|
||||
*/
|
||||
function createSpanEnvelope(spans, dsn) {
|
||||
const headers = {
|
||||
sent_at: new Date().toISOString(),
|
||||
};
|
||||
|
||||
if (dsn) {
|
||||
headers.dsn = dsnToString(dsn);
|
||||
}
|
||||
|
||||
const items = spans.map(createSpanItem);
|
||||
return createEnvelope(headers, items);
|
||||
}
|
||||
|
||||
function createSpanItem(span) {
|
||||
const spanHeaders = {
|
||||
type: 'span',
|
||||
};
|
||||
return [spanHeaders, span];
|
||||
}
|
||||
|
||||
export { createSpanEnvelope };
|
||||
//# sourceMappingURL=span.js.map
|
||||
1
node_modules/@sentry/core/esm/span.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/span.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"span.js","sources":["../../src/span.ts"],"sourcesContent":["import type { DsnComponents, SpanEnvelope, SpanItem } from '@sentry/types';\nimport type { Span } from '@sentry/types';\nimport { createEnvelope, dsnToString } from '@sentry/utils';\n\n/**\n * Create envelope from Span item.\n */\nexport function createSpanEnvelope(spans: Span[], dsn?: DsnComponents): SpanEnvelope {\n const headers: SpanEnvelope[0] = {\n sent_at: new Date().toISOString(),\n };\n\n if (dsn) {\n headers.dsn = dsnToString(dsn);\n }\n\n const items = spans.map(createSpanItem);\n return createEnvelope<SpanEnvelope>(headers, items);\n}\n\nfunction createSpanItem(span: Span): SpanItem {\n const spanHeaders: SpanItem[0] = {\n type: 'span',\n };\n return [spanHeaders, span];\n}\n"],"names":[],"mappings":";;AAIA;AACA;AACA;AACO,SAAS,kBAAkB,CAAC,KAAK,EAAU,GAAG,EAAgC;AACrF,EAAE,MAAM,OAAO,GAAoB;AACnC,IAAI,OAAO,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;AACrC,GAAG,CAAA;AACH;AACA,EAAE,IAAI,GAAG,EAAE;AACX,IAAI,OAAO,CAAC,GAAA,GAAM,WAAW,CAAC,GAAG,CAAC,CAAA;AAClC,GAAE;AACF;AACA,EAAE,MAAM,QAAQ,KAAK,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;AACzC,EAAE,OAAO,cAAc,CAAe,OAAO,EAAE,KAAK,CAAC,CAAA;AACrD,CAAA;AACA;AACA,SAAS,cAAc,CAAC,IAAI,EAAkB;AAC9C,EAAE,MAAM,WAAW,GAAgB;AACnC,IAAI,IAAI,EAAE,MAAM;AAChB,GAAG,CAAA;AACH,EAAE,OAAO,CAAC,WAAW,EAAE,IAAI,CAAC,CAAA;AAC5B;;;;"}
|
||||
95
node_modules/@sentry/core/esm/tracing/dynamicSamplingContext.js
generated
vendored
Normal file
95
node_modules/@sentry/core/esm/tracing/dynamicSamplingContext.js
generated
vendored
Normal file
@@ -0,0 +1,95 @@
|
||||
import { dropUndefinedKeys } from '@sentry/utils';
|
||||
import { DEFAULT_ENVIRONMENT } from '../constants.js';
|
||||
import { getClient, getCurrentScope } from '../exports.js';
|
||||
import { getRootSpan } from '../utils/getRootSpan.js';
|
||||
import { spanToJSON, spanIsSampled } from '../utils/spanUtils.js';
|
||||
|
||||
/**
|
||||
* Creates a dynamic sampling context from a client.
|
||||
*
|
||||
* Dispatches the `createDsc` lifecycle hook as a side effect.
|
||||
*/
|
||||
function getDynamicSamplingContextFromClient(
|
||||
trace_id,
|
||||
client,
|
||||
scope,
|
||||
) {
|
||||
const options = client.getOptions();
|
||||
|
||||
const { publicKey: public_key } = client.getDsn() || {};
|
||||
// TODO(v8): Remove segment from User
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { segment: user_segment } = (scope && scope.getUser()) || {};
|
||||
|
||||
const dsc = dropUndefinedKeys({
|
||||
environment: options.environment || DEFAULT_ENVIRONMENT,
|
||||
release: options.release,
|
||||
user_segment,
|
||||
public_key,
|
||||
trace_id,
|
||||
}) ;
|
||||
|
||||
client.emit && client.emit('createDsc', dsc);
|
||||
|
||||
return dsc;
|
||||
}
|
||||
|
||||
/**
|
||||
* A Span with a frozen dynamic sampling context.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Creates a dynamic sampling context from a span (and client and scope)
|
||||
*
|
||||
* @param span the span from which a few values like the root span name and sample rate are extracted.
|
||||
*
|
||||
* @returns a dynamic sampling context
|
||||
*/
|
||||
function getDynamicSamplingContextFromSpan(span) {
|
||||
const client = getClient();
|
||||
if (!client) {
|
||||
return {};
|
||||
}
|
||||
|
||||
// passing emit=false here to only emit later once the DSC is actually populated
|
||||
const dsc = getDynamicSamplingContextFromClient(spanToJSON(span).trace_id || '', client, getCurrentScope());
|
||||
|
||||
// TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
|
||||
const txn = getRootSpan(span) ;
|
||||
if (!txn) {
|
||||
return dsc;
|
||||
}
|
||||
|
||||
// TODO (v8): Remove v7FrozenDsc as a Transaction will no longer have _frozenDynamicSamplingContext
|
||||
// For now we need to avoid breaking users who directly created a txn with a DSC, where this field is still set.
|
||||
// @see Transaction class constructor
|
||||
const v7FrozenDsc = txn && txn._frozenDynamicSamplingContext;
|
||||
if (v7FrozenDsc) {
|
||||
return v7FrozenDsc;
|
||||
}
|
||||
|
||||
// TODO (v8): Replace txn.metadata with txn.attributes[]
|
||||
// We can't do this yet because attributes aren't always set yet.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { sampleRate: maybeSampleRate, source } = txn.metadata;
|
||||
if (maybeSampleRate != null) {
|
||||
dsc.sample_rate = `${maybeSampleRate}`;
|
||||
}
|
||||
|
||||
// We don't want to have a transaction name in the DSC if the source is "url" because URLs might contain PII
|
||||
const jsonSpan = spanToJSON(txn);
|
||||
|
||||
// after JSON conversion, txn.name becomes jsonSpan.description
|
||||
if (source && source !== 'url') {
|
||||
dsc.transaction = jsonSpan.description;
|
||||
}
|
||||
|
||||
dsc.sampled = String(spanIsSampled(txn));
|
||||
|
||||
client.emit && client.emit('createDsc', dsc);
|
||||
|
||||
return dsc;
|
||||
}
|
||||
|
||||
export { getDynamicSamplingContextFromClient, getDynamicSamplingContextFromSpan };
|
||||
//# sourceMappingURL=dynamicSamplingContext.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/dynamicSamplingContext.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/dynamicSamplingContext.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
38
node_modules/@sentry/core/esm/tracing/errors.js
generated
vendored
Normal file
38
node_modules/@sentry/core/esm/tracing/errors.js
generated
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
import { addGlobalErrorInstrumentationHandler, addGlobalUnhandledRejectionInstrumentationHandler, logger } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { getActiveTransaction } from './utils.js';
|
||||
|
||||
let errorsInstrumented = false;
|
||||
|
||||
/**
|
||||
* Configures global error listeners
|
||||
*/
|
||||
function registerErrorInstrumentation() {
|
||||
if (errorsInstrumented) {
|
||||
return;
|
||||
}
|
||||
|
||||
errorsInstrumented = true;
|
||||
addGlobalErrorInstrumentationHandler(errorCallback);
|
||||
addGlobalUnhandledRejectionInstrumentationHandler(errorCallback);
|
||||
}
|
||||
|
||||
/**
|
||||
* If an error or unhandled promise occurs, we mark the active transaction as failed
|
||||
*/
|
||||
function errorCallback() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const activeTransaction = getActiveTransaction();
|
||||
if (activeTransaction) {
|
||||
const status = 'internal_error';
|
||||
DEBUG_BUILD && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`);
|
||||
activeTransaction.setStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
// The function name will be lost when bundling but we need to be able to identify this listener later to maintain the
|
||||
// node.js default exit behaviour
|
||||
errorCallback.tag = 'sentry_tracingErrorCallback';
|
||||
|
||||
export { registerErrorInstrumentation };
|
||||
//# sourceMappingURL=errors.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/errors.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/errors.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"errors.js","sources":["../../../src/tracing/errors.ts"],"sourcesContent":["import {\n addGlobalErrorInstrumentationHandler,\n addGlobalUnhandledRejectionInstrumentationHandler,\n logger,\n} from '@sentry/utils';\n\nimport { DEBUG_BUILD } from '../debug-build';\nimport type { SpanStatusType } from './spanstatus';\nimport { getActiveTransaction } from './utils';\n\nlet errorsInstrumented = false;\n\n/**\n * Configures global error listeners\n */\nexport function registerErrorInstrumentation(): void {\n if (errorsInstrumented) {\n return;\n }\n\n errorsInstrumented = true;\n addGlobalErrorInstrumentationHandler(errorCallback);\n addGlobalUnhandledRejectionInstrumentationHandler(errorCallback);\n}\n\n/**\n * If an error or unhandled promise occurs, we mark the active transaction as failed\n */\nfunction errorCallback(): void {\n // eslint-disable-next-line deprecation/deprecation\n const activeTransaction = getActiveTransaction();\n if (activeTransaction) {\n const status: SpanStatusType = 'internal_error';\n DEBUG_BUILD && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`);\n activeTransaction.setStatus(status);\n }\n}\n\n// The function name will be lost when bundling but we need to be able to identify this listener later to maintain the\n// node.js default exit behaviour\nerrorCallback.tag = 'sentry_tracingErrorCallback';\n"],"names":[],"mappings":";;;;AAUA,IAAI,kBAAA,GAAqB,KAAK,CAAA;AAC9B;AACA;AACA;AACA;AACO,SAAS,4BAA4B,GAAS;AACrD,EAAE,IAAI,kBAAkB,EAAE;AAC1B,IAAI,OAAM;AACV,GAAE;AACF;AACA,EAAE,kBAAA,GAAqB,IAAI,CAAA;AAC3B,EAAE,oCAAoC,CAAC,aAAa,CAAC,CAAA;AACrD,EAAE,iDAAiD,CAAC,aAAa,CAAC,CAAA;AAClE,CAAA;AACA;AACA;AACA;AACA;AACA,SAAS,aAAa,GAAS;AAC/B;AACA,EAAE,MAAM,iBAAA,GAAoB,oBAAoB,EAAE,CAAA;AAClD,EAAE,IAAI,iBAAiB,EAAE;AACzB,IAAI,MAAM,MAAM,GAAmB,gBAAgB,CAAA;AACnD,IAAI,WAAY,IAAG,MAAM,CAAC,GAAG,CAAC,CAAC,uBAAuB,EAAE,MAAM,CAAC,wBAAwB,CAAC,CAAC,CAAA;AACzF,IAAI,iBAAiB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;AACvC,GAAE;AACF,CAAA;AACA;AACA;AACA;AACA,aAAa,CAAC,GAAI,GAAE,6BAA6B;;;;"}
|
||||
154
node_modules/@sentry/core/esm/tracing/hubextensions.js
generated
vendored
Normal file
154
node_modules/@sentry/core/esm/tracing/hubextensions.js
generated
vendored
Normal file
@@ -0,0 +1,154 @@
|
||||
import { logger } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { getMainCarrier } from '../hub.js';
|
||||
import { spanToTraceHeader } from '../utils/spanUtils.js';
|
||||
import { registerErrorInstrumentation } from './errors.js';
|
||||
import { IdleTransaction } from './idletransaction.js';
|
||||
import { sampleTransaction } from './sampling.js';
|
||||
import { Transaction } from './transaction.js';
|
||||
|
||||
/** Returns all trace headers that are currently on the top scope. */
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function traceHeaders() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const scope = this.getScope();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const span = scope.getSpan();
|
||||
|
||||
return span
|
||||
? {
|
||||
'sentry-trace': spanToTraceHeader(span),
|
||||
}
|
||||
: {};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new transaction and adds a sampling decision if it doesn't yet have one.
|
||||
*
|
||||
* The Hub.startTransaction method delegates to this method to do its work, passing the Hub instance in as `this`, as if
|
||||
* it had been called on the hub directly. Exists as a separate function so that it can be injected into the class as an
|
||||
* "extension method."
|
||||
*
|
||||
* @param this: The Hub starting the transaction
|
||||
* @param transactionContext: Data used to configure the transaction
|
||||
* @param CustomSamplingContext: Optional data to be provided to the `tracesSampler` function (if any)
|
||||
*
|
||||
* @returns The new transaction
|
||||
*
|
||||
* @see {@link Hub.startTransaction}
|
||||
*/
|
||||
function _startTransaction(
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
|
||||
transactionContext,
|
||||
customSamplingContext,
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = this.getClient();
|
||||
const options = (client && client.getOptions()) || {};
|
||||
|
||||
const configInstrumenter = options.instrumenter || 'sentry';
|
||||
const transactionInstrumenter = transactionContext.instrumenter || 'sentry';
|
||||
|
||||
if (configInstrumenter !== transactionInstrumenter) {
|
||||
DEBUG_BUILD &&
|
||||
logger.error(
|
||||
`A transaction was started with instrumenter=\`${transactionInstrumenter}\`, but the SDK is configured with the \`${configInstrumenter}\` instrumenter.
|
||||
The transaction will not be sampled. Please use the ${configInstrumenter} instrumentation to start transactions.`,
|
||||
);
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transactionContext.sampled = false;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
let transaction = new Transaction(transactionContext, this);
|
||||
transaction = sampleTransaction(transaction, options, {
|
||||
name: transactionContext.name,
|
||||
parentSampled: transactionContext.parentSampled,
|
||||
transactionContext,
|
||||
attributes: {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
...transactionContext.data,
|
||||
...transactionContext.attributes,
|
||||
},
|
||||
...customSamplingContext,
|
||||
});
|
||||
if (transaction.isRecording()) {
|
||||
transaction.initSpanRecorder(options._experiments && (options._experiments.maxSpans ));
|
||||
}
|
||||
if (client && client.emit) {
|
||||
client.emit('startTransaction', transaction);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create new idle transaction.
|
||||
*/
|
||||
function startIdleTransaction(
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
hub,
|
||||
transactionContext,
|
||||
idleTimeout,
|
||||
finalTimeout,
|
||||
onScope,
|
||||
customSamplingContext,
|
||||
heartbeatInterval,
|
||||
delayAutoFinishUntilSignal = false,
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = hub.getClient();
|
||||
const options = (client && client.getOptions()) || {};
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
let transaction = new IdleTransaction(
|
||||
transactionContext,
|
||||
hub,
|
||||
idleTimeout,
|
||||
finalTimeout,
|
||||
heartbeatInterval,
|
||||
onScope,
|
||||
delayAutoFinishUntilSignal,
|
||||
);
|
||||
transaction = sampleTransaction(transaction, options, {
|
||||
name: transactionContext.name,
|
||||
parentSampled: transactionContext.parentSampled,
|
||||
transactionContext,
|
||||
attributes: {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
...transactionContext.data,
|
||||
...transactionContext.attributes,
|
||||
},
|
||||
...customSamplingContext,
|
||||
});
|
||||
if (transaction.isRecording()) {
|
||||
transaction.initSpanRecorder(options._experiments && (options._experiments.maxSpans ));
|
||||
}
|
||||
if (client && client.emit) {
|
||||
client.emit('startTransaction', transaction);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds tracing extensions to the global hub.
|
||||
*/
|
||||
function addTracingExtensions() {
|
||||
const carrier = getMainCarrier();
|
||||
if (!carrier.__SENTRY__) {
|
||||
return;
|
||||
}
|
||||
carrier.__SENTRY__.extensions = carrier.__SENTRY__.extensions || {};
|
||||
if (!carrier.__SENTRY__.extensions.startTransaction) {
|
||||
carrier.__SENTRY__.extensions.startTransaction = _startTransaction;
|
||||
}
|
||||
if (!carrier.__SENTRY__.extensions.traceHeaders) {
|
||||
carrier.__SENTRY__.extensions.traceHeaders = traceHeaders;
|
||||
}
|
||||
|
||||
registerErrorInstrumentation();
|
||||
}
|
||||
|
||||
export { addTracingExtensions, startIdleTransaction };
|
||||
//# sourceMappingURL=hubextensions.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/hubextensions.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/hubextensions.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
403
node_modules/@sentry/core/esm/tracing/idletransaction.js
generated
vendored
Normal file
403
node_modules/@sentry/core/esm/tracing/idletransaction.js
generated
vendored
Normal file
@@ -0,0 +1,403 @@
|
||||
import { logger, timestampInSeconds } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { spanTimeInputToSeconds, spanToJSON } from '../utils/spanUtils.js';
|
||||
import { SpanRecorder } from './span.js';
|
||||
import { Transaction } from './transaction.js';
|
||||
|
||||
const TRACING_DEFAULTS = {
|
||||
idleTimeout: 1000,
|
||||
finalTimeout: 30000,
|
||||
heartbeatInterval: 5000,
|
||||
};
|
||||
|
||||
const FINISH_REASON_TAG = 'finishReason';
|
||||
|
||||
const IDLE_TRANSACTION_FINISH_REASONS = [
|
||||
'heartbeatFailed',
|
||||
'idleTimeout',
|
||||
'documentHidden',
|
||||
'finalTimeout',
|
||||
'externalFinish',
|
||||
'cancelled',
|
||||
];
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
class IdleTransactionSpanRecorder extends SpanRecorder {
|
||||
constructor(
|
||||
_pushActivity,
|
||||
_popActivity,
|
||||
transactionSpanId,
|
||||
maxlen,
|
||||
) {
|
||||
super(maxlen);this._pushActivity = _pushActivity;this._popActivity = _popActivity;this.transactionSpanId = transactionSpanId; }
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
add(span) {
|
||||
// We should make sure we do not push and pop activities for
|
||||
// the transaction that this span recorder belongs to.
|
||||
if (span.spanContext().spanId !== this.transactionSpanId) {
|
||||
// We patch span.end() to pop an activity after setting an endTimestamp.
|
||||
// eslint-disable-next-line @typescript-eslint/unbound-method
|
||||
const originalEnd = span.end;
|
||||
span.end = (...rest) => {
|
||||
this._popActivity(span.spanContext().spanId);
|
||||
return originalEnd.apply(span, rest);
|
||||
};
|
||||
|
||||
// We should only push new activities if the span does not have an end timestamp.
|
||||
if (spanToJSON(span).timestamp === undefined) {
|
||||
this._pushActivity(span.spanContext().spanId);
|
||||
}
|
||||
}
|
||||
|
||||
super.add(span);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An IdleTransaction is a transaction that automatically finishes. It does this by tracking child spans as activities.
|
||||
* You can have multiple IdleTransactions active, but if the `onScope` option is specified, the idle transaction will
|
||||
* put itself on the scope on creation.
|
||||
*/
|
||||
class IdleTransaction extends Transaction {
|
||||
// Activities store a list of active spans
|
||||
|
||||
// Track state of activities in previous heartbeat
|
||||
|
||||
// Amount of times heartbeat has counted. Will cause transaction to finish after 3 beats.
|
||||
|
||||
// We should not use heartbeat if we finished a transaction
|
||||
|
||||
// Idle timeout was canceled and we should finish the transaction with the last span end.
|
||||
|
||||
/**
|
||||
* Timer that tracks Transaction idleTimeout
|
||||
*/
|
||||
|
||||
/**
|
||||
* @deprecated Transactions will be removed in v8. Use spans instead.
|
||||
*/
|
||||
constructor(
|
||||
transactionContext,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
_idleHub,
|
||||
/**
|
||||
* The time to wait in ms until the idle transaction will be finished. This timer is started each time
|
||||
* there are no active spans on this transaction.
|
||||
*/
|
||||
_idleTimeout = TRACING_DEFAULTS.idleTimeout,
|
||||
/**
|
||||
* The final value in ms that a transaction cannot exceed
|
||||
*/
|
||||
_finalTimeout = TRACING_DEFAULTS.finalTimeout,
|
||||
_heartbeatInterval = TRACING_DEFAULTS.heartbeatInterval,
|
||||
// Whether or not the transaction should put itself on the scope when it starts and pop itself off when it ends
|
||||
_onScope = false,
|
||||
/**
|
||||
* When set to `true`, will disable the idle timeout (`_idleTimeout` option) and heartbeat mechanisms (`_heartbeatInterval`
|
||||
* option) until the `sendAutoFinishSignal()` method is called. The final timeout mechanism (`_finalTimeout` option)
|
||||
* will not be affected by this option, meaning the transaction will definitely be finished when the final timeout is
|
||||
* reached, no matter what this option is configured to.
|
||||
*
|
||||
* Defaults to `false`.
|
||||
*/
|
||||
delayAutoFinishUntilSignal = false,
|
||||
) {
|
||||
super(transactionContext, _idleHub);this._idleHub = _idleHub;this._idleTimeout = _idleTimeout;this._finalTimeout = _finalTimeout;this._heartbeatInterval = _heartbeatInterval;this._onScope = _onScope;
|
||||
this.activities = {};
|
||||
this._heartbeatCounter = 0;
|
||||
this._finished = false;
|
||||
this._idleTimeoutCanceledPermanently = false;
|
||||
this._beforeFinishCallbacks = [];
|
||||
this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[4];
|
||||
this._autoFinishAllowed = !delayAutoFinishUntilSignal;
|
||||
|
||||
if (_onScope) {
|
||||
// We set the transaction here on the scope so error events pick up the trace
|
||||
// context and attach it to the error.
|
||||
DEBUG_BUILD && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanContext().spanId}`);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
_idleHub.getScope().setSpan(this);
|
||||
}
|
||||
|
||||
if (!delayAutoFinishUntilSignal) {
|
||||
this._restartIdleTimeout();
|
||||
}
|
||||
|
||||
setTimeout(() => {
|
||||
if (!this._finished) {
|
||||
this.setStatus('deadline_exceeded');
|
||||
this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[3];
|
||||
this.end();
|
||||
}
|
||||
}, this._finalTimeout);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
end(endTimestamp) {
|
||||
const endTimestampInS = spanTimeInputToSeconds(endTimestamp);
|
||||
|
||||
this._finished = true;
|
||||
this.activities = {};
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (this.op === 'ui.action.click') {
|
||||
this.setAttribute(FINISH_REASON_TAG, this._finishReason);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (this.spanRecorder) {
|
||||
DEBUG_BUILD &&
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
logger.log('[Tracing] finishing IdleTransaction', new Date(endTimestampInS * 1000).toISOString(), this.op);
|
||||
|
||||
for (const callback of this._beforeFinishCallbacks) {
|
||||
callback(this, endTimestampInS);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.spanRecorder.spans = this.spanRecorder.spans.filter((span) => {
|
||||
// If we are dealing with the transaction itself, we just return it
|
||||
if (span.spanContext().spanId === this.spanContext().spanId) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// We cancel all pending spans with status "cancelled" to indicate the idle transaction was finished early
|
||||
if (!spanToJSON(span).timestamp) {
|
||||
span.setStatus('cancelled');
|
||||
span.end(endTimestampInS);
|
||||
DEBUG_BUILD &&
|
||||
logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2));
|
||||
}
|
||||
|
||||
const { start_timestamp: startTime, timestamp: endTime } = spanToJSON(span);
|
||||
const spanStartedBeforeTransactionFinish = startTime && startTime < endTimestampInS;
|
||||
|
||||
// Add a delta with idle timeout so that we prevent false positives
|
||||
const timeoutWithMarginOfError = (this._finalTimeout + this._idleTimeout) / 1000;
|
||||
const spanEndedBeforeFinalTimeout = endTime && startTime && endTime - startTime < timeoutWithMarginOfError;
|
||||
|
||||
if (DEBUG_BUILD) {
|
||||
const stringifiedSpan = JSON.stringify(span, undefined, 2);
|
||||
if (!spanStartedBeforeTransactionFinish) {
|
||||
logger.log('[Tracing] discarding Span since it happened after Transaction was finished', stringifiedSpan);
|
||||
} else if (!spanEndedBeforeFinalTimeout) {
|
||||
logger.log('[Tracing] discarding Span since it finished after Transaction final timeout', stringifiedSpan);
|
||||
}
|
||||
}
|
||||
|
||||
return spanStartedBeforeTransactionFinish && spanEndedBeforeFinalTimeout;
|
||||
});
|
||||
|
||||
DEBUG_BUILD && logger.log('[Tracing] flushing IdleTransaction');
|
||||
} else {
|
||||
DEBUG_BUILD && logger.log('[Tracing] No active IdleTransaction');
|
||||
}
|
||||
|
||||
// if `this._onScope` is `true`, the transaction put itself on the scope when it started
|
||||
if (this._onScope) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const scope = this._idleHub.getScope();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (scope.getTransaction() === this) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
scope.setSpan(undefined);
|
||||
}
|
||||
}
|
||||
|
||||
return super.end(endTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a callback function that gets executed before the transaction finishes.
|
||||
* Useful for cleanup or if you want to add any additional spans based on current context.
|
||||
*
|
||||
* This is exposed because users have no other way of running something before an idle transaction
|
||||
* finishes.
|
||||
*/
|
||||
registerBeforeFinishCallback(callback) {
|
||||
this._beforeFinishCallbacks.push(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
initSpanRecorder(maxlen) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (!this.spanRecorder) {
|
||||
const pushActivity = (id) => {
|
||||
if (this._finished) {
|
||||
return;
|
||||
}
|
||||
this._pushActivity(id);
|
||||
};
|
||||
const popActivity = (id) => {
|
||||
if (this._finished) {
|
||||
return;
|
||||
}
|
||||
this._popActivity(id);
|
||||
};
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.spanRecorder = new IdleTransactionSpanRecorder(pushActivity, popActivity, this.spanContext().spanId, maxlen);
|
||||
|
||||
// Start heartbeat so that transactions do not run forever.
|
||||
DEBUG_BUILD && logger.log('Starting heartbeat');
|
||||
this._pingHeartbeat();
|
||||
}
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.spanRecorder.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the existing idle timeout, if there is one.
|
||||
* @param restartOnChildSpanChange Default is `true`.
|
||||
* If set to false the transaction will end
|
||||
* with the last child span.
|
||||
*/
|
||||
cancelIdleTimeout(
|
||||
endTimestamp,
|
||||
{
|
||||
restartOnChildSpanChange,
|
||||
}
|
||||
|
||||
= {
|
||||
restartOnChildSpanChange: true,
|
||||
},
|
||||
) {
|
||||
this._idleTimeoutCanceledPermanently = restartOnChildSpanChange === false;
|
||||
if (this._idleTimeoutID) {
|
||||
clearTimeout(this._idleTimeoutID);
|
||||
this._idleTimeoutID = undefined;
|
||||
|
||||
if (Object.keys(this.activities).length === 0 && this._idleTimeoutCanceledPermanently) {
|
||||
this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[5];
|
||||
this.end(endTimestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporary method used to externally set the transaction's `finishReason`
|
||||
*
|
||||
* ** WARNING**
|
||||
* This is for the purpose of experimentation only and will be removed in the near future, do not use!
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
*/
|
||||
setFinishReason(reason) {
|
||||
this._finishReason = reason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Permits the IdleTransaction to automatically end itself via the idle timeout and heartbeat mechanisms when the `delayAutoFinishUntilSignal` option was set to `true`.
|
||||
*/
|
||||
sendAutoFinishSignal() {
|
||||
if (!this._autoFinishAllowed) {
|
||||
DEBUG_BUILD && logger.log('[Tracing] Received finish signal for idle transaction.');
|
||||
this._restartIdleTimeout();
|
||||
this._autoFinishAllowed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Restarts idle timeout, if there is no running idle timeout it will start one.
|
||||
*/
|
||||
_restartIdleTimeout(endTimestamp) {
|
||||
this.cancelIdleTimeout();
|
||||
this._idleTimeoutID = setTimeout(() => {
|
||||
if (!this._finished && Object.keys(this.activities).length === 0) {
|
||||
this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[1];
|
||||
this.end(endTimestamp);
|
||||
}
|
||||
}, this._idleTimeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start tracking a specific activity.
|
||||
* @param spanId The span id that represents the activity
|
||||
*/
|
||||
_pushActivity(spanId) {
|
||||
this.cancelIdleTimeout(undefined, { restartOnChildSpanChange: !this._idleTimeoutCanceledPermanently });
|
||||
DEBUG_BUILD && logger.log(`[Tracing] pushActivity: ${spanId}`);
|
||||
this.activities[spanId] = true;
|
||||
DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove an activity from usage
|
||||
* @param spanId The span id that represents the activity
|
||||
*/
|
||||
_popActivity(spanId) {
|
||||
if (this.activities[spanId]) {
|
||||
DEBUG_BUILD && logger.log(`[Tracing] popActivity ${spanId}`);
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete this.activities[spanId];
|
||||
DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length);
|
||||
}
|
||||
|
||||
if (Object.keys(this.activities).length === 0) {
|
||||
const endTimestamp = timestampInSeconds();
|
||||
if (this._idleTimeoutCanceledPermanently) {
|
||||
if (this._autoFinishAllowed) {
|
||||
this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[5];
|
||||
this.end(endTimestamp);
|
||||
}
|
||||
} else {
|
||||
// We need to add the timeout here to have the real endtimestamp of the transaction
|
||||
// Remember timestampInSeconds is in seconds, timeout is in ms
|
||||
this._restartIdleTimeout(endTimestamp + this._idleTimeout / 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks when entries of this.activities are not changing for 3 beats.
|
||||
* If this occurs we finish the transaction.
|
||||
*/
|
||||
_beat() {
|
||||
// We should not be running heartbeat if the idle transaction is finished.
|
||||
if (this._finished) {
|
||||
return;
|
||||
}
|
||||
|
||||
const heartbeatString = Object.keys(this.activities).join('');
|
||||
|
||||
if (heartbeatString === this._prevHeartbeatString) {
|
||||
this._heartbeatCounter++;
|
||||
} else {
|
||||
this._heartbeatCounter = 1;
|
||||
}
|
||||
|
||||
this._prevHeartbeatString = heartbeatString;
|
||||
|
||||
if (this._heartbeatCounter >= 3) {
|
||||
if (this._autoFinishAllowed) {
|
||||
DEBUG_BUILD && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats');
|
||||
this.setStatus('deadline_exceeded');
|
||||
this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[0];
|
||||
this.end();
|
||||
}
|
||||
} else {
|
||||
this._pingHeartbeat();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Pings the heartbeat
|
||||
*/
|
||||
_pingHeartbeat() {
|
||||
DEBUG_BUILD && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`);
|
||||
setTimeout(() => {
|
||||
this._beat();
|
||||
}, this._heartbeatInterval);
|
||||
}
|
||||
}
|
||||
|
||||
export { IdleTransaction, IdleTransactionSpanRecorder, TRACING_DEFAULTS };
|
||||
//# sourceMappingURL=idletransaction.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/idletransaction.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/idletransaction.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
16
node_modules/@sentry/core/esm/tracing/measurement.js
generated
vendored
Normal file
16
node_modules/@sentry/core/esm/tracing/measurement.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
import { getActiveTransaction } from './utils.js';
|
||||
|
||||
/**
|
||||
* Adds a measurement to the current active transaction.
|
||||
*/
|
||||
function setMeasurement(name, value, unit) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const transaction = getActiveTransaction();
|
||||
if (transaction) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.setMeasurement(name, value, unit);
|
||||
}
|
||||
}
|
||||
|
||||
export { setMeasurement };
|
||||
//# sourceMappingURL=measurement.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/measurement.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/measurement.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"measurement.js","sources":["../../../src/tracing/measurement.ts"],"sourcesContent":["import type { MeasurementUnit } from '@sentry/types';\n\nimport { getActiveTransaction } from './utils';\n\n/**\n * Adds a measurement to the current active transaction.\n */\nexport function setMeasurement(name: string, value: number, unit: MeasurementUnit): void {\n // eslint-disable-next-line deprecation/deprecation\n const transaction = getActiveTransaction();\n if (transaction) {\n // eslint-disable-next-line deprecation/deprecation\n transaction.setMeasurement(name, value, unit);\n }\n}\n"],"names":[],"mappings":";;AAIA;AACA;AACA;AACO,SAAS,cAAc,CAAC,IAAI,EAAU,KAAK,EAAU,IAAI,EAAyB;AACzF;AACA,EAAE,MAAM,WAAA,GAAc,oBAAoB,EAAE,CAAA;AAC5C,EAAE,IAAI,WAAW,EAAE;AACnB;AACA,IAAI,WAAW,CAAC,cAAc,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAA;AACjD,GAAE;AACF;;;;"}
|
||||
126
node_modules/@sentry/core/esm/tracing/sampling.js
generated
vendored
Normal file
126
node_modules/@sentry/core/esm/tracing/sampling.js
generated
vendored
Normal file
@@ -0,0 +1,126 @@
|
||||
import { isNaN, logger } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '../semanticAttributes.js';
|
||||
import { hasTracingEnabled } from '../utils/hasTracingEnabled.js';
|
||||
import { spanToJSON } from '../utils/spanUtils.js';
|
||||
|
||||
/**
|
||||
* Makes a sampling decision for the given transaction and stores it on the transaction.
|
||||
*
|
||||
* Called every time a transaction is created. Only transactions which emerge with a `sampled` value of `true` will be
|
||||
* sent to Sentry.
|
||||
*
|
||||
* This method muttes the given `transaction` and will set the `sampled` value on it.
|
||||
* It returns the same transaction, for convenience.
|
||||
*/
|
||||
function sampleTransaction(
|
||||
transaction,
|
||||
options,
|
||||
samplingContext,
|
||||
) {
|
||||
// nothing to do if tracing is not enabled
|
||||
if (!hasTracingEnabled(options)) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.sampled = false;
|
||||
return transaction;
|
||||
}
|
||||
|
||||
// if the user has forced a sampling decision by passing a `sampled` value in their transaction context, go with that
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (transaction.sampled !== undefined) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Number(transaction.sampled));
|
||||
return transaction;
|
||||
}
|
||||
|
||||
// we would have bailed already if neither `tracesSampler` nor `tracesSampleRate` nor `enableTracing` were defined, so one of these should
|
||||
// work; prefer the hook if so
|
||||
let sampleRate;
|
||||
if (typeof options.tracesSampler === 'function') {
|
||||
sampleRate = options.tracesSampler(samplingContext);
|
||||
transaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Number(sampleRate));
|
||||
} else if (samplingContext.parentSampled !== undefined) {
|
||||
sampleRate = samplingContext.parentSampled;
|
||||
} else if (typeof options.tracesSampleRate !== 'undefined') {
|
||||
sampleRate = options.tracesSampleRate;
|
||||
transaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, Number(sampleRate));
|
||||
} else {
|
||||
// When `enableTracing === true`, we use a sample rate of 100%
|
||||
sampleRate = 1;
|
||||
transaction.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE, sampleRate);
|
||||
}
|
||||
|
||||
// Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The
|
||||
// only valid values are booleans or numbers between 0 and 1.)
|
||||
if (!isValidSampleRate(sampleRate)) {
|
||||
DEBUG_BUILD && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.');
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.sampled = false;
|
||||
return transaction;
|
||||
}
|
||||
|
||||
// if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped
|
||||
if (!sampleRate) {
|
||||
DEBUG_BUILD &&
|
||||
logger.log(
|
||||
`[Tracing] Discarding transaction because ${
|
||||
typeof options.tracesSampler === 'function'
|
||||
? 'tracesSampler returned 0 or false'
|
||||
: 'a negative sampling decision was inherited or tracesSampleRate is set to 0'
|
||||
}`,
|
||||
);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.sampled = false;
|
||||
return transaction;
|
||||
}
|
||||
|
||||
// Now we roll the dice. Math.random is inclusive of 0, but not of 1, so strict < is safe here. In case sampleRate is
|
||||
// a boolean, the < comparison will cause it to be automatically cast to 1 if it's true and 0 if it's false.
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transaction.sampled = Math.random() < (sampleRate );
|
||||
|
||||
// if we're not going to keep it, we're done
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (!transaction.sampled) {
|
||||
DEBUG_BUILD &&
|
||||
logger.log(
|
||||
`[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${Number(
|
||||
sampleRate,
|
||||
)})`,
|
||||
);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
DEBUG_BUILD &&
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
logger.log(`[Tracing] starting ${transaction.op} transaction - ${spanToJSON(transaction).description}`);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the given sample rate to make sure it is valid type and value (a boolean, or a number between 0 and 1).
|
||||
*/
|
||||
function isValidSampleRate(rate) {
|
||||
// we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
if (isNaN(rate) || !(typeof rate === 'number' || typeof rate === 'boolean')) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(
|
||||
`[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify(
|
||||
rate,
|
||||
)} of type ${JSON.stringify(typeof rate)}.`,
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
// in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false
|
||||
if (rate < 0 || rate > 1) {
|
||||
DEBUG_BUILD &&
|
||||
logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export { isValidSampleRate, sampleTransaction };
|
||||
//# sourceMappingURL=sampling.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/sampling.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/sampling.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
641
node_modules/@sentry/core/esm/tracing/span.js
generated
vendored
Normal file
641
node_modules/@sentry/core/esm/tracing/span.js
generated
vendored
Normal file
@@ -0,0 +1,641 @@
|
||||
import { uuid4, timestampInSeconds, logger, dropUndefinedKeys } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary.js';
|
||||
import { SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, SEMANTIC_ATTRIBUTE_SENTRY_OP, SEMANTIC_ATTRIBUTE_PROFILE_ID } from '../semanticAttributes.js';
|
||||
import { getRootSpan } from '../utils/getRootSpan.js';
|
||||
import { TRACE_FLAG_SAMPLED, TRACE_FLAG_NONE, spanToJSON, spanTimeInputToSeconds, spanToTraceHeader, spanToTraceContext } from '../utils/spanUtils.js';
|
||||
import { setHttpStatus } from './spanstatus.js';
|
||||
|
||||
/**
|
||||
* Keeps track of finished spans for a given transaction
|
||||
* @internal
|
||||
* @hideconstructor
|
||||
* @hidden
|
||||
*/
|
||||
class SpanRecorder {
|
||||
|
||||
constructor(maxlen = 1000) {
|
||||
this._maxlen = maxlen;
|
||||
this.spans = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* This is just so that we don't run out of memory while recording a lot
|
||||
* of spans. At some point we just stop and flush out the start of the
|
||||
* trace tree (i.e.the first n spans with the smallest
|
||||
* start_timestamp).
|
||||
*/
|
||||
add(span) {
|
||||
if (this.spans.length > this._maxlen) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
span.spanRecorder = undefined;
|
||||
} else {
|
||||
this.spans.push(span);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Span contains all data about a span
|
||||
*/
|
||||
class Span {
|
||||
/**
|
||||
* Tags for the span.
|
||||
* @deprecated Use `spanToJSON(span).atttributes` instead.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Data for the span.
|
||||
* @deprecated Use `spanToJSON(span).atttributes` instead.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
|
||||
/**
|
||||
* List of spans that were finalized
|
||||
*
|
||||
* @deprecated This property will no longer be public. Span recording will be handled internally.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use top level `Sentry.getRootSpan()` instead
|
||||
*/
|
||||
|
||||
/**
|
||||
* The instrumenter that created this span.
|
||||
*
|
||||
* TODO (v8): This can probably be replaced by an `instanceOf` check of the span class.
|
||||
* the instrumenter can only be sentry or otel so we can check the span instance
|
||||
* to verify which one it is and remove this field entirely.
|
||||
*
|
||||
* @deprecated This field will be removed.
|
||||
*/
|
||||
|
||||
/** Epoch timestamp in seconds when the span started. */
|
||||
|
||||
/** Epoch timestamp in seconds when the span ended. */
|
||||
|
||||
/** Internal keeper of the status */
|
||||
|
||||
/**
|
||||
* You should never call the constructor manually, always use `Sentry.startTransaction()`
|
||||
* or call `startChild()` on an existing span.
|
||||
* @internal
|
||||
* @hideconstructor
|
||||
* @hidden
|
||||
*/
|
||||
constructor(spanContext = {}) {
|
||||
this._traceId = spanContext.traceId || uuid4();
|
||||
this._spanId = spanContext.spanId || uuid4().substring(16);
|
||||
this._startTime = spanContext.startTimestamp || timestampInSeconds();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.tags = spanContext.tags ? { ...spanContext.tags } : {};
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.data = spanContext.data ? { ...spanContext.data } : {};
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.instrumenter = spanContext.instrumenter || 'sentry';
|
||||
|
||||
this._attributes = {};
|
||||
this.setAttributes({
|
||||
[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN]: spanContext.origin || 'manual',
|
||||
[SEMANTIC_ATTRIBUTE_SENTRY_OP]: spanContext.op,
|
||||
...spanContext.attributes,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this._name = spanContext.name || spanContext.description;
|
||||
|
||||
if (spanContext.parentSpanId) {
|
||||
this._parentSpanId = spanContext.parentSpanId;
|
||||
}
|
||||
// We want to include booleans as well here
|
||||
if ('sampled' in spanContext) {
|
||||
this._sampled = spanContext.sampled;
|
||||
}
|
||||
if (spanContext.status) {
|
||||
this._status = spanContext.status;
|
||||
}
|
||||
if (spanContext.endTimestamp) {
|
||||
this._endTime = spanContext.endTimestamp;
|
||||
}
|
||||
if (spanContext.exclusiveTime !== undefined) {
|
||||
this._exclusiveTime = spanContext.exclusiveTime;
|
||||
}
|
||||
this._measurements = spanContext.measurements ? { ...spanContext.measurements } : {};
|
||||
}
|
||||
|
||||
// This rule conflicts with another eslint rule :(
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
|
||||
/**
|
||||
* An alias for `description` of the Span.
|
||||
* @deprecated Use `spanToJSON(span).description` instead.
|
||||
*/
|
||||
get name() {
|
||||
return this._name || '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the name of the span.
|
||||
* @deprecated Use `spanToJSON(span).description` instead.
|
||||
*/
|
||||
set name(name) {
|
||||
this.updateName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of the Span.
|
||||
* @deprecated Use `spanToJSON(span).description` instead.
|
||||
*/
|
||||
get description() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the description of the Span.
|
||||
* @deprecated Use `spanToJSON(span).description` instead.
|
||||
*/
|
||||
set description(description) {
|
||||
this._name = description;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the trace.
|
||||
* @deprecated Use `spanContext().traceId` instead.
|
||||
*/
|
||||
get traceId() {
|
||||
return this._traceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the trace.
|
||||
* @deprecated You cannot update the traceId of a span after span creation.
|
||||
*/
|
||||
set traceId(traceId) {
|
||||
this._traceId = traceId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the span.
|
||||
* @deprecated Use `spanContext().spanId` instead.
|
||||
*/
|
||||
get spanId() {
|
||||
return this._spanId;
|
||||
}
|
||||
|
||||
/**
|
||||
* The ID of the span.
|
||||
* @deprecated You cannot update the spanId of a span after span creation.
|
||||
*/
|
||||
set spanId(spanId) {
|
||||
this._spanId = spanId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `startSpan` functions instead.
|
||||
*/
|
||||
set parentSpanId(string) {
|
||||
this._parentSpanId = string;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `spanToJSON(span).parent_span_id` instead.
|
||||
*/
|
||||
get parentSpanId() {
|
||||
return this._parentSpanId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was this span chosen to be sent as part of the sample?
|
||||
* @deprecated Use `isRecording()` instead.
|
||||
*/
|
||||
get sampled() {
|
||||
return this._sampled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Was this span chosen to be sent as part of the sample?
|
||||
* @deprecated You cannot update the sampling decision of a span after span creation.
|
||||
*/
|
||||
set sampled(sampled) {
|
||||
this._sampled = sampled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes for the span.
|
||||
* @deprecated Use `spanToJSON(span).atttributes` instead.
|
||||
*/
|
||||
get attributes() {
|
||||
return this._attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attributes for the span.
|
||||
* @deprecated Use `setAttributes()` instead.
|
||||
*/
|
||||
set attributes(attributes) {
|
||||
this._attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp in seconds (epoch time) indicating when the span started.
|
||||
* @deprecated Use `spanToJSON()` instead.
|
||||
*/
|
||||
get startTimestamp() {
|
||||
return this._startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp in seconds (epoch time) indicating when the span started.
|
||||
* @deprecated In v8, you will not be able to update the span start time after creation.
|
||||
*/
|
||||
set startTimestamp(startTime) {
|
||||
this._startTime = startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp in seconds when the span ended.
|
||||
* @deprecated Use `spanToJSON()` instead.
|
||||
*/
|
||||
get endTimestamp() {
|
||||
return this._endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp in seconds when the span ended.
|
||||
* @deprecated Set the end time via `span.end()` instead.
|
||||
*/
|
||||
set endTimestamp(endTime) {
|
||||
this._endTime = endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* The status of the span.
|
||||
*
|
||||
* @deprecated Use `spanToJSON().status` instead to get the status.
|
||||
*/
|
||||
get status() {
|
||||
return this._status;
|
||||
}
|
||||
|
||||
/**
|
||||
* The status of the span.
|
||||
*
|
||||
* @deprecated Use `.setStatus()` instead to set or update the status.
|
||||
*/
|
||||
set status(status) {
|
||||
this._status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation of the span
|
||||
*
|
||||
* @deprecated Use `spanToJSON().op` to read the op instead.
|
||||
*/
|
||||
get op() {
|
||||
return this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Operation of the span
|
||||
*
|
||||
* @deprecated Use `startSpan()` functions to set or `span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, 'op')
|
||||
* to update the span instead.
|
||||
*/
|
||||
set op(op) {
|
||||
this.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_OP, op);
|
||||
}
|
||||
|
||||
/**
|
||||
* The origin of the span, giving context about what created the span.
|
||||
*
|
||||
* @deprecated Use `spanToJSON().origin` to read the origin instead.
|
||||
*/
|
||||
get origin() {
|
||||
return this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] ;
|
||||
}
|
||||
|
||||
/**
|
||||
* The origin of the span, giving context about what created the span.
|
||||
*
|
||||
* @deprecated Use `startSpan()` functions to set the origin instead.
|
||||
*/
|
||||
set origin(origin) {
|
||||
this.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, origin);
|
||||
}
|
||||
|
||||
/* eslint-enable @typescript-eslint/member-ordering */
|
||||
|
||||
/** @inheritdoc */
|
||||
spanContext() {
|
||||
const { _spanId: spanId, _traceId: traceId, _sampled: sampled } = this;
|
||||
return {
|
||||
spanId,
|
||||
traceId,
|
||||
traceFlags: sampled ? TRACE_FLAG_SAMPLED : TRACE_FLAG_NONE,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new `Span` while setting the current `Span.id` as `parentSpanId`.
|
||||
* Also the `sampled` decision will be inherited.
|
||||
*
|
||||
* @deprecated Use `startSpan()`, `startSpanManual()` or `startInactiveSpan()` instead.
|
||||
*/
|
||||
startChild(
|
||||
spanContext,
|
||||
) {
|
||||
const childSpan = new Span({
|
||||
...spanContext,
|
||||
parentSpanId: this._spanId,
|
||||
sampled: this._sampled,
|
||||
traceId: this._traceId,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
childSpan.spanRecorder = this.spanRecorder;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (childSpan.spanRecorder) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
childSpan.spanRecorder.add(childSpan);
|
||||
}
|
||||
|
||||
const rootSpan = getRootSpan(this);
|
||||
// TODO: still set span.transaction here until we have a more permanent solution
|
||||
// Probably similarly to the weakmap we hold in node-experimental
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
childSpan.transaction = rootSpan ;
|
||||
|
||||
if (DEBUG_BUILD && rootSpan) {
|
||||
const opStr = (spanContext && spanContext.op) || '< unknown op >';
|
||||
const nameStr = spanToJSON(childSpan).description || '< unknown name >';
|
||||
const idStr = rootSpan.spanContext().spanId;
|
||||
|
||||
const logMessage = `[Tracing] Starting '${opStr}' span on transaction '${nameStr}' (${idStr}).`;
|
||||
logger.log(logMessage);
|
||||
this._logMessage = logMessage;
|
||||
}
|
||||
|
||||
return childSpan;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the tag attribute on the current span.
|
||||
*
|
||||
* Can also be used to unset a tag, by passing `undefined`.
|
||||
*
|
||||
* @param key Tag key
|
||||
* @param value Tag value
|
||||
* @deprecated Use `setAttribute()` instead.
|
||||
*/
|
||||
setTag(key, value) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.tags = { ...this.tags, [key]: value };
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the data attribute on the current span
|
||||
* @param key Data key
|
||||
* @param value Data value
|
||||
* @deprecated Use `setAttribute()` instead.
|
||||
*/
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
setData(key, value) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.data = { ...this.data, [key]: value };
|
||||
return this;
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
setAttribute(key, value) {
|
||||
if (value === undefined) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete this._attributes[key];
|
||||
} else {
|
||||
this._attributes[key] = value;
|
||||
}
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
setAttributes(attributes) {
|
||||
Object.keys(attributes).forEach(key => this.setAttribute(key, attributes[key]));
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
setStatus(value) {
|
||||
this._status = value;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
* @deprecated Use top-level `setHttpStatus()` instead.
|
||||
*/
|
||||
setHttpStatus(httpStatus) {
|
||||
setHttpStatus(this, httpStatus);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @deprecated Use `.updateName()` instead.
|
||||
*/
|
||||
setName(name) {
|
||||
this.updateName(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
updateName(name) {
|
||||
this._name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `spanToJSON(span).status === 'ok'` instead.
|
||||
*/
|
||||
isSuccess() {
|
||||
return this._status === 'ok';
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `.end()` instead.
|
||||
*/
|
||||
finish(endTimestamp) {
|
||||
return this.end(endTimestamp);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
end(endTimestamp) {
|
||||
// If already ended, skip
|
||||
if (this._endTime) {
|
||||
return;
|
||||
}
|
||||
const rootSpan = getRootSpan(this);
|
||||
if (
|
||||
DEBUG_BUILD &&
|
||||
// Don't call this for transactions
|
||||
rootSpan &&
|
||||
rootSpan.spanContext().spanId !== this._spanId
|
||||
) {
|
||||
const logMessage = this._logMessage;
|
||||
if (logMessage) {
|
||||
logger.log((logMessage ).replace('Starting', 'Finishing'));
|
||||
}
|
||||
}
|
||||
|
||||
this._endTime = spanTimeInputToSeconds(endTimestamp);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `spanToTraceHeader()` instead.
|
||||
*/
|
||||
toTraceparent() {
|
||||
return spanToTraceHeader(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `spanToJSON()` or access the fields directly instead.
|
||||
*/
|
||||
toContext() {
|
||||
return dropUndefinedKeys({
|
||||
data: this._getData(),
|
||||
description: this._name,
|
||||
endTimestamp: this._endTime,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
op: this.op,
|
||||
parentSpanId: this._parentSpanId,
|
||||
sampled: this._sampled,
|
||||
spanId: this._spanId,
|
||||
startTimestamp: this._startTime,
|
||||
status: this._status,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
tags: this.tags,
|
||||
traceId: this._traceId,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Update the fields directly instead.
|
||||
*/
|
||||
updateWithContext(spanContext) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.data = spanContext.data || {};
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this._name = spanContext.name || spanContext.description;
|
||||
this._endTime = spanContext.endTimestamp;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.op = spanContext.op;
|
||||
this._parentSpanId = spanContext.parentSpanId;
|
||||
this._sampled = spanContext.sampled;
|
||||
this._spanId = spanContext.spanId || this._spanId;
|
||||
this._startTime = spanContext.startTimestamp || this._startTime;
|
||||
this._status = spanContext.status;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.tags = spanContext.tags || {};
|
||||
this._traceId = spanContext.traceId || this._traceId;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use `spanToTraceContext()` util function instead.
|
||||
*/
|
||||
getTraceContext() {
|
||||
return spanToTraceContext(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get JSON representation of this span.
|
||||
*
|
||||
* @hidden
|
||||
* @internal This method is purely for internal purposes and should not be used outside
|
||||
* of SDK code. If you need to get a JSON representation of a span,
|
||||
* use `spanToJSON(span)` instead.
|
||||
*/
|
||||
getSpanJSON() {
|
||||
return dropUndefinedKeys({
|
||||
data: this._getData(),
|
||||
description: this._name,
|
||||
op: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_OP] ,
|
||||
parent_span_id: this._parentSpanId,
|
||||
span_id: this._spanId,
|
||||
start_timestamp: this._startTime,
|
||||
status: this._status,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
tags: Object.keys(this.tags).length > 0 ? this.tags : undefined,
|
||||
timestamp: this._endTime,
|
||||
trace_id: this._traceId,
|
||||
origin: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN] ,
|
||||
_metrics_summary: getMetricSummaryJsonForSpan(this),
|
||||
profile_id: this._attributes[SEMANTIC_ATTRIBUTE_PROFILE_ID] ,
|
||||
exclusive_time: this._exclusiveTime,
|
||||
measurements: Object.keys(this._measurements).length > 0 ? this._measurements : undefined,
|
||||
});
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
isRecording() {
|
||||
return !this._endTime && !!this._sampled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the object to JSON.
|
||||
* @deprecated Use `spanToJSON(span)` instead.
|
||||
*/
|
||||
toJSON() {
|
||||
return this.getSpanJSON();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged data for this span.
|
||||
* For now, this combines `data` and `attributes` together,
|
||||
* until eventually we can ingest `attributes` directly.
|
||||
*/
|
||||
_getData()
|
||||
|
||||
{
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { data, _attributes: attributes } = this;
|
||||
|
||||
const hasData = Object.keys(data).length > 0;
|
||||
const hasAttributes = Object.keys(attributes).length > 0;
|
||||
|
||||
if (!hasData && !hasAttributes) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (hasData && hasAttributes) {
|
||||
return {
|
||||
...data,
|
||||
...attributes,
|
||||
};
|
||||
}
|
||||
|
||||
return hasData ? data : attributes;
|
||||
}
|
||||
}
|
||||
|
||||
export { Span, SpanRecorder };
|
||||
//# sourceMappingURL=span.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/span.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/span.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
123
node_modules/@sentry/core/esm/tracing/spanstatus.js
generated
vendored
Normal file
123
node_modules/@sentry/core/esm/tracing/spanstatus.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
/** The status of an Span.
|
||||
*
|
||||
* @deprecated Use string literals - if you require type casting, cast to SpanStatusType type
|
||||
*/
|
||||
var SpanStatus; (function (SpanStatus) {
|
||||
/** The operation completed successfully. */
|
||||
const Ok = 'ok'; SpanStatus["Ok"] = Ok;
|
||||
/** Deadline expired before operation could complete. */
|
||||
const DeadlineExceeded = 'deadline_exceeded'; SpanStatus["DeadlineExceeded"] = DeadlineExceeded;
|
||||
/** 401 Unauthorized (actually does mean unauthenticated according to RFC 7235) */
|
||||
const Unauthenticated = 'unauthenticated'; SpanStatus["Unauthenticated"] = Unauthenticated;
|
||||
/** 403 Forbidden */
|
||||
const PermissionDenied = 'permission_denied'; SpanStatus["PermissionDenied"] = PermissionDenied;
|
||||
/** 404 Not Found. Some requested entity (file or directory) was not found. */
|
||||
const NotFound = 'not_found'; SpanStatus["NotFound"] = NotFound;
|
||||
/** 429 Too Many Requests */
|
||||
const ResourceExhausted = 'resource_exhausted'; SpanStatus["ResourceExhausted"] = ResourceExhausted;
|
||||
/** Client specified an invalid argument. 4xx. */
|
||||
const InvalidArgument = 'invalid_argument'; SpanStatus["InvalidArgument"] = InvalidArgument;
|
||||
/** 501 Not Implemented */
|
||||
const Unimplemented = 'unimplemented'; SpanStatus["Unimplemented"] = Unimplemented;
|
||||
/** 503 Service Unavailable */
|
||||
const Unavailable = 'unavailable'; SpanStatus["Unavailable"] = Unavailable;
|
||||
/** Other/generic 5xx. */
|
||||
const InternalError = 'internal_error'; SpanStatus["InternalError"] = InternalError;
|
||||
/** Unknown. Any non-standard HTTP status code. */
|
||||
const UnknownError = 'unknown_error'; SpanStatus["UnknownError"] = UnknownError;
|
||||
/** The operation was cancelled (typically by the user). */
|
||||
const Cancelled = 'cancelled'; SpanStatus["Cancelled"] = Cancelled;
|
||||
/** Already exists (409) */
|
||||
const AlreadyExists = 'already_exists'; SpanStatus["AlreadyExists"] = AlreadyExists;
|
||||
/** Operation was rejected because the system is not in a state required for the operation's */
|
||||
const FailedPrecondition = 'failed_precondition'; SpanStatus["FailedPrecondition"] = FailedPrecondition;
|
||||
/** The operation was aborted, typically due to a concurrency issue. */
|
||||
const Aborted = 'aborted'; SpanStatus["Aborted"] = Aborted;
|
||||
/** Operation was attempted past the valid range. */
|
||||
const OutOfRange = 'out_of_range'; SpanStatus["OutOfRange"] = OutOfRange;
|
||||
/** Unrecoverable data loss or corruption */
|
||||
const DataLoss = 'data_loss'; SpanStatus["DataLoss"] = DataLoss;
|
||||
})(SpanStatus || (SpanStatus = {}));
|
||||
|
||||
/**
|
||||
* Converts a HTTP status code into a {@link SpanStatusType}.
|
||||
*
|
||||
* @param httpStatus The HTTP response status code.
|
||||
* @returns The span status or unknown_error.
|
||||
*/
|
||||
function getSpanStatusFromHttpCode(httpStatus) {
|
||||
if (httpStatus < 400 && httpStatus >= 100) {
|
||||
return 'ok';
|
||||
}
|
||||
|
||||
if (httpStatus >= 400 && httpStatus < 500) {
|
||||
switch (httpStatus) {
|
||||
case 401:
|
||||
return 'unauthenticated';
|
||||
case 403:
|
||||
return 'permission_denied';
|
||||
case 404:
|
||||
return 'not_found';
|
||||
case 409:
|
||||
return 'already_exists';
|
||||
case 413:
|
||||
return 'failed_precondition';
|
||||
case 429:
|
||||
return 'resource_exhausted';
|
||||
default:
|
||||
return 'invalid_argument';
|
||||
}
|
||||
}
|
||||
|
||||
if (httpStatus >= 500 && httpStatus < 600) {
|
||||
switch (httpStatus) {
|
||||
case 501:
|
||||
return 'unimplemented';
|
||||
case 503:
|
||||
return 'unavailable';
|
||||
case 504:
|
||||
return 'deadline_exceeded';
|
||||
default:
|
||||
return 'internal_error';
|
||||
}
|
||||
}
|
||||
|
||||
return 'unknown_error';
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts a HTTP status code into a {@link SpanStatusType}.
|
||||
*
|
||||
* @deprecated Use {@link spanStatusFromHttpCode} instead.
|
||||
* This export will be removed in v8 as the signature contains a typo.
|
||||
*
|
||||
* @param httpStatus The HTTP response status code.
|
||||
* @returns The span status or unknown_error.
|
||||
*/
|
||||
const spanStatusfromHttpCode = getSpanStatusFromHttpCode;
|
||||
|
||||
/**
|
||||
* Sets the Http status attributes on the current span based on the http code.
|
||||
* Additionally, the span's status is updated, depending on the http code.
|
||||
*/
|
||||
function setHttpStatus(span, httpStatus) {
|
||||
// TODO (v8): Remove these calls
|
||||
// Relay does not require us to send the status code as a tag
|
||||
// For now, just because users might expect it to land as a tag we keep sending it.
|
||||
// Same with data.
|
||||
// In v8, we replace both, simply with
|
||||
// span.setAttribute('http.response.status_code', httpStatus);
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
span.setTag('http.status_code', String(httpStatus));
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
span.setData('http.response.status_code', httpStatus);
|
||||
|
||||
const spanStatus = getSpanStatusFromHttpCode(httpStatus);
|
||||
if (spanStatus !== 'unknown_error') {
|
||||
span.setStatus(spanStatus);
|
||||
}
|
||||
}
|
||||
|
||||
export { SpanStatus, getSpanStatusFromHttpCode, setHttpStatus, spanStatusfromHttpCode };
|
||||
//# sourceMappingURL=spanstatus.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/spanstatus.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/spanstatus.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
383
node_modules/@sentry/core/esm/tracing/trace.js
generated
vendored
Normal file
383
node_modules/@sentry/core/esm/tracing/trace.js
generated
vendored
Normal file
@@ -0,0 +1,383 @@
|
||||
import { tracingContextFromHeaders, logger, dropUndefinedKeys, addNonEnumerableProperty } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { getCurrentHub, runWithAsyncContext, getIsolationScope } from '../hub.js';
|
||||
import { spanToJSON, spanIsSampled, spanTimeInputToSeconds } from '../utils/spanUtils.js';
|
||||
import './errors.js';
|
||||
import './spanstatus.js';
|
||||
import { getDynamicSamplingContextFromSpan } from './dynamicSamplingContext.js';
|
||||
import { getCurrentScope, withScope } from '../exports.js';
|
||||
import { handleCallbackErrors } from '../utils/handleCallbackErrors.js';
|
||||
import { hasTracingEnabled } from '../utils/hasTracingEnabled.js';
|
||||
|
||||
/**
|
||||
* Wraps a function with a transaction/span and finishes the span after the function is done.
|
||||
*
|
||||
* Note that if you have not enabled tracing extensions via `addTracingExtensions`
|
||||
* or you didn't set `tracesSampleRate`, this function will not generate spans
|
||||
* and the `span` returned from the callback will be undefined.
|
||||
*
|
||||
* This function is meant to be used internally and may break at any time. Use at your own risk.
|
||||
*
|
||||
* @internal
|
||||
* @private
|
||||
*
|
||||
* @deprecated Use `startSpan` instead.
|
||||
*/
|
||||
function trace(
|
||||
context,
|
||||
callback,
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
onError = () => {},
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-function
|
||||
afterFinish = () => {},
|
||||
) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = getCurrentHub();
|
||||
const scope = getCurrentScope();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const parentSpan = scope.getSpan();
|
||||
|
||||
const spanContext = normalizeContext(context);
|
||||
const activeSpan = createChildSpanOrTransaction(hub, {
|
||||
parentSpan,
|
||||
spanContext,
|
||||
forceTransaction: false,
|
||||
scope,
|
||||
});
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
scope.setSpan(activeSpan);
|
||||
|
||||
return handleCallbackErrors(
|
||||
() => callback(activeSpan),
|
||||
error => {
|
||||
activeSpan && activeSpan.setStatus('internal_error');
|
||||
onError(error, activeSpan);
|
||||
},
|
||||
() => {
|
||||
activeSpan && activeSpan.end();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
scope.setSpan(parentSpan);
|
||||
afterFinish();
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a function with a transaction/span and finishes the span after the function is done.
|
||||
* The created span is the active span and will be used as parent by other spans created inside the function
|
||||
* and can be accessed via `Sentry.getSpan()`, as long as the function is executed while the scope is active.
|
||||
*
|
||||
* If you want to create a span that is not set as active, use {@link startInactiveSpan}.
|
||||
*
|
||||
* Note that if you have not enabled tracing extensions via `addTracingExtensions`
|
||||
* or you didn't set `tracesSampleRate`, this function will not generate spans
|
||||
* and the `span` returned from the callback will be undefined.
|
||||
*/
|
||||
function startSpan(context, callback) {
|
||||
const spanContext = normalizeContext(context);
|
||||
|
||||
return runWithAsyncContext(() => {
|
||||
return withScope(context.scope, scope => {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = getCurrentHub();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const parentSpan = scope.getSpan();
|
||||
|
||||
const shouldSkipSpan = context.onlyIfParent && !parentSpan;
|
||||
const activeSpan = shouldSkipSpan
|
||||
? undefined
|
||||
: createChildSpanOrTransaction(hub, {
|
||||
parentSpan,
|
||||
spanContext,
|
||||
forceTransaction: context.forceTransaction,
|
||||
scope,
|
||||
});
|
||||
|
||||
return handleCallbackErrors(
|
||||
() => callback(activeSpan),
|
||||
() => {
|
||||
// Only update the span status if it hasn't been changed yet
|
||||
if (activeSpan) {
|
||||
const { status } = spanToJSON(activeSpan);
|
||||
if (!status || status === 'ok') {
|
||||
activeSpan.setStatus('internal_error');
|
||||
}
|
||||
}
|
||||
},
|
||||
() => activeSpan && activeSpan.end(),
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated Use {@link startSpan} instead.
|
||||
*/
|
||||
const startActiveSpan = startSpan;
|
||||
|
||||
/**
|
||||
* Similar to `Sentry.startSpan`. Wraps a function with a transaction/span, but does not finish the span
|
||||
* after the function is done automatically. You'll have to call `span.end()` manually.
|
||||
*
|
||||
* The created span is the active span and will be used as parent by other spans created inside the function
|
||||
* and can be accessed via `Sentry.getActiveSpan()`, as long as the function is executed while the scope is active.
|
||||
*
|
||||
* Note that if you have not enabled tracing extensions via `addTracingExtensions`
|
||||
* or you didn't set `tracesSampleRate`, this function will not generate spans
|
||||
* and the `span` returned from the callback will be undefined.
|
||||
*/
|
||||
function startSpanManual(
|
||||
context,
|
||||
callback,
|
||||
) {
|
||||
const spanContext = normalizeContext(context);
|
||||
|
||||
return runWithAsyncContext(() => {
|
||||
return withScope(context.scope, scope => {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = getCurrentHub();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const parentSpan = scope.getSpan();
|
||||
|
||||
const shouldSkipSpan = context.onlyIfParent && !parentSpan;
|
||||
const activeSpan = shouldSkipSpan
|
||||
? undefined
|
||||
: createChildSpanOrTransaction(hub, {
|
||||
parentSpan,
|
||||
spanContext,
|
||||
forceTransaction: context.forceTransaction,
|
||||
scope,
|
||||
});
|
||||
|
||||
function finishAndSetSpan() {
|
||||
activeSpan && activeSpan.end();
|
||||
}
|
||||
|
||||
return handleCallbackErrors(
|
||||
() => callback(activeSpan, finishAndSetSpan),
|
||||
() => {
|
||||
// Only update the span status if it hasn't been changed yet, and the span is not yet finished
|
||||
if (activeSpan && activeSpan.isRecording()) {
|
||||
const { status } = spanToJSON(activeSpan);
|
||||
if (!status || status === 'ok') {
|
||||
activeSpan.setStatus('internal_error');
|
||||
}
|
||||
}
|
||||
},
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a span. This span is not set as active, so will not get automatic instrumentation spans
|
||||
* as children or be able to be accessed via `Sentry.getSpan()`.
|
||||
*
|
||||
* If you want to create a span that is set as active, use {@link startSpan}.
|
||||
*
|
||||
* Note that if you have not enabled tracing extensions via `addTracingExtensions`
|
||||
* or you didn't set `tracesSampleRate` or `tracesSampler`, this function will not generate spans
|
||||
* and the `span` returned from the callback will be undefined.
|
||||
*/
|
||||
function startInactiveSpan(context) {
|
||||
if (!hasTracingEnabled()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const spanContext = normalizeContext(context);
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = getCurrentHub();
|
||||
const parentSpan = context.scope
|
||||
? // eslint-disable-next-line deprecation/deprecation
|
||||
context.scope.getSpan()
|
||||
: getActiveSpan();
|
||||
|
||||
const shouldSkipSpan = context.onlyIfParent && !parentSpan;
|
||||
|
||||
if (shouldSkipSpan) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const scope = context.scope || getCurrentScope();
|
||||
|
||||
// Even though we don't actually want to make this span active on the current scope,
|
||||
// we need to make it active on a temporary scope that we use for event processing
|
||||
// as otherwise, it won't pick the correct span for the event when processing it
|
||||
const temporaryScope = (scope ).clone();
|
||||
|
||||
return createChildSpanOrTransaction(hub, {
|
||||
parentSpan,
|
||||
spanContext,
|
||||
forceTransaction: context.forceTransaction,
|
||||
scope: temporaryScope,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active span.
|
||||
*/
|
||||
function getActiveSpan() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return getCurrentScope().getSpan();
|
||||
}
|
||||
|
||||
const continueTrace = (
|
||||
{
|
||||
sentryTrace,
|
||||
baggage,
|
||||
}
|
||||
|
||||
,
|
||||
callback,
|
||||
) => {
|
||||
// TODO(v8): Change this function so it doesn't do anything besides setting the propagation context on the current scope:
|
||||
/*
|
||||
return withScope((scope) => {
|
||||
const propagationContext = propagationContextFromHeaders(sentryTrace, baggage);
|
||||
scope.setPropagationContext(propagationContext);
|
||||
return callback();
|
||||
})
|
||||
*/
|
||||
|
||||
const currentScope = getCurrentScope();
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { traceparentData, dynamicSamplingContext, propagationContext } = tracingContextFromHeaders(
|
||||
sentryTrace,
|
||||
baggage,
|
||||
);
|
||||
|
||||
currentScope.setPropagationContext(propagationContext);
|
||||
|
||||
if (DEBUG_BUILD && traceparentData) {
|
||||
logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`);
|
||||
}
|
||||
|
||||
const transactionContext = {
|
||||
...traceparentData,
|
||||
metadata: dropUndefinedKeys({
|
||||
dynamicSamplingContext,
|
||||
}),
|
||||
};
|
||||
|
||||
if (!callback) {
|
||||
return transactionContext;
|
||||
}
|
||||
|
||||
return runWithAsyncContext(() => {
|
||||
return callback(transactionContext);
|
||||
});
|
||||
};
|
||||
|
||||
function createChildSpanOrTransaction(
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
hub,
|
||||
{
|
||||
parentSpan,
|
||||
spanContext,
|
||||
forceTransaction,
|
||||
scope,
|
||||
}
|
||||
|
||||
,
|
||||
) {
|
||||
if (!hasTracingEnabled()) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const isolationScope = getIsolationScope();
|
||||
|
||||
let span;
|
||||
if (parentSpan && !forceTransaction) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
span = parentSpan.startChild(spanContext);
|
||||
} else if (parentSpan) {
|
||||
// If we forced a transaction but have a parent span, make sure to continue from the parent span, not the scope
|
||||
const dsc = getDynamicSamplingContextFromSpan(parentSpan);
|
||||
const { traceId, spanId: parentSpanId } = parentSpan.spanContext();
|
||||
const sampled = spanIsSampled(parentSpan);
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
span = hub.startTransaction({
|
||||
traceId,
|
||||
parentSpanId,
|
||||
parentSampled: sampled,
|
||||
...spanContext,
|
||||
metadata: {
|
||||
dynamicSamplingContext: dsc,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
...spanContext.metadata,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
const { traceId, dsc, parentSpanId, sampled } = {
|
||||
...isolationScope.getPropagationContext(),
|
||||
...scope.getPropagationContext(),
|
||||
};
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
span = hub.startTransaction({
|
||||
traceId,
|
||||
parentSpanId,
|
||||
parentSampled: sampled,
|
||||
...spanContext,
|
||||
metadata: {
|
||||
dynamicSamplingContext: dsc,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
...spanContext.metadata,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
// We always set this as active span on the scope
|
||||
// In the case of this being an inactive span, we ensure to pass a detached scope in here in the first place
|
||||
// But by having this here, we can ensure that the lookup through `getCapturedScopesOnSpan` results in the correct scope & span combo
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
scope.setSpan(span);
|
||||
|
||||
setCapturedScopesOnSpan(span, scope, isolationScope);
|
||||
|
||||
return span;
|
||||
}
|
||||
|
||||
/**
|
||||
* This converts StartSpanOptions to TransactionContext.
|
||||
* For the most part (for now) we accept the same options,
|
||||
* but some of them need to be transformed.
|
||||
*
|
||||
* Eventually the StartSpanOptions will be more aligned with OpenTelemetry.
|
||||
*/
|
||||
function normalizeContext(context) {
|
||||
if (context.startTime) {
|
||||
const ctx = { ...context };
|
||||
ctx.startTimestamp = spanTimeInputToSeconds(context.startTime);
|
||||
delete ctx.startTime;
|
||||
return ctx;
|
||||
}
|
||||
|
||||
return context;
|
||||
}
|
||||
|
||||
const SCOPE_ON_START_SPAN_FIELD = '_sentryScope';
|
||||
const ISOLATION_SCOPE_ON_START_SPAN_FIELD = '_sentryIsolationScope';
|
||||
|
||||
function setCapturedScopesOnSpan(span, scope, isolationScope) {
|
||||
if (span) {
|
||||
addNonEnumerableProperty(span, ISOLATION_SCOPE_ON_START_SPAN_FIELD, isolationScope);
|
||||
addNonEnumerableProperty(span, SCOPE_ON_START_SPAN_FIELD, scope);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Grabs the scope and isolation scope off a span that were active when the span was started.
|
||||
*/
|
||||
function getCapturedScopesOnSpan(span) {
|
||||
return {
|
||||
scope: (span )[SCOPE_ON_START_SPAN_FIELD],
|
||||
isolationScope: (span )[ISOLATION_SCOPE_ON_START_SPAN_FIELD],
|
||||
};
|
||||
}
|
||||
|
||||
export { continueTrace, getActiveSpan, getCapturedScopesOnSpan, startActiveSpan, startInactiveSpan, startSpan, startSpanManual, trace };
|
||||
//# sourceMappingURL=trace.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/trace.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/trace.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
350
node_modules/@sentry/core/esm/tracing/transaction.js
generated
vendored
Normal file
350
node_modules/@sentry/core/esm/tracing/transaction.js
generated
vendored
Normal file
@@ -0,0 +1,350 @@
|
||||
import { dropUndefinedKeys, logger } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
import { getCurrentHub } from '../hub.js';
|
||||
import { getMetricSummaryJsonForSpan } from '../metrics/metric-summary.js';
|
||||
import { SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE } from '../semanticAttributes.js';
|
||||
import { spanTimeInputToSeconds, spanToJSON, spanToTraceContext } from '../utils/spanUtils.js';
|
||||
import { getDynamicSamplingContextFromSpan } from './dynamicSamplingContext.js';
|
||||
import { Span, SpanRecorder } from './span.js';
|
||||
import { getCapturedScopesOnSpan } from './trace.js';
|
||||
|
||||
/** JSDoc */
|
||||
class Transaction extends Span {
|
||||
/**
|
||||
* The reference to the current hub.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
|
||||
// DO NOT yet remove this property, it is used in a hack for v7 backwards compatibility.
|
||||
|
||||
/**
|
||||
* This constructor should never be called manually. Those instrumenting tracing should use
|
||||
* `Sentry.startTransaction()`, and internal methods should use `hub.startTransaction()`.
|
||||
* @internal
|
||||
* @hideconstructor
|
||||
* @hidden
|
||||
*
|
||||
* @deprecated Transactions will be removed in v8. Use spans instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
constructor(transactionContext, hub) {
|
||||
super(transactionContext);
|
||||
this._contexts = {};
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this._hub = hub || getCurrentHub();
|
||||
|
||||
this._name = transactionContext.name || '';
|
||||
|
||||
this._metadata = {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
...transactionContext.metadata,
|
||||
};
|
||||
|
||||
this._trimEnd = transactionContext.trimEnd;
|
||||
|
||||
// this is because transactions are also spans, and spans have a transaction pointer
|
||||
// TODO (v8): Replace this with another way to set the root span
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.transaction = this;
|
||||
|
||||
// If Dynamic Sampling Context is provided during the creation of the transaction, we freeze it as it usually means
|
||||
// there is incoming Dynamic Sampling Context. (Either through an incoming request, a baggage meta-tag, or other means)
|
||||
const incomingDynamicSamplingContext = this._metadata.dynamicSamplingContext;
|
||||
if (incomingDynamicSamplingContext) {
|
||||
// We shallow copy this in case anything writes to the original reference of the passed in `dynamicSamplingContext`
|
||||
this._frozenDynamicSamplingContext = { ...incomingDynamicSamplingContext };
|
||||
}
|
||||
}
|
||||
|
||||
// This sadly conflicts with the getter/setter ordering :(
|
||||
/* eslint-disable @typescript-eslint/member-ordering */
|
||||
|
||||
/**
|
||||
* Getter for `name` property.
|
||||
* @deprecated Use `spanToJSON(span).description` instead.
|
||||
*/
|
||||
get name() {
|
||||
return this._name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Setter for `name` property, which also sets `source` as custom.
|
||||
* @deprecated Use `updateName()` and `setMetadata()` instead.
|
||||
*/
|
||||
set name(newName) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.setName(newName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the metadata for this transaction.
|
||||
* @deprecated Use `spanGetMetadata(transaction)` instead.
|
||||
*/
|
||||
get metadata() {
|
||||
// We merge attributes in for backwards compatibility
|
||||
return {
|
||||
// Defaults
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
source: 'custom',
|
||||
spanMetadata: {},
|
||||
|
||||
// Legacy metadata
|
||||
...this._metadata,
|
||||
|
||||
// From attributes
|
||||
...(this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] && {
|
||||
source: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SOURCE] ,
|
||||
}),
|
||||
...(this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] && {
|
||||
sampleRate: this._attributes[SEMANTIC_ATTRIBUTE_SENTRY_SAMPLE_RATE] ,
|
||||
}),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the metadata for this transaction.
|
||||
* @deprecated Use `spanGetMetadata(transaction)` instead.
|
||||
*/
|
||||
set metadata(metadata) {
|
||||
this._metadata = metadata;
|
||||
}
|
||||
|
||||
/* eslint-enable @typescript-eslint/member-ordering */
|
||||
|
||||
/**
|
||||
* Setter for `name` property, which also sets `source` on the metadata.
|
||||
*
|
||||
* @deprecated Use `.updateName()` and `.setAttribute()` instead.
|
||||
*/
|
||||
setName(name, source = 'custom') {
|
||||
this._name = name;
|
||||
this.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_SOURCE, source);
|
||||
}
|
||||
|
||||
/** @inheritdoc */
|
||||
updateName(name) {
|
||||
this._name = name;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches SpanRecorder to the span itself
|
||||
* @param maxlen maximum number of spans that can be recorded
|
||||
*/
|
||||
initSpanRecorder(maxlen = 1000) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
if (!this.spanRecorder) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.spanRecorder = new SpanRecorder(maxlen);
|
||||
}
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
this.spanRecorder.add(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the context of a transaction event.
|
||||
* @deprecated Use either `.setAttribute()`, or set the context on the scope before creating the transaction.
|
||||
*/
|
||||
setContext(key, context) {
|
||||
if (context === null) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
||||
delete this._contexts[key];
|
||||
} else {
|
||||
this._contexts[key] = context;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*
|
||||
* @deprecated Use top-level `setMeasurement()` instead.
|
||||
*/
|
||||
setMeasurement(name, value, unit = '') {
|
||||
this._measurements[name] = { value, unit };
|
||||
}
|
||||
|
||||
/**
|
||||
* Store metadata on this transaction.
|
||||
* @deprecated Use attributes or store data on the scope instead.
|
||||
*/
|
||||
setMetadata(newMetadata) {
|
||||
this._metadata = { ...this._metadata, ...newMetadata };
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
end(endTimestamp) {
|
||||
const timestampInS = spanTimeInputToSeconds(endTimestamp);
|
||||
const transaction = this._finishTransaction(timestampInS);
|
||||
if (!transaction) {
|
||||
return undefined;
|
||||
}
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return this._hub.captureEvent(transaction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
toContext() {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const spanContext = super.toContext();
|
||||
|
||||
return dropUndefinedKeys({
|
||||
...spanContext,
|
||||
name: this._name,
|
||||
trimEnd: this._trimEnd,
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
updateWithContext(transactionContext) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
super.updateWithContext(transactionContext);
|
||||
|
||||
this._name = transactionContext.name || '';
|
||||
this._trimEnd = transactionContext.trimEnd;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritdoc
|
||||
*
|
||||
* @experimental
|
||||
*
|
||||
* @deprecated Use top-level `getDynamicSamplingContextFromSpan` instead.
|
||||
*/
|
||||
getDynamicSamplingContext() {
|
||||
return getDynamicSamplingContextFromSpan(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the current hub with a new one.
|
||||
* Used if you want another hub to finish the transaction.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
setHub(hub) {
|
||||
this._hub = hub;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the profile id of the transaction.
|
||||
*/
|
||||
getProfileId() {
|
||||
if (this._contexts !== undefined && this._contexts['profile'] !== undefined) {
|
||||
return this._contexts['profile'].profile_id ;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finish the transaction & prepare the event to send to Sentry.
|
||||
*/
|
||||
_finishTransaction(endTimestamp) {
|
||||
// This transaction is already finished, so we should not flush it again.
|
||||
if (this._endTime !== undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (!this._name) {
|
||||
DEBUG_BUILD && logger.warn('Transaction has no name, falling back to `<unlabeled transaction>`.');
|
||||
this._name = '<unlabeled transaction>';
|
||||
}
|
||||
|
||||
// just sets the end timestamp
|
||||
super.end(endTimestamp);
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const client = this._hub.getClient();
|
||||
if (client && client.emit) {
|
||||
client.emit('finishTransaction', this);
|
||||
}
|
||||
|
||||
if (this._sampled !== true) {
|
||||
// At this point if `sampled !== true` we want to discard the transaction.
|
||||
DEBUG_BUILD && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.');
|
||||
|
||||
if (client) {
|
||||
client.recordDroppedEvent('sample_rate', 'transaction');
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const finishedSpans = this.spanRecorder
|
||||
? // eslint-disable-next-line deprecation/deprecation
|
||||
this.spanRecorder.spans.filter(span => span !== this && spanToJSON(span).timestamp)
|
||||
: [];
|
||||
|
||||
if (this._trimEnd && finishedSpans.length > 0) {
|
||||
const endTimes = finishedSpans.map(span => spanToJSON(span).timestamp).filter(Boolean) ;
|
||||
this._endTime = endTimes.reduce((prev, current) => {
|
||||
return prev > current ? prev : current;
|
||||
});
|
||||
}
|
||||
|
||||
const { scope: capturedSpanScope, isolationScope: capturedSpanIsolationScope } = getCapturedScopesOnSpan(this);
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { metadata } = this;
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const { source } = metadata;
|
||||
|
||||
const transaction = {
|
||||
contexts: {
|
||||
...this._contexts,
|
||||
// We don't want to override trace context
|
||||
trace: spanToTraceContext(this),
|
||||
},
|
||||
// TODO: Pass spans serialized via `spanToJSON()` here instead in v8.
|
||||
spans: finishedSpans,
|
||||
start_timestamp: this._startTime,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
tags: this.tags,
|
||||
timestamp: this._endTime,
|
||||
transaction: this._name,
|
||||
type: 'transaction',
|
||||
sdkProcessingMetadata: {
|
||||
...metadata,
|
||||
capturedSpanScope,
|
||||
capturedSpanIsolationScope,
|
||||
...dropUndefinedKeys({
|
||||
dynamicSamplingContext: getDynamicSamplingContextFromSpan(this),
|
||||
}),
|
||||
},
|
||||
_metrics_summary: getMetricSummaryJsonForSpan(this),
|
||||
...(source && {
|
||||
transaction_info: {
|
||||
source,
|
||||
},
|
||||
}),
|
||||
};
|
||||
|
||||
const hasMeasurements = Object.keys(this._measurements).length > 0;
|
||||
|
||||
if (hasMeasurements) {
|
||||
DEBUG_BUILD &&
|
||||
logger.log(
|
||||
'[Measurements] Adding measurements to transaction',
|
||||
JSON.stringify(this._measurements, undefined, 2),
|
||||
);
|
||||
transaction.measurements = this._measurements;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
DEBUG_BUILD && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this._name}.`);
|
||||
|
||||
return transaction;
|
||||
}
|
||||
}
|
||||
|
||||
export { Transaction };
|
||||
//# sourceMappingURL=transaction.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/transaction.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/transaction.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
35
node_modules/@sentry/core/esm/tracing/utils.js
generated
vendored
Normal file
35
node_modules/@sentry/core/esm/tracing/utils.js
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
import { extractTraceparentData as extractTraceparentData$1 } from '@sentry/utils';
|
||||
export { stripUrlQueryAndFragment } from '@sentry/utils';
|
||||
import { getCurrentHub } from '../hub.js';
|
||||
|
||||
/**
|
||||
* Grabs active transaction off scope.
|
||||
*
|
||||
* @deprecated You should not rely on the transaction, but just use `startSpan()` APIs instead.
|
||||
*/
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
function getActiveTransaction(maybeHub) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const hub = maybeHub || getCurrentHub();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
const scope = hub.getScope();
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return scope.getTransaction() ;
|
||||
}
|
||||
|
||||
/**
|
||||
* The `extractTraceparentData` function and `TRACEPARENT_REGEXP` constant used
|
||||
* to be declared in this file. It was later moved into `@sentry/utils` as part of a
|
||||
* move to remove `@sentry/tracing` dependencies from `@sentry/node` (`extractTraceparentData`
|
||||
* is the only tracing function used by `@sentry/node`).
|
||||
*
|
||||
* These exports are kept here for backwards compatability's sake.
|
||||
*
|
||||
* See https://github.com/getsentry/sentry-javascript/issues/4642 for more details.
|
||||
*
|
||||
* @deprecated Import this function from `@sentry/utils` instead
|
||||
*/
|
||||
const extractTraceparentData = extractTraceparentData$1;
|
||||
|
||||
export { extractTraceparentData, getActiveTransaction };
|
||||
//# sourceMappingURL=utils.js.map
|
||||
1
node_modules/@sentry/core/esm/tracing/utils.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/tracing/utils.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"utils.js","sources":["../../../src/tracing/utils.ts"],"sourcesContent":["import type { Transaction } from '@sentry/types';\nimport { extractTraceparentData as _extractTraceparentData } from '@sentry/utils';\n\nimport type { Hub } from '../hub';\nimport { getCurrentHub } from '../hub';\n\n/**\n * Grabs active transaction off scope.\n *\n * @deprecated You should not rely on the transaction, but just use `startSpan()` APIs instead.\n */\n// eslint-disable-next-line deprecation/deprecation\nexport function getActiveTransaction<T extends Transaction>(maybeHub?: Hub): T | undefined {\n // eslint-disable-next-line deprecation/deprecation\n const hub = maybeHub || getCurrentHub();\n // eslint-disable-next-line deprecation/deprecation\n const scope = hub.getScope();\n // eslint-disable-next-line deprecation/deprecation\n return scope.getTransaction() as T | undefined;\n}\n\n// so it can be used in manual instrumentation without necessitating a hard dependency on @sentry/utils\nexport { stripUrlQueryAndFragment } from '@sentry/utils';\n\n/**\n * The `extractTraceparentData` function and `TRACEPARENT_REGEXP` constant used\n * to be declared in this file. It was later moved into `@sentry/utils` as part of a\n * move to remove `@sentry/tracing` dependencies from `@sentry/node` (`extractTraceparentData`\n * is the only tracing function used by `@sentry/node`).\n *\n * These exports are kept here for backwards compatability's sake.\n *\n * See https://github.com/getsentry/sentry-javascript/issues/4642 for more details.\n *\n * @deprecated Import this function from `@sentry/utils` instead\n */\nexport const extractTraceparentData = _extractTraceparentData;\n"],"names":["_extractTraceparentData"],"mappings":";;;;AAMA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,oBAAoB,CAAwB,QAAQ,EAAuB;AAC3F;AACA,EAAE,MAAM,GAAI,GAAE,YAAY,aAAa,EAAE,CAAA;AACzC;AACA,EAAE,MAAM,KAAM,GAAE,GAAG,CAAC,QAAQ,EAAE,CAAA;AAC9B;AACA,EAAE,OAAO,KAAK,CAAC,cAAc,EAAG,EAAA;AAChC,CAAA;AAIA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,MAAM,sBAAuB,GAAEA;;;;"}
|
||||
102
node_modules/@sentry/core/esm/transports/base.js
generated
vendored
Normal file
102
node_modules/@sentry/core/esm/transports/base.js
generated
vendored
Normal file
@@ -0,0 +1,102 @@
|
||||
import { makePromiseBuffer, forEachEnvelopeItem, envelopeItemTypeToDataCategory, isRateLimited, resolvedSyncPromise, createEnvelope, SentryError, logger, serializeEnvelope, updateRateLimits } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
|
||||
const DEFAULT_TRANSPORT_BUFFER_SIZE = 30;
|
||||
|
||||
/**
|
||||
* Creates an instance of a Sentry `Transport`
|
||||
*
|
||||
* @param options
|
||||
* @param makeRequest
|
||||
*/
|
||||
function createTransport(
|
||||
options,
|
||||
makeRequest,
|
||||
buffer = makePromiseBuffer(
|
||||
options.bufferSize || DEFAULT_TRANSPORT_BUFFER_SIZE,
|
||||
),
|
||||
) {
|
||||
let rateLimits = {};
|
||||
const flush = (timeout) => buffer.drain(timeout);
|
||||
|
||||
function send(envelope) {
|
||||
const filteredEnvelopeItems = [];
|
||||
|
||||
// Drop rate limited items from envelope
|
||||
forEachEnvelopeItem(envelope, (item, type) => {
|
||||
const dataCategory = envelopeItemTypeToDataCategory(type);
|
||||
if (isRateLimited(rateLimits, dataCategory)) {
|
||||
const event = getEventForEnvelopeItem(item, type);
|
||||
options.recordDroppedEvent('ratelimit_backoff', dataCategory, event);
|
||||
} else {
|
||||
filteredEnvelopeItems.push(item);
|
||||
}
|
||||
});
|
||||
|
||||
// Skip sending if envelope is empty after filtering out rate limited events
|
||||
if (filteredEnvelopeItems.length === 0) {
|
||||
return resolvedSyncPromise();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
const filteredEnvelope = createEnvelope(envelope[0], filteredEnvelopeItems );
|
||||
|
||||
// Creates client report for each item in an envelope
|
||||
const recordEnvelopeLoss = (reason) => {
|
||||
forEachEnvelopeItem(filteredEnvelope, (item, type) => {
|
||||
const event = getEventForEnvelopeItem(item, type);
|
||||
options.recordDroppedEvent(reason, envelopeItemTypeToDataCategory(type), event);
|
||||
});
|
||||
};
|
||||
|
||||
const requestTask = () =>
|
||||
makeRequest({ body: serializeEnvelope(filteredEnvelope, options.textEncoder) }).then(
|
||||
response => {
|
||||
// We don't want to throw on NOK responses, but we want to at least log them
|
||||
if (response.statusCode !== undefined && (response.statusCode < 200 || response.statusCode >= 300)) {
|
||||
DEBUG_BUILD && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`);
|
||||
}
|
||||
|
||||
rateLimits = updateRateLimits(rateLimits, response);
|
||||
return response;
|
||||
},
|
||||
error => {
|
||||
recordEnvelopeLoss('network_error');
|
||||
throw error;
|
||||
},
|
||||
);
|
||||
|
||||
return buffer.add(requestTask).then(
|
||||
result => result,
|
||||
error => {
|
||||
if (error instanceof SentryError) {
|
||||
DEBUG_BUILD && logger.error('Skipped sending event because buffer is full.');
|
||||
recordEnvelopeLoss('queue_overflow');
|
||||
return resolvedSyncPromise();
|
||||
} else {
|
||||
throw error;
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// We use this to identifify if the transport is the base transport
|
||||
// TODO (v8): Remove this again as we'll no longer need it
|
||||
send.__sentry__baseTransport__ = true;
|
||||
|
||||
return {
|
||||
send,
|
||||
flush,
|
||||
};
|
||||
}
|
||||
|
||||
function getEventForEnvelopeItem(item, type) {
|
||||
if (type !== 'event' && type !== 'transaction') {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return Array.isArray(item) ? (item )[1] : undefined;
|
||||
}
|
||||
|
||||
export { DEFAULT_TRANSPORT_BUFFER_SIZE, createTransport };
|
||||
//# sourceMappingURL=base.js.map
|
||||
1
node_modules/@sentry/core/esm/transports/base.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/transports/base.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
142
node_modules/@sentry/core/esm/transports/multiplexed.js
generated
vendored
Normal file
142
node_modules/@sentry/core/esm/transports/multiplexed.js
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
import { createEnvelope, dsnFromString, forEachEnvelopeItem } from '@sentry/utils';
|
||||
import { getEnvelopeEndpointWithUrlEncodedAuth } from '../api.js';
|
||||
|
||||
/**
|
||||
* Gets an event from an envelope.
|
||||
*
|
||||
* This is only exported for use in the tests
|
||||
*/
|
||||
function eventFromEnvelope(env, types) {
|
||||
let event;
|
||||
|
||||
forEachEnvelopeItem(env, (item, type) => {
|
||||
if (types.includes(type)) {
|
||||
event = Array.isArray(item) ? (item )[1] : undefined;
|
||||
}
|
||||
// bail out if we found an event
|
||||
return !!event;
|
||||
});
|
||||
|
||||
return event;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a transport that overrides the release on all events.
|
||||
*/
|
||||
function makeOverrideReleaseTransport(
|
||||
createTransport,
|
||||
release,
|
||||
) {
|
||||
return options => {
|
||||
const transport = createTransport(options);
|
||||
|
||||
return {
|
||||
...transport,
|
||||
send: async (envelope) => {
|
||||
const event = eventFromEnvelope(envelope, ['event', 'transaction', 'profile', 'replay_event']);
|
||||
|
||||
if (event) {
|
||||
event.release = release;
|
||||
}
|
||||
return transport.send(envelope);
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/** Overrides the DSN in the envelope header */
|
||||
function overrideDsn(envelope, dsn) {
|
||||
return createEnvelope(
|
||||
dsn
|
||||
? {
|
||||
...envelope[0],
|
||||
dsn,
|
||||
}
|
||||
: envelope[0],
|
||||
envelope[1],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a transport that can send events to different DSNs depending on the envelope contents.
|
||||
*/
|
||||
function makeMultiplexedTransport(
|
||||
createTransport,
|
||||
matcher,
|
||||
) {
|
||||
return options => {
|
||||
const fallbackTransport = createTransport(options);
|
||||
const otherTransports = new Map();
|
||||
|
||||
function getTransport(dsn, release) {
|
||||
// We create a transport for every unique dsn/release combination as there may be code from multiple releases in
|
||||
// use at the same time
|
||||
const key = release ? `${dsn}:${release}` : dsn;
|
||||
|
||||
let transport = otherTransports.get(key);
|
||||
|
||||
if (!transport) {
|
||||
const validatedDsn = dsnFromString(dsn);
|
||||
if (!validatedDsn) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const url = getEnvelopeEndpointWithUrlEncodedAuth(validatedDsn, options.tunnel);
|
||||
|
||||
transport = release
|
||||
? makeOverrideReleaseTransport(createTransport, release)({ ...options, url })
|
||||
: createTransport({ ...options, url });
|
||||
|
||||
otherTransports.set(key, transport);
|
||||
}
|
||||
|
||||
return [dsn, transport];
|
||||
}
|
||||
|
||||
async function send(envelope) {
|
||||
function getEvent(types) {
|
||||
const eventTypes = types && types.length ? types : ['event'];
|
||||
return eventFromEnvelope(envelope, eventTypes);
|
||||
}
|
||||
|
||||
const transports = matcher({ envelope, getEvent })
|
||||
.map(result => {
|
||||
if (typeof result === 'string') {
|
||||
return getTransport(result, undefined);
|
||||
} else {
|
||||
return getTransport(result.dsn, result.release);
|
||||
}
|
||||
})
|
||||
.filter((t) => !!t);
|
||||
|
||||
// If we have no transports to send to, use the fallback transport
|
||||
if (transports.length === 0) {
|
||||
// Don't override the DSN in the header for the fallback transport. '' is falsy
|
||||
transports.push(['', fallbackTransport]);
|
||||
}
|
||||
|
||||
const results = await Promise.all(
|
||||
transports.map(([dsn, transport]) => transport.send(overrideDsn(envelope, dsn))),
|
||||
);
|
||||
|
||||
return results[0];
|
||||
}
|
||||
|
||||
async function flush(timeout) {
|
||||
const promises = [await fallbackTransport.flush(timeout)];
|
||||
for (const [, transport] of otherTransports) {
|
||||
promises.push(await transport.flush(timeout));
|
||||
}
|
||||
|
||||
return promises.every(r => r);
|
||||
}
|
||||
|
||||
return {
|
||||
send,
|
||||
flush,
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export { eventFromEnvelope, makeMultiplexedTransport };
|
||||
//# sourceMappingURL=multiplexed.js.map
|
||||
1
node_modules/@sentry/core/esm/transports/multiplexed.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/transports/multiplexed.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
123
node_modules/@sentry/core/esm/transports/offline.js
generated
vendored
Normal file
123
node_modules/@sentry/core/esm/transports/offline.js
generated
vendored
Normal file
@@ -0,0 +1,123 @@
|
||||
import { parseRetryAfterHeader, logger, envelopeContainsItemType } from '@sentry/utils';
|
||||
import { DEBUG_BUILD } from '../debug-build.js';
|
||||
|
||||
const MIN_DELAY = 100; // 100 ms
|
||||
const START_DELAY = 5000; // 5 seconds
|
||||
const MAX_DELAY = 3.6e6; // 1 hour
|
||||
|
||||
function log(msg, error) {
|
||||
DEBUG_BUILD && logger.info(`[Offline]: ${msg}`, error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps a transport and stores and retries events when they fail to send.
|
||||
*
|
||||
* @param createTransport The transport to wrap.
|
||||
*/
|
||||
function makeOfflineTransport(
|
||||
createTransport,
|
||||
) {
|
||||
return options => {
|
||||
const transport = createTransport(options);
|
||||
const store = options.createStore ? options.createStore(options) : undefined;
|
||||
|
||||
let retryDelay = START_DELAY;
|
||||
let flushTimer;
|
||||
|
||||
function shouldQueue(env, error, retryDelay) {
|
||||
// We don't queue Session Replay envelopes because they are:
|
||||
// - Ordered and Replay relies on the response status to know when they're successfully sent.
|
||||
// - Likely to fill the queue quickly and block other events from being sent.
|
||||
// We also want to drop client reports because they can be generated when we retry sending events while offline.
|
||||
if (envelopeContainsItemType(env, ['replay_event', 'replay_recording', 'client_report'])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (options.shouldStore) {
|
||||
return options.shouldStore(env, error, retryDelay);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function flushIn(delay) {
|
||||
if (!store) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (flushTimer) {
|
||||
clearTimeout(flushTimer );
|
||||
}
|
||||
|
||||
flushTimer = setTimeout(async () => {
|
||||
flushTimer = undefined;
|
||||
|
||||
const found = await store.pop();
|
||||
if (found) {
|
||||
log('Attempting to send previously queued event');
|
||||
void send(found).catch(e => {
|
||||
log('Failed to retry sending', e);
|
||||
});
|
||||
}
|
||||
}, delay) ;
|
||||
|
||||
// We need to unref the timer in node.js, otherwise the node process never exit.
|
||||
if (typeof flushTimer !== 'number' && flushTimer.unref) {
|
||||
flushTimer.unref();
|
||||
}
|
||||
}
|
||||
|
||||
function flushWithBackOff() {
|
||||
if (flushTimer) {
|
||||
return;
|
||||
}
|
||||
|
||||
flushIn(retryDelay);
|
||||
|
||||
retryDelay = Math.min(retryDelay * 2, MAX_DELAY);
|
||||
}
|
||||
|
||||
async function send(envelope) {
|
||||
try {
|
||||
const result = await transport.send(envelope);
|
||||
|
||||
let delay = MIN_DELAY;
|
||||
|
||||
if (result) {
|
||||
// If there's a retry-after header, use that as the next delay.
|
||||
if (result.headers && result.headers['retry-after']) {
|
||||
delay = parseRetryAfterHeader(result.headers['retry-after']);
|
||||
} // If we have a server error, return now so we don't flush the queue.
|
||||
else if ((result.statusCode || 0) >= 400) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
flushIn(delay);
|
||||
retryDelay = START_DELAY;
|
||||
return result;
|
||||
} catch (e) {
|
||||
if (store && (await shouldQueue(envelope, e , retryDelay))) {
|
||||
await store.insert(envelope);
|
||||
flushWithBackOff();
|
||||
log('Error sending. Event queued', e );
|
||||
return {};
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (options.flushAtStartup) {
|
||||
flushWithBackOff();
|
||||
}
|
||||
|
||||
return {
|
||||
send,
|
||||
flush: t => transport.flush(t),
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export { MIN_DELAY, START_DELAY, makeOfflineTransport };
|
||||
//# sourceMappingURL=offline.js.map
|
||||
1
node_modules/@sentry/core/esm/transports/offline.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/transports/offline.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
189
node_modules/@sentry/core/esm/utils/applyScopeDataToEvent.js
generated
vendored
Normal file
189
node_modules/@sentry/core/esm/utils/applyScopeDataToEvent.js
generated
vendored
Normal file
@@ -0,0 +1,189 @@
|
||||
import { dropUndefinedKeys, arrayify } from '@sentry/utils';
|
||||
import { getDynamicSamplingContextFromSpan } from '../tracing/dynamicSamplingContext.js';
|
||||
import { getRootSpan } from './getRootSpan.js';
|
||||
import { spanToTraceContext, spanToJSON } from './spanUtils.js';
|
||||
|
||||
/**
|
||||
* Applies data from the scope to the event and runs all event processors on it.
|
||||
*/
|
||||
function applyScopeDataToEvent(event, data) {
|
||||
const { fingerprint, span, breadcrumbs, sdkProcessingMetadata } = data;
|
||||
|
||||
// Apply general data
|
||||
applyDataToEvent(event, data);
|
||||
|
||||
// We want to set the trace context for normal events only if there isn't already
|
||||
// a trace context on the event. There is a product feature in place where we link
|
||||
// errors with transaction and it relies on that.
|
||||
if (span) {
|
||||
applySpanToEvent(event, span);
|
||||
}
|
||||
|
||||
applyFingerprintToEvent(event, fingerprint);
|
||||
applyBreadcrumbsToEvent(event, breadcrumbs);
|
||||
applySdkMetadataToEvent(event, sdkProcessingMetadata);
|
||||
}
|
||||
|
||||
/** Merge data of two scopes together. */
|
||||
function mergeScopeData(data, mergeData) {
|
||||
const {
|
||||
extra,
|
||||
tags,
|
||||
user,
|
||||
contexts,
|
||||
level,
|
||||
sdkProcessingMetadata,
|
||||
breadcrumbs,
|
||||
fingerprint,
|
||||
eventProcessors,
|
||||
attachments,
|
||||
propagationContext,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transactionName,
|
||||
span,
|
||||
} = mergeData;
|
||||
|
||||
mergeAndOverwriteScopeData(data, 'extra', extra);
|
||||
mergeAndOverwriteScopeData(data, 'tags', tags);
|
||||
mergeAndOverwriteScopeData(data, 'user', user);
|
||||
mergeAndOverwriteScopeData(data, 'contexts', contexts);
|
||||
mergeAndOverwriteScopeData(data, 'sdkProcessingMetadata', sdkProcessingMetadata);
|
||||
|
||||
if (level) {
|
||||
data.level = level;
|
||||
}
|
||||
|
||||
if (transactionName) {
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
data.transactionName = transactionName;
|
||||
}
|
||||
|
||||
if (span) {
|
||||
data.span = span;
|
||||
}
|
||||
|
||||
if (breadcrumbs.length) {
|
||||
data.breadcrumbs = [...data.breadcrumbs, ...breadcrumbs];
|
||||
}
|
||||
|
||||
if (fingerprint.length) {
|
||||
data.fingerprint = [...data.fingerprint, ...fingerprint];
|
||||
}
|
||||
|
||||
if (eventProcessors.length) {
|
||||
data.eventProcessors = [...data.eventProcessors, ...eventProcessors];
|
||||
}
|
||||
|
||||
if (attachments.length) {
|
||||
data.attachments = [...data.attachments, ...attachments];
|
||||
}
|
||||
|
||||
data.propagationContext = { ...data.propagationContext, ...propagationContext };
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges certain scope data. Undefined values will overwrite any existing values.
|
||||
* Exported only for tests.
|
||||
*/
|
||||
function mergeAndOverwriteScopeData
|
||||
|
||||
(data, prop, mergeVal) {
|
||||
if (mergeVal && Object.keys(mergeVal).length) {
|
||||
// Clone object
|
||||
data[prop] = { ...data[prop] };
|
||||
for (const key in mergeVal) {
|
||||
if (Object.prototype.hasOwnProperty.call(mergeVal, key)) {
|
||||
data[prop][key] = mergeVal[key];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function applyDataToEvent(event, data) {
|
||||
const {
|
||||
extra,
|
||||
tags,
|
||||
user,
|
||||
contexts,
|
||||
level,
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
transactionName,
|
||||
} = data;
|
||||
|
||||
const cleanedExtra = dropUndefinedKeys(extra);
|
||||
if (cleanedExtra && Object.keys(cleanedExtra).length) {
|
||||
event.extra = { ...cleanedExtra, ...event.extra };
|
||||
}
|
||||
|
||||
const cleanedTags = dropUndefinedKeys(tags);
|
||||
if (cleanedTags && Object.keys(cleanedTags).length) {
|
||||
event.tags = { ...cleanedTags, ...event.tags };
|
||||
}
|
||||
|
||||
const cleanedUser = dropUndefinedKeys(user);
|
||||
if (cleanedUser && Object.keys(cleanedUser).length) {
|
||||
event.user = { ...cleanedUser, ...event.user };
|
||||
}
|
||||
|
||||
const cleanedContexts = dropUndefinedKeys(contexts);
|
||||
if (cleanedContexts && Object.keys(cleanedContexts).length) {
|
||||
event.contexts = { ...cleanedContexts, ...event.contexts };
|
||||
}
|
||||
|
||||
if (level) {
|
||||
event.level = level;
|
||||
}
|
||||
|
||||
if (transactionName) {
|
||||
event.transaction = transactionName;
|
||||
}
|
||||
}
|
||||
|
||||
function applyBreadcrumbsToEvent(event, breadcrumbs) {
|
||||
const mergedBreadcrumbs = [...(event.breadcrumbs || []), ...breadcrumbs];
|
||||
event.breadcrumbs = mergedBreadcrumbs.length ? mergedBreadcrumbs : undefined;
|
||||
}
|
||||
|
||||
function applySdkMetadataToEvent(event, sdkProcessingMetadata) {
|
||||
event.sdkProcessingMetadata = {
|
||||
...event.sdkProcessingMetadata,
|
||||
...sdkProcessingMetadata,
|
||||
};
|
||||
}
|
||||
|
||||
function applySpanToEvent(event, span) {
|
||||
event.contexts = { trace: spanToTraceContext(span), ...event.contexts };
|
||||
const rootSpan = getRootSpan(span);
|
||||
if (rootSpan) {
|
||||
event.sdkProcessingMetadata = {
|
||||
dynamicSamplingContext: getDynamicSamplingContextFromSpan(span),
|
||||
...event.sdkProcessingMetadata,
|
||||
};
|
||||
const transactionName = spanToJSON(rootSpan).description;
|
||||
if (transactionName) {
|
||||
event.tags = { transaction: transactionName, ...event.tags };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies fingerprint from the scope to the event if there's one,
|
||||
* uses message if there's one instead or get rid of empty fingerprint
|
||||
*/
|
||||
function applyFingerprintToEvent(event, fingerprint) {
|
||||
// Make sure it's an array first and we actually have something in place
|
||||
event.fingerprint = event.fingerprint ? arrayify(event.fingerprint) : [];
|
||||
|
||||
// If we have something on the scope, then merge it with event
|
||||
if (fingerprint) {
|
||||
event.fingerprint = event.fingerprint.concat(fingerprint);
|
||||
}
|
||||
|
||||
// If we have no data at all, remove empty array default
|
||||
if (event.fingerprint && !event.fingerprint.length) {
|
||||
delete event.fingerprint;
|
||||
}
|
||||
}
|
||||
|
||||
export { applyScopeDataToEvent, mergeAndOverwriteScopeData, mergeScopeData };
|
||||
//# sourceMappingURL=applyScopeDataToEvent.js.map
|
||||
1
node_modules/@sentry/core/esm/utils/applyScopeDataToEvent.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/utils/applyScopeDataToEvent.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
16
node_modules/@sentry/core/esm/utils/getRootSpan.js
generated
vendored
Normal file
16
node_modules/@sentry/core/esm/utils/getRootSpan.js
generated
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Returns the root span of a given span.
|
||||
*
|
||||
* As long as we use `Transaction`s internally, the returned root span
|
||||
* will be a `Transaction` but be aware that this might change in the future.
|
||||
*
|
||||
* If the given span has no root span or transaction, `undefined` is returned.
|
||||
*/
|
||||
function getRootSpan(span) {
|
||||
// TODO (v8): Remove this check and just return span
|
||||
// eslint-disable-next-line deprecation/deprecation
|
||||
return span.transaction;
|
||||
}
|
||||
|
||||
export { getRootSpan };
|
||||
//# sourceMappingURL=getRootSpan.js.map
|
||||
1
node_modules/@sentry/core/esm/utils/getRootSpan.js.map
generated
vendored
Normal file
1
node_modules/@sentry/core/esm/utils/getRootSpan.js.map
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{"version":3,"file":"getRootSpan.js","sources":["../../../src/utils/getRootSpan.ts"],"sourcesContent":["import type { Span } from '@sentry/types';\n\n/**\n * Returns the root span of a given span.\n *\n * As long as we use `Transaction`s internally, the returned root span\n * will be a `Transaction` but be aware that this might change in the future.\n *\n * If the given span has no root span or transaction, `undefined` is returned.\n */\nexport function getRootSpan(span: Span): Span | undefined {\n // TODO (v8): Remove this check and just return span\n // eslint-disable-next-line deprecation/deprecation\n return span.transaction;\n}\n"],"names":[],"mappings":"AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACO,SAAS,WAAW,CAAC,IAAI,EAA0B;AAC1D;AACA;AACA,EAAE,OAAO,IAAI,CAAC,WAAW,CAAA;AACzB;;;;"}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user