123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691 |
- Object.defineProperty(exports, '__esModule', { value: true });
- const utils = require('@sentry/utils');
- const eventProcessors = require('./eventProcessors.js');
- const session = require('./session.js');
- const applyScopeDataToEvent = require('./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) {
- 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.
- * @deprecated Use extra or tags instead.
- */
- 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 (utils.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: utils.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.applyScopeDataToEvent(event, this.getScopeData());
- // TODO (v8): Update this order to be: Global > Client > Scope
- const eventProcessors$1 = [
- ...additionalEventProcessors,
- // eslint-disable-next-line deprecation/deprecation
- ...eventProcessors.getGlobalEventProcessors(),
- ...this._eventProcessors,
- ];
- return eventProcessors.notifyEventProcessors(eventProcessors$1, 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 : utils.uuid4();
- if (!this._client) {
- utils.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 : utils.uuid4();
- if (!this._client) {
- utils.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 : utils.uuid4();
- if (!this._client) {
- utils.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: utils.uuid4(),
- spanId: utils.uuid4().substring(16),
- };
- }
- exports.Scope = Scope;
- exports.getGlobalScope = getGlobalScope;
- exports.setGlobalScope = setGlobalScope;
- //# sourceMappingURL=scope.js.map
|