From 9c7826187c3cbc737768a7bc1a5cd2d5aa01783b Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 10:45:07 -0500 Subject: [PATCH 01/17] ref(core): Remove backend This patch removes the backend from the core. It turns `eventFromException` and `eventFromMessage` into abstract methods on the client class (so we can remove the `SentryError` calls) and moves the transport setup from the backend into the client. --- packages/core/src/basebackend.ts | 126 ------------------------------- packages/core/src/baseclient.ts | 91 +++++++++++++--------- packages/core/src/index.ts | 1 - packages/types/src/client.ts | 6 ++ 4 files changed, 61 insertions(+), 163 deletions(-) delete mode 100644 packages/core/src/basebackend.ts diff --git a/packages/core/src/basebackend.ts b/packages/core/src/basebackend.ts deleted file mode 100644 index ffdcd22af6c0..000000000000 --- a/packages/core/src/basebackend.ts +++ /dev/null @@ -1,126 +0,0 @@ -import { Event, EventHint, Options, Session, SeverityLevel, Transport } from '@sentry/types'; -import { logger, SentryError } from '@sentry/utils'; - -import { NoopTransport } from './transports/noop'; - -/** - * Internal platform-dependent Sentry SDK Backend. - * - * While {@link Client} contains business logic specific to an SDK, the - * Backend offers platform specific implementations for low-level operations. - * These are persisting and loading information, sending events, and hooking - * into the environment. - * - * Backends receive a handle to the Client in their constructor. When a - * Backend automatically generates events, it must pass them to - * the Client for validation and processing first. - * - * Usually, the Client will be of corresponding type, e.g. NodeBackend - * receives NodeClient. However, higher-level SDKs can choose to instantiate - * multiple Backends and delegate tasks between them. In this case, an event - * generated by one backend might very well be sent by another one. - * - * The client also provides access to options via {@link Client.getOptions}. - * @hidden - */ -export interface Backend { - /** Creates a {@link Event} from an exception. */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any - eventFromException(exception: any, hint?: EventHint): PromiseLike; - - /** Creates a {@link Event} from a plain message. */ - eventFromMessage(message: string, level?: SeverityLevel, hint?: EventHint): PromiseLike; - - /** Submits the event to Sentry */ - sendEvent(event: Event): void; - - /** Submits the session to Sentry */ - sendSession(session: Session): void; - - /** - * Returns the transport that is used by the backend. - * Please note that the transport gets lazy initialized so it will only be there once the first event has been sent. - * - * @returns The transport. - */ - getTransport(): Transport; -} - -/** - * A class object that can instantiate Backend objects. - * @hidden - */ -export type BackendClass = new (options: O) => B; - -/** - * This is the base implemention of a Backend. - * @hidden - */ -export abstract class BaseBackend implements Backend { - /** Options passed to the SDK. */ - protected readonly _options: O; - - /** Cached transport used internally. */ - protected _transport: Transport; - - /** Creates a new backend instance. */ - public constructor(options: O) { - this._options = options; - if (!this._options.dsn) { - logger.warn('No DSN provided, backend will not do anything.'); - } - this._transport = this._setupTransport(); - } - - /** - * @inheritDoc - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types - public eventFromException(_exception: any, _hint?: EventHint): PromiseLike { - throw new SentryError('Backend has to implement `eventFromException` method'); - } - - /** - * @inheritDoc - */ - public eventFromMessage(_message: string, _level?: SeverityLevel, _hint?: EventHint): PromiseLike { - throw new SentryError('Backend has to implement `eventFromMessage` method'); - } - - /** - * @inheritDoc - */ - public sendEvent(event: Event): void { - void this._transport.sendEvent(event).then(null, reason => { - logger.error(`Error while sending event: ${reason}`); - }); - } - - /** - * @inheritDoc - */ - public sendSession(session: Session): void { - if (!this._transport.sendSession) { - logger.warn("Dropping session because custom transport doesn't implement sendSession"); - return; - } - - void this._transport.sendSession(session).then(null, reason => { - logger.error(`Error while sending session: ${reason}`); - }); - } - - /** - * @inheritDoc - */ - public getTransport(): Transport { - return this._transport; - } - - /** - * Sets up the transport so it can be used later to send requests. - */ - protected _setupTransport(): Transport { - return new NoopTransport(); - } -} diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 8ff1bb60e739..795c561e8c4a 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -27,8 +27,8 @@ import { uuid4, } from '@sentry/utils'; -import { Backend, BackendClass } from './basebackend'; import { IntegrationIndex, setupIntegrations } from './integration'; +import { NoopTransport } from './transports/noop'; const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; @@ -64,14 +64,7 @@ const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been ca * // ... * } */ -export abstract class BaseClient implements Client { - /** - * The backend used to physically interact in the environment. Usually, this - * will correspond to the client. When composing SDKs, however, the Backend - * from the root SDK will be used. - */ - protected readonly _backend: B; - +export abstract class BaseClient implements Client { /** Options passed to the SDK. */ protected readonly _options: O; @@ -84,19 +77,23 @@ export abstract class BaseClient implement /** Number of calls being processed */ protected _numProcessing: number = 0; + /** Cached transport used internally. */ + protected _transport: Transport; + /** * Initializes this client instance. * * @param backendClass A constructor function to create the backend. * @param options Options for the client. */ - protected constructor(backendClass: BackendClass, options: O) { - this._backend = new backendClass(options); + protected constructor(options: O) { this._options = options; if (options.dsn) { this._dsn = new Dsn(options.dsn); } + + this._transport = this._setupTransport(); } /** @@ -113,8 +110,7 @@ export abstract class BaseClient implement let eventId: string | undefined = hint && hint.event_id; this._process( - this._getBackend() - .eventFromException(exception, hint) + this._eventFromException(exception, hint) .then(event => this._captureEvent(event, hint, scope)) .then(result => { eventId = result; @@ -131,8 +127,8 @@ export abstract class BaseClient implement let eventId: string | undefined = hint && hint.event_id; const promisedEvent = isPrimitive(message) - ? this._getBackend().eventFromMessage(String(message), level, hint) - : this._getBackend().eventFromException(message, hint); + ? this._eventFromMessage(String(message), level, hint) + : this._eventFromException(message, hint); this._process( promisedEvent @@ -178,7 +174,7 @@ export abstract class BaseClient implement if (!(typeof session.release === 'string')) { logger.warn('Discarded session because of missing or non-string release'); } else { - this._sendSession(session); + this.sendSession(session); // After sending, we set init false to indicate it's not the first occurrence session.update({ init: false }); } @@ -202,7 +198,7 @@ export abstract class BaseClient implement * @inheritDoc */ public getTransport(): Transport { - return this._getBackend().getTransport(); + return this._transport; } /** @@ -247,6 +243,29 @@ export abstract class BaseClient implement } } + /** + * @inheritDoc + */ + public sendEvent(event: Event): void { + void this._transport.sendEvent(event).then(null, reason => { + logger.error(`Error while sending event: ${reason}`); + }); + } + + /** + * @inheritDoc + */ + public sendSession(session: Session): void { + if (!this._transport.sendSession) { + logger.warn("Dropping session because custom transport doesn't implement sendSession"); + return; + } + + void this._transport.sendSession(session).then(null, reason => { + logger.error(`Error while sending session: ${reason}`); + }); + } + /** Updates existing session based on the provided event */ protected _updateSessionFromEvent(session: Session, event: Event): void { let crashed = false; @@ -280,11 +299,6 @@ export abstract class BaseClient implement } } - /** Deliver captured session to Sentry */ - protected _sendSession(session: Session): void { - this._getBackend().sendSession(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. @@ -315,11 +329,6 @@ export abstract class BaseClient implement }); } - /** Returns the current backend. */ - protected _getBackend(): B { - return this._backend; - } - /** Determines whether this SDK is enabled and a valid Dsn is present. */ protected _isEnabled(): boolean { return this.getOptions().enabled !== false && this._dsn !== undefined; @@ -479,14 +488,6 @@ export abstract class BaseClient implement } } - /** - * Tells the backend to send this event - * @param event The Sentry event to send - */ - protected _sendEvent(event: Event): void { - this._getBackend().sendEvent(event); - } - /** * Processes the event and logs an error in case of rejection * @param event @@ -575,7 +576,7 @@ export abstract class BaseClient implement this._updateSessionFromEvent(session, processedEvent); } - this._sendEvent(processedEvent); + this.sendEvent(processedEvent); return processedEvent; }) .then(null, reason => { @@ -611,6 +612,24 @@ export abstract class BaseClient implement }, ); } + + /** + * Sets up the transport so it can be used later to send requests. + */ + protected _setupTransport(): Transport { + return new NoopTransport(); + } + + /** + * @inheritDoc + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types + protected abstract _eventFromException(_exception: any, _hint?: EventHint): PromiseLike; + + /** + * @inheritDoc + */ + protected abstract _eventFromMessage(_message: string, _level?: SeverityLevel, _hint?: EventHint): PromiseLike; } /** diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 22308a0cb7e8..e264d18f5203 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -25,7 +25,6 @@ export { getReportDialogEndpoint, } from './api'; export { BaseClient } from './baseclient'; -export { BackendClass, BaseBackend } from './basebackend'; export { eventToSentryRequest, sessionToSentryRequest } from './request'; export { initAndBind, ClientClass } from './sdk'; export { NoopTransport } from './transports/noop'; diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index e71a3d2f39c6..96dda52249aa 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -88,4 +88,10 @@ export interface Client { /** This is an internal function to setup all integrations that should run on the client */ setupIntegrations(): void; + + /** Submits the event to Sentry */ + sendEvent(event: Event): void; + + /** Submits the session to Sentry */ + sendSession(session: Session): void; } From 460852204f0dba0c802ddbacbdbf8f34b5a699b3 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 10:53:37 -0500 Subject: [PATCH 02/17] ref(browser): Remove backend --- packages/browser/src/backend.ts | 77 ------------------------------- packages/browser/src/client.ts | 80 ++++++++++++++++++++++++++++++--- packages/browser/src/exports.ts | 3 +- packages/browser/src/sdk.ts | 3 +- packages/core/src/baseclient.ts | 4 +- 5 files changed, 78 insertions(+), 89 deletions(-) delete mode 100644 packages/browser/src/backend.ts diff --git a/packages/browser/src/backend.ts b/packages/browser/src/backend.ts deleted file mode 100644 index 5396a8b3dab6..000000000000 --- a/packages/browser/src/backend.ts +++ /dev/null @@ -1,77 +0,0 @@ -import { BaseBackend } from '@sentry/core'; -import { Event, EventHint, Options, SeverityLevel, Transport } from '@sentry/types'; -import { supportsFetch } from '@sentry/utils'; - -import { eventFromException, eventFromMessage } from './eventbuilder'; -import { FetchTransport, XHRTransport } from './transports'; - -/** - * Configuration options for the Sentry Browser SDK. - * @see BrowserClient for more information. - */ -export interface BrowserOptions extends Options { - /** - * A pattern for error URLs which should exclusively be sent to Sentry. - * This is the opposite of {@link Options.denyUrls}. - * By default, all errors will be sent. - */ - allowUrls?: Array; - - /** - * A pattern for error URLs which should not be sent to Sentry. - * To allow certain errors instead, use {@link Options.allowUrls}. - * By default, all errors will be sent. - */ - denyUrls?: Array; - - /** @deprecated use {@link Options.allowUrls} instead. */ - whitelistUrls?: Array; - - /** @deprecated use {@link Options.denyUrls} instead. */ - blacklistUrls?: Array; -} - -/** - * The Sentry Browser SDK Backend. - * @hidden - */ -export class BrowserBackend extends BaseBackend { - /** - * @inheritDoc - */ - public eventFromException(exception: unknown, hint?: EventHint): PromiseLike { - return eventFromException(this._options, exception, hint); - } - /** - * @inheritDoc - */ - public eventFromMessage(message: string, level: SeverityLevel = 'info', hint?: EventHint): PromiseLike { - return eventFromMessage(this._options, message, level, hint); - } - - /** - * @inheritDoc - */ - protected _setupTransport(): Transport { - if (!this._options.dsn) { - // We return the noop transport here in case there is no Dsn. - return super._setupTransport(); - } - - const transportOptions = { - ...this._options.transportOptions, - dsn: this._options.dsn, - tunnel: this._options.tunnel, - sendClientReports: this._options.sendClientReports, - _metadata: this._options._metadata, - }; - - if (this._options.transport) { - return new this._options.transport(transportOptions); - } - if (supportsFetch()) { - return new FetchTransport(transportOptions); - } - return new XHRTransport(transportOptions); - } -} diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index aeb1539e2a7d..0b82e34c79ae 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -1,10 +1,37 @@ import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; -import { Event, EventHint } from '@sentry/types'; -import { getGlobalObject, logger } from '@sentry/utils'; +import { Event, EventHint, Options, SeverityLevel, Transport } from '@sentry/types'; +import { getGlobalObject, logger, supportsFetch } from '@sentry/utils'; -import { BrowserBackend, BrowserOptions } from './backend'; +import { eventFromException, eventFromMessage } from './eventbuilder'; import { injectReportDialog, ReportDialogOptions } from './helpers'; import { Breadcrumbs } from './integrations'; +import { FetchTransport, XHRTransport } from './transports'; + +/** + * Configuration options for the Sentry Browser SDK. + * @see BrowserClient for more information. + */ +export interface BrowserOptions extends Options { + /** + * A pattern for error URLs which should exclusively be sent to Sentry. + * This is the opposite of {@link Options.denyUrls}. + * By default, all errors will be sent. + */ + allowUrls?: Array; + + /** + * A pattern for error URLs which should not be sent to Sentry. + * To allow certain errors instead, use {@link Options.allowUrls}. + * By default, all errors will be sent. + */ + denyUrls?: Array; + + /** @deprecated use {@link Options.allowUrls} instead. */ + whitelistUrls?: Array; + + /** @deprecated use {@link Options.denyUrls} instead. */ + blacklistUrls?: Array; +} /** * The Sentry Browser SDK Client. @@ -12,7 +39,7 @@ import { Breadcrumbs } from './integrations'; * @see BrowserOptions for documentation on configuration options. * @see SentryClient for usage documentation. */ -export class BrowserClient extends BaseClient { +export class BrowserClient extends BaseClient { /** * Creates a new Browser SDK instance. * @@ -31,7 +58,7 @@ export class BrowserClient extends BaseClient { version: SDK_VERSION, }; - super(BrowserBackend, options); + super(options); } /** @@ -73,6 +100,47 @@ export class BrowserClient extends BaseClient { if (integration) { integration.addSentryBreadcrumb(event); } - super._sendEvent(event); + super.sendEvent(event); + } + + /** + * @inheritDoc + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types + protected _eventFromException(exception: any, hint?: EventHint): PromiseLike { + return eventFromException(this._options, exception, hint); + } + + /** + * @inheritDoc + */ + protected _eventFromMessage(message: string, level: SeverityLevel = 'info', hint?: EventHint): PromiseLike { + return eventFromMessage(this._options, message, level, hint); + } + + /** + * @inheritDoc + */ + protected _setupTransport(): Transport { + if (!this._options.dsn) { + // We return the noop transport here in case there is no Dsn. + return super._setupTransport(); + } + + const transportOptions = { + ...this._options.transportOptions, + dsn: this._options.dsn, + tunnel: this._options.tunnel, + sendClientReports: this._options.sendClientReports, + _metadata: this._options._metadata, + }; + + if (this._options.transport) { + return new this._options.transport(transportOptions); + } + if (supportsFetch()) { + return new FetchTransport(transportOptions); + } + return new XHRTransport(transportOptions); } } diff --git a/packages/browser/src/exports.ts b/packages/browser/src/exports.ts index 60cce87af08a..6c59e838237d 100644 --- a/packages/browser/src/exports.ts +++ b/packages/browser/src/exports.ts @@ -38,8 +38,7 @@ export { withScope, } from '@sentry/core'; -export { BrowserOptions } from './backend'; -export { BrowserClient } from './client'; +export { BrowserClient, BrowserOptions } from './client'; export { injectReportDialog, ReportDialogOptions } from './helpers'; export { eventFromException, eventFromMessage } from './eventbuilder'; export { defaultIntegrations, forceLoad, init, lastEventId, onLoad, showReportDialog, flush, close, wrap } from './sdk'; diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index c980d986d3b3..c83eecffa028 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -1,8 +1,7 @@ import { getCurrentHub, initAndBind, Integrations as CoreIntegrations } from '@sentry/core'; import { addInstrumentationHandler, getGlobalObject, logger, resolvedSyncPromise } from '@sentry/utils'; -import { BrowserOptions } from './backend'; -import { BrowserClient } from './client'; +import { BrowserClient, BrowserOptions } from './client'; import { ReportDialogOptions, wrap as internalWrap } from './helpers'; import { Breadcrumbs, Dedupe, GlobalHandlers, LinkedErrors, TryCatch, UserAgent } from './integrations'; diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 795c561e8c4a..d8f939d9cca8 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -624,12 +624,12 @@ export abstract class BaseClient implements Client { * @inheritDoc */ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types - protected abstract _eventFromException(_exception: any, _hint?: EventHint): PromiseLike; + protected abstract _eventFromException(exception: any, hint?: EventHint): PromiseLike; /** * @inheritDoc */ - protected abstract _eventFromMessage(_message: string, _level?: SeverityLevel, _hint?: EventHint): PromiseLike; + protected abstract _eventFromMessage(message: string, level?: SeverityLevel, hint?: EventHint): PromiseLike; } /** From 566f55f215ec10419f3ee228fee2c7bd26d3fb6e Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 11:52:36 -0500 Subject: [PATCH 03/17] ref(node): Remove backend --- packages/node/src/backend.ts | 58 ------------------------------------ packages/node/src/client.ts | 56 ++++++++++++++++++++++++++++++---- 2 files changed, 51 insertions(+), 63 deletions(-) delete mode 100644 packages/node/src/backend.ts diff --git a/packages/node/src/backend.ts b/packages/node/src/backend.ts deleted file mode 100644 index c18dd3aaafd9..000000000000 --- a/packages/node/src/backend.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { BaseBackend } from '@sentry/core'; -import { Event, EventHint, SeverityLevel, Transport, TransportOptions } from '@sentry/types'; -import { Dsn } from '@sentry/utils'; - -import { eventFromException, eventFromMessage } from './eventbuilder'; -import { HTTPSTransport, HTTPTransport } from './transports'; -import { NodeOptions } from './types'; - -/** - * The Sentry Node SDK Backend. - * @hidden - */ -export class NodeBackend extends BaseBackend { - /** - * @inheritDoc - */ - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types - public eventFromException(exception: any, hint?: EventHint): PromiseLike { - return eventFromException(this._options, exception, hint); - } - - /** - * @inheritDoc - */ - public eventFromMessage(message: string, level: SeverityLevel = 'info', hint?: EventHint): PromiseLike { - return eventFromMessage(this._options, message, level, hint); - } - - /** - * @inheritDoc - */ - protected _setupTransport(): Transport { - if (!this._options.dsn) { - // We return the noop transport here in case there is no Dsn. - return super._setupTransport(); - } - - const dsn = new Dsn(this._options.dsn); - - const transportOptions: TransportOptions = { - ...this._options.transportOptions, - ...(this._options.httpProxy && { httpProxy: this._options.httpProxy }), - ...(this._options.httpsProxy && { httpsProxy: this._options.httpsProxy }), - ...(this._options.caCerts && { caCerts: this._options.caCerts }), - dsn: this._options.dsn, - tunnel: this._options.tunnel, - _metadata: this._options._metadata, - }; - - if (this._options.transport) { - return new this._options.transport(transportOptions); - } - if (dsn.protocol === 'http') { - return new HTTPTransport(transportOptions); - } - return new HTTPSTransport(transportOptions); - } -} diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index c5f19ed611d0..e50a4b435d53 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -1,9 +1,10 @@ import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; import { SessionFlusher } from '@sentry/hub'; -import { Event, EventHint } from '@sentry/types'; -import { logger } from '@sentry/utils'; +import { Event, EventHint, SeverityLevel, Transport, TransportOptions } from '@sentry/types'; +import { Dsn, logger } from '@sentry/utils'; -import { NodeBackend } from './backend'; +import { eventFromException, eventFromMessage } from './eventbuilder'; +import { HTTPSTransport, HTTPTransport } from './transports'; import { NodeOptions } from './types'; /** @@ -12,7 +13,7 @@ import { NodeOptions } from './types'; * @see NodeOptions for documentation on configuration options. * @see SentryClient for usage documentation. */ -export class NodeClient extends BaseClient { +export class NodeClient extends BaseClient { protected _sessionFlusher: SessionFlusher | undefined; /** @@ -32,7 +33,7 @@ export class NodeClient extends BaseClient { version: SDK_VERSION, }; - super(NodeBackend, options); + super(options); } /** @@ -127,4 +128,49 @@ export class NodeClient extends BaseClient { this._sessionFlusher.incrementSessionStatusCount(); } } + + /** + * @inheritDoc + */ + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types + protected _eventFromException(exception: any, hint?: EventHint): PromiseLike { + return eventFromException(this._options, exception, hint); + } + + /** + * @inheritDoc + */ + protected _eventFromMessage(message: string, level: SeverityLevel = 'info', hint?: EventHint): PromiseLike { + return eventFromMessage(this._options, message, level, hint); + } + + /** + * @inheritDoc + */ + protected _setupTransport(): Transport { + if (!this._options.dsn) { + // We return the noop transport here in case there is no Dsn. + return super._setupTransport(); + } + + const dsn = new Dsn(this._options.dsn); + + const transportOptions: TransportOptions = { + ...this._options.transportOptions, + ...(this._options.httpProxy && { httpProxy: this._options.httpProxy }), + ...(this._options.httpsProxy && { httpsProxy: this._options.httpsProxy }), + ...(this._options.caCerts && { caCerts: this._options.caCerts }), + dsn: this._options.dsn, + tunnel: this._options.tunnel, + _metadata: this._options._metadata, + }; + + if (this._options.transport) { + return new this._options.transport(transportOptions); + } + if (dsn.protocol === 'http') { + return new HTTPTransport(transportOptions); + } + return new HTTPSTransport(transportOptions); + } } From feeff81caca8199c9f9b8f63ee35b4dab7cb4b95 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 11:53:14 -0500 Subject: [PATCH 04/17] ref(core): Remove comments related to backend --- packages/core/src/baseclient.ts | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index d8f939d9cca8..2f02e6d96002 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -35,17 +35,15 @@ const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been ca /** * Base implementation for all JavaScript SDK clients. * - * Call the constructor with the corresponding backend constructor and options - * specific to the client subclass. To access these options later, use - * {@link Client.getOptions}. Also, the Backend instance is available via - * {@link Client.getBackend}. + * Call the constructor with the 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 via the backend, it is passed through + * Before sending an event via the transport, 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. @@ -83,7 +81,6 @@ export abstract class BaseClient implements Client { /** * Initializes this client instance. * - * @param backendClass A constructor function to create the backend. * @param options Options for the client. */ protected constructor(options: O) { From 4c4b2af93a9052a6adeb63499d266c5e80408168 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 11:57:48 -0500 Subject: [PATCH 05/17] ref(core): Adjust test mocks --- packages/core/test/mocks/backend.ts | 75 ----------------------------- packages/core/test/mocks/client.ts | 69 ++++++++++++++++++++++++-- packages/node/src/index.ts | 1 - 3 files changed, 66 insertions(+), 79 deletions(-) delete mode 100644 packages/core/test/mocks/backend.ts diff --git a/packages/core/test/mocks/backend.ts b/packages/core/test/mocks/backend.ts deleted file mode 100644 index 10e3862211f8..000000000000 --- a/packages/core/test/mocks/backend.ts +++ /dev/null @@ -1,75 +0,0 @@ -import { Session } from '@sentry/hub'; -import { Event, Options, SeverityLevel, Transport } from '@sentry/types'; -import { resolvedSyncPromise } from '@sentry/utils'; - -import { BaseBackend } from '../../src/basebackend'; - -export interface TestOptions extends Options { - test?: boolean; - mockInstallFailure?: boolean; - enableSend?: boolean; -} - -export class TestBackend extends BaseBackend { - public static instance?: TestBackend; - public static sendEventCalled?: (event: Event) => void; - - public event?: Event; - public session?: Session; - - public constructor(protected readonly _options: TestOptions) { - super(_options); - TestBackend.instance = this; - } - - // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types - public eventFromException(exception: any): PromiseLike { - return resolvedSyncPromise({ - exception: { - values: [ - { - /* eslint-disable @typescript-eslint/no-unsafe-member-access */ - type: exception.name, - value: exception.message, - /* eslint-enable @typescript-eslint/no-unsafe-member-access */ - }, - ], - }, - }); - } - - public eventFromMessage(message: string, level: SeverityLevel = 'info'): PromiseLike { - return resolvedSyncPromise({ message, level }); - } - - public sendEvent(event: Event): void { - this.event = event; - if (this._options.enableSend) { - super.sendEvent(event); - return; - } - // eslint-disable-next-line @typescript-eslint/no-unused-expressions - TestBackend.sendEventCalled && TestBackend.sendEventCalled(event); - } - - public sendSession(session: Session): void { - this.session = session; - } - - protected _setupTransport(): Transport { - if (!this._options.dsn) { - // We return the noop transport here in case there is no Dsn. - return super._setupTransport(); - } - - const transportOptions = this._options.transportOptions - ? this._options.transportOptions - : { dsn: this._options.dsn }; - - if (this._options.transport) { - return new this._options.transport(transportOptions); - } - - return super._setupTransport(); - } -} diff --git a/packages/core/test/mocks/client.ts b/packages/core/test/mocks/client.ts index 810328818eae..ecceb6baae58 100644 --- a/packages/core/test/mocks/client.ts +++ b/packages/core/test/mocks/client.ts @@ -1,14 +1,77 @@ +import { Options, EventHint, Event, Session, SeverityLevel, Transport } from '@sentry/types'; + import { BaseClient } from '../../src/baseclient'; import { initAndBind } from '../../src/sdk'; -import { TestBackend, TestOptions } from './backend'; +import { resolvedSyncPromise } from '@sentry/utils'; + +interface TestOptions extends Options { + test?: boolean; + mockInstallFailure?: boolean; + enableSend?: boolean; +} -export class TestClient extends BaseClient { +export class TestClient extends BaseClient { public static instance?: TestClient; + public static sendEventCalled?: (event: Event) => void; + + public event?: Event; + public session?: Session; public constructor(options: TestOptions) { - super(TestBackend, options); + super(options); TestClient.instance = this; } + + public sendEvent(event: Event): void { + this.event = event; + if (this._options.enableSend) { + super.sendEvent(event); + return; + } + // eslint-disable-next-line @typescript-eslint/no-unused-expressions + TestClient.sendEventCalled && TestClient.sendEventCalled(event); + } + + public sendSession(session: Session): void { + this.session = session; + } + + protected _setupTransport(): Transport { + if (!this._options.dsn) { + // We return the noop transport here in case there is no Dsn. + return super._setupTransport(); + } + + const transportOptions = this._options.transportOptions + ? this._options.transportOptions + : { dsn: this._options.dsn }; + + if (this._options.transport) { + return new this._options.transport(transportOptions); + } + + return super._setupTransport(); + } + + // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types + protected _eventFromException(exception: any, _hint?: EventHint): PromiseLike { + return resolvedSyncPromise({ + exception: { + values: [ + { + /* eslint-disable @typescript-eslint/no-unsafe-member-access */ + type: exception.name, + value: exception.message, + /* eslint-enable @typescript-eslint/no-unsafe-member-access */ + }, + ], + }, + }); + } + + protected _eventFromMessage(message: string, level: SeverityLevel = 'info'): PromiseLike { + return resolvedSyncPromise({ message, level }); + } } export function init(options: TestOptions): void { diff --git a/packages/node/src/index.ts b/packages/node/src/index.ts index 8aa44c75912b..6508fcfe803b 100644 --- a/packages/node/src/index.ts +++ b/packages/node/src/index.ts @@ -39,7 +39,6 @@ export { } from '@sentry/core'; export { NodeOptions } from './types'; -export { NodeBackend } from './backend'; export { NodeClient } from './client'; export { defaultIntegrations, init, lastEventId, flush, close, getSentryRelease } from './sdk'; export { deepReadDirSync } from './utils'; From 21c759c06085aca495a1c2edccac5ea85a8534c5 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:08:08 -0500 Subject: [PATCH 06/17] remove noop transport --- packages/browser/src/client.ts | 2 +- packages/core/src/baseclient.ts | 36 +++++++++++++++++----------- packages/core/src/transports/noop.ts | 22 ----------------- packages/core/test/mocks/client.ts | 25 ++++++++++++++++--- packages/node/src/client.ts | 17 +++++++++---- packages/types/src/client.ts | 2 +- 6 files changed, 58 insertions(+), 46 deletions(-) delete mode 100644 packages/core/src/transports/noop.ts diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 0b82e34c79ae..ab4b634b2e0c 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -124,7 +124,7 @@ export class BrowserClient extends BaseClient { protected _setupTransport(): Transport { if (!this._options.dsn) { // We return the noop transport here in case there is no Dsn. - return super._setupTransport(); + return undefined; } const transportOptions = { diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 2f02e6d96002..e8a00297fa89 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -28,7 +28,6 @@ import { } from '@sentry/utils'; import { IntegrationIndex, setupIntegrations } from './integration'; -import { NoopTransport } from './transports/noop'; const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; @@ -76,7 +75,7 @@ export abstract class BaseClient implements Client { protected _numProcessing: number = 0; /** Cached transport used internally. */ - protected _transport: Transport; + protected _transport: Transport | undefined; /** * Initializes this client instance. @@ -194,7 +193,7 @@ export abstract class BaseClient implements Client { /** * @inheritDoc */ - public getTransport(): Transport { + public getTransport(): Transport | undefined { return this._transport; } @@ -203,9 +202,11 @@ export abstract class BaseClient implements Client { */ public flush(timeout?: number): PromiseLike { return this._isClientDoneProcessing(timeout).then(clientFinished => { - return this.getTransport() - .close(timeout) - .then(transportFlushed => clientFinished && transportFlushed); + const transport = this.getTransport(); + if (transport) { + return transport.close(timeout).then(transportFlushed => clientFinished && transportFlushed); + } + return false; }); } @@ -244,21 +245,28 @@ export abstract class BaseClient implements Client { * @inheritDoc */ public sendEvent(event: Event): void { - void this._transport.sendEvent(event).then(null, reason => { - logger.error(`Error while sending event: ${reason}`); - }); + const transport = this.getTransport(); + if (transport) { + void transport.sendEvent(event).then(null, reason => { + logger.error(`Error while sending event: ${reason}`); + }); + } } /** * @inheritDoc */ public sendSession(session: Session): void { - if (!this._transport.sendSession) { + const transport = this.getTransport(); + if (!transport) { + return; + } + if (!transport.sendSession) { logger.warn("Dropping session because custom transport doesn't implement sendSession"); return; } - void this._transport.sendSession(session).then(null, reason => { + void transport.sendSession(session).then(null, reason => { logger.error(`Error while sending session: ${reason}`); }); } @@ -525,7 +533,7 @@ export abstract class BaseClient implements Client { type RecordLostEventParams = Parameters; function recordLostEvent(outcome: RecordLostEventParams[0], category: RecordLostEventParams[1]): void { - if (transport.recordLostEvent) { + if (transport && transport.recordLostEvent) { transport.recordLostEvent(outcome, category); } } @@ -613,8 +621,8 @@ export abstract class BaseClient implements Client { /** * Sets up the transport so it can be used later to send requests. */ - protected _setupTransport(): Transport { - return new NoopTransport(); + protected _setupTransport(): Transport | undefined { + return undefined; } /** diff --git a/packages/core/src/transports/noop.ts b/packages/core/src/transports/noop.ts deleted file mode 100644 index 0fc2c190f263..000000000000 --- a/packages/core/src/transports/noop.ts +++ /dev/null @@ -1,22 +0,0 @@ -import { Event, Response, Transport } from '@sentry/types'; -import { resolvedSyncPromise } from '@sentry/utils'; - -/** Noop transport */ -export class NoopTransport implements Transport { - /** - * @inheritDoc - */ - public sendEvent(_: Event): PromiseLike { - return resolvedSyncPromise({ - reason: `NoopTransport: Event has been skipped because no Dsn is configured.`, - status: 'skipped', - }); - } - - /** - * @inheritDoc - */ - public close(_?: number): PromiseLike { - return resolvedSyncPromise(true); - } -} diff --git a/packages/core/test/mocks/client.ts b/packages/core/test/mocks/client.ts index ecceb6baae58..6ff86b402c22 100644 --- a/packages/core/test/mocks/client.ts +++ b/packages/core/test/mocks/client.ts @@ -1,9 +1,28 @@ -import { Options, EventHint, Event, Session, SeverityLevel, Transport } from '@sentry/types'; +import { Options, EventHint, Event, Session, SeverityLevel, Transport, Response } from '@sentry/types'; import { BaseClient } from '../../src/baseclient'; import { initAndBind } from '../../src/sdk'; import { resolvedSyncPromise } from '@sentry/utils'; +export class NoopTransport implements Transport { + /** + * @inheritDoc + */ + public sendEvent(_: Event): PromiseLike { + return resolvedSyncPromise({ + reason: `NoopTransport: Event has been skipped because no Dsn is configured.`, + status: 'skipped', + }); + } + + /** + * @inheritDoc + */ + public close(_?: number): PromiseLike { + return resolvedSyncPromise(true); + } +} + interface TestOptions extends Options { test?: boolean; mockInstallFailure?: boolean; @@ -39,7 +58,7 @@ export class TestClient extends BaseClient { protected _setupTransport(): Transport { if (!this._options.dsn) { // We return the noop transport here in case there is no Dsn. - return super._setupTransport(); + return new NoopTransport(); } const transportOptions = this._options.transportOptions @@ -50,7 +69,7 @@ export class TestClient extends BaseClient { return new this._options.transport(transportOptions); } - return super._setupTransport(); + return new NoopTransport(); } // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index e50a4b435d53..026bfb8ed6b3 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -96,14 +96,21 @@ export class NodeClient extends BaseClient { /** Method that initialises an instance of SessionFlusher on Client */ public initSessionFlusher(): void { const { release, environment } = this._options; + const transport = this.getTransport(); + + if (!transport) { + logger.warn('Cannot initialise an instance of SessionFlusher if no transport is initialized!'); + return; + } if (!release) { logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); - } else { - this._sessionFlusher = new SessionFlusher(this.getTransport(), { - release, - environment, - }); + return; } + + this._sessionFlusher = new SessionFlusher(transport, { + release, + environment, + }); } /** diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index 96dda52249aa..8eb5afdfee3a 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -61,7 +61,7 @@ export interface Client { getOptions(): O; /** Returns clients transport. */ - getTransport?(): Transport; + getTransport?(): Transport | undefined; /** * Flush the event queue and set the client to `enabled = false`. See {@link Client.flush}. From a021a36e5f4a26ac42ae64f9454877c5ad8ff3ba Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:15:20 -0500 Subject: [PATCH 07/17] delete test --- packages/browser/test/unit/backend.test.ts | 12 ------------ packages/core/src/index.ts | 1 - 2 files changed, 13 deletions(-) delete mode 100644 packages/browser/test/unit/backend.test.ts diff --git a/packages/browser/test/unit/backend.test.ts b/packages/browser/test/unit/backend.test.ts deleted file mode 100644 index 71ffec4d75b1..000000000000 --- a/packages/browser/test/unit/backend.test.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { BrowserBackend } from '../../src/backend'; - -let backend: BrowserBackend; - -describe('BrowserBackend', () => { - describe('sendEvent()', () => { - it('should use NoopTransport', () => { - backend = new BrowserBackend({}); - expect(backend.getTransport().constructor.name).toBe('NoopTransport'); - }); - }); -}); diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index e264d18f5203..39f8319647f1 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -27,7 +27,6 @@ export { export { BaseClient } from './baseclient'; export { eventToSentryRequest, sessionToSentryRequest } from './request'; export { initAndBind, ClientClass } from './sdk'; -export { NoopTransport } from './transports/noop'; export { SDK_VERSION } from './version'; import * as Integrations from './integrations'; From 6418e05f4976a9c9df3c75d96c0f49eb755ad11a Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:22:55 -0500 Subject: [PATCH 08/17] make transport undefined --- packages/browser/src/client.ts | 2 +- packages/node/src/client.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index ab4b634b2e0c..d076176c18ca 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -121,7 +121,7 @@ export class BrowserClient extends BaseClient { /** * @inheritDoc */ - protected _setupTransport(): Transport { + protected _setupTransport(): Transport | undefined { if (!this._options.dsn) { // We return the noop transport here in case there is no Dsn. return undefined; diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index 026bfb8ed6b3..685439ce0812 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -154,7 +154,7 @@ export class NodeClient extends BaseClient { /** * @inheritDoc */ - protected _setupTransport(): Transport { + protected _setupTransport(): Transport | undefined { if (!this._options.dsn) { // We return the noop transport here in case there is no Dsn. return super._setupTransport(); From 5924e727cfae913c1fd147b0dfc77fee6e4b5ae2 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:28:33 -0500 Subject: [PATCH 09/17] make setup transport abstract --- packages/core/src/baseclient.ts | 4 +--- packages/node/src/client.ts | 3 +-- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index e8a00297fa89..62e112d8c889 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -621,9 +621,7 @@ export abstract class BaseClient implements Client { /** * Sets up the transport so it can be used later to send requests. */ - protected _setupTransport(): Transport | undefined { - return undefined; - } + protected abstract _setupTransport(): Transport | undefined; /** * @inheritDoc diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index 685439ce0812..e70423b05dd9 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -156,8 +156,7 @@ export class NodeClient extends BaseClient { */ protected _setupTransport(): Transport | undefined { if (!this._options.dsn) { - // We return the noop transport here in case there is no Dsn. - return super._setupTransport(); + return undefined; } const dsn = new Dsn(this._options.dsn); From 1e05e25feca4ebd3837040c53d8aeadad468ed21 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:41:06 -0500 Subject: [PATCH 10/17] fix core backend tests by migrating to client --- packages/core/test/lib/base.test.ts | 100 ++++++++++++++-------------- 1 file changed, 51 insertions(+), 49 deletions(-) diff --git a/packages/core/test/lib/base.test.ts b/packages/core/test/lib/base.test.ts index cd8d7f992fb4..d1655807247d 100644 --- a/packages/core/test/lib/base.test.ts +++ b/packages/core/test/lib/base.test.ts @@ -3,7 +3,6 @@ import { Event, Span, Transport } from '@sentry/types'; import { logger, SentryError, SyncPromise } from '@sentry/utils'; import * as integrationModule from '../../src/integration'; -import { TestBackend } from '../mocks/backend'; import { TestClient } from '../mocks/client'; import { TestIntegration } from '../mocks/integration'; import { FakeTransport } from '../mocks/transport'; @@ -12,7 +11,8 @@ const PUBLIC_DSN = 'https://username@domain/123'; // eslint-disable-next-line no-var declare var global: any; -const backendEventFromException = jest.spyOn(TestBackend.prototype, 'eventFromException'); +// @ts-ignore inspecting protected method +const backendEventFromException = jest.spyOn(TestClient.prototype, '_eventFromException'); const clientProcess = jest.spyOn(TestClient.prototype as any, '_process'); jest.mock('@sentry/utils', () => { @@ -55,8 +55,8 @@ jest.mock('@sentry/utils', () => { describe('BaseClient', () => { beforeEach(() => { - TestBackend.sendEventCalled = undefined; - TestBackend.instance = undefined; + TestClient.sendEventCalled = undefined; + TestClient.instance = undefined; }); afterEach(() => { @@ -97,7 +97,7 @@ describe('BaseClient', () => { const options = { dsn: PUBLIC_DSN, transport: FakeTransport }; const client = new TestClient(options); expect(client.getTransport()).toBeInstanceOf(FakeTransport); - expect(TestBackend.instance!.getTransport()).toBe(client.getTransport()); + expect(TestClient.instance!.getTransport()).toBe(client.getTransport()); }); }); @@ -189,7 +189,7 @@ describe('BaseClient', () => { test('captures and sends exceptions', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); client.captureException(new Error('test exception')); - expect(TestBackend.instance!.event).toEqual({ + expect(TestClient.instance!.event).toEqual({ environment: 'production', event_id: '42', exception: { @@ -219,7 +219,7 @@ describe('BaseClient', () => { }, scope, ); - expect(TestBackend.instance!.event).toEqual( + expect(TestClient.instance!.event).toEqual( expect.objectContaining({ extra: { bar: 'wat', @@ -244,7 +244,7 @@ describe('BaseClient', () => { }, scope, ); - expect(TestBackend.instance!.event).toEqual( + expect(TestClient.instance!.event).toEqual( expect.objectContaining({ extra: { bar: 'wat', @@ -282,7 +282,7 @@ describe('BaseClient', () => { test('captures and sends messages', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); client.captureMessage('test message'); - expect(TestBackend.instance!.event).toEqual({ + expect(TestClient.instance!.event).toEqual({ environment: 'production', event_id: '42', level: 'info', @@ -293,7 +293,8 @@ describe('BaseClient', () => { test('should call eventFromException if input to captureMessage is not a primitive', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); - const spy = jest.spyOn(TestBackend.instance!, 'eventFromException'); + // @ts-ignore grabbing protected instance + const spy = jest.spyOn(TestClient.instance!, '_eventFromException'); client.captureMessage('foo'); client.captureMessage(null as any); @@ -323,7 +324,7 @@ describe('BaseClient', () => { }, scope, ); - expect(TestBackend.instance!.event).toEqual( + expect(TestClient.instance!.event).toEqual( expect.objectContaining({ extra: { bar: 'wat', @@ -341,7 +342,7 @@ describe('BaseClient', () => { const client = new TestClient({ enabled: false, dsn: PUBLIC_DSN }); const scope = new Scope(); client.captureEvent({}, undefined, scope); - expect(TestBackend.instance!.event).toBeUndefined(); + expect(TestClient.instance!.event).toBeUndefined(); }); test('skips without a Dsn', () => { @@ -349,7 +350,7 @@ describe('BaseClient', () => { const client = new TestClient({}); const scope = new Scope(); client.captureEvent({}, undefined, scope); - expect(TestBackend.instance!.event).toBeUndefined(); + expect(TestClient.instance!.event).toBeUndefined(); }); test.each([ @@ -386,8 +387,8 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); const scope = new Scope(); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!.message).toBe('message'); - expect(TestBackend.instance!.event).toEqual({ + expect(TestClient.instance!.event!.message).toBe('message'); + expect(TestClient.instance!.event).toEqual({ environment: 'production', event_id: '42', message: 'message', @@ -400,8 +401,8 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); const scope = new Scope(); client.captureEvent({ message: 'message', timestamp: 1234 }, undefined, scope); - expect(TestBackend.instance!.event!.message).toBe('message'); - expect(TestBackend.instance!.event).toEqual({ + expect(TestClient.instance!.event!.message).toBe('message'); + expect(TestClient.instance!.event).toEqual({ environment: 'production', event_id: '42', message: 'message', @@ -414,7 +415,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); const scope = new Scope(); client.captureEvent({ message: 'message' }, { event_id: 'wat' }, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: 'production', event_id: 'wat', message: 'message', @@ -429,7 +430,7 @@ describe('BaseClient', () => { }); const scope = new Scope(); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: 'production', event_id: '42', message: 'message', @@ -445,7 +446,7 @@ describe('BaseClient', () => { }); const scope = new Scope(); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: 'env', event_id: '42', message: 'message', @@ -461,7 +462,7 @@ describe('BaseClient', () => { }); const scope = new Scope(); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: undefined, event_id: '42', message: 'message', @@ -477,7 +478,7 @@ describe('BaseClient', () => { }); const scope = new Scope(); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: 'production', event_id: '42', message: 'message', @@ -492,10 +493,10 @@ describe('BaseClient', () => { const scope = new Scope(); scope.addBreadcrumb({ message: 'breadcrumb' }, 100); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toHaveProperty('event_id', '42'); - expect(TestBackend.instance!.event!).toHaveProperty('message', 'message'); - expect(TestBackend.instance!.event!).toHaveProperty('breadcrumbs'); - expect(TestBackend.instance!.event!.breadcrumbs![0]).toHaveProperty('message', 'breadcrumb'); + expect(TestClient.instance!.event!).toHaveProperty('event_id', '42'); + expect(TestClient.instance!.event!).toHaveProperty('message', 'message'); + expect(TestClient.instance!.event!).toHaveProperty('breadcrumbs'); + expect(TestClient.instance!.event!.breadcrumbs![0]).toHaveProperty('message', 'breadcrumb'); }); test('limits previously saved breadcrumbs', () => { @@ -506,8 +507,8 @@ describe('BaseClient', () => { hub.addBreadcrumb({ message: '1' }); hub.addBreadcrumb({ message: '2' }); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!.breadcrumbs).toHaveLength(1); - expect(TestBackend.instance!.event!.breadcrumbs![0].message).toEqual('2'); + expect(TestClient.instance!.event!.breadcrumbs).toHaveLength(1); + expect(TestClient.instance!.event!.breadcrumbs![0].message).toEqual('2'); }); test('adds context data', () => { @@ -518,7 +519,7 @@ describe('BaseClient', () => { scope.setTag('a', 'a'); scope.setUser({ id: 'user' }); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: 'production', event_id: '42', extra: { b: 'b' }, @@ -535,7 +536,7 @@ describe('BaseClient', () => { const scope = new Scope(); scope.setFingerprint(['abcd']); client.captureEvent({ message: 'message' }, undefined, scope); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ environment: 'production', event_id: '42', fingerprint: ['abcd'], @@ -548,7 +549,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN, integrations: [new TestIntegration()] }); client.setupIntegrations(); client.captureEvent({ message: 'message' }); - expect(TestBackend.instance!.event!.sdk).toEqual({ + expect(TestClient.instance!.event!.sdk).toEqual({ integrations: ['TestIntegration'], }); }); @@ -588,7 +589,7 @@ describe('BaseClient', () => { extra: fourLevelsObject, user: fourLevelsObject, }); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ breadcrumbs: [normalizedBreadcrumb, normalizedBreadcrumb, normalizedBreadcrumb], contexts: normalizedObject, environment: 'production', @@ -634,7 +635,7 @@ describe('BaseClient', () => { extra: fourLevelsObject, user: fourLevelsObject, }); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ breadcrumbs: [normalizedBreadcrumb, normalizedBreadcrumb, normalizedBreadcrumb], contexts: normalizedObject, environment: 'production', @@ -685,7 +686,7 @@ describe('BaseClient', () => { extra: fourLevelsObject, user: fourLevelsObject, }); - expect(TestBackend.instance!.event!).toEqual({ + expect(TestClient.instance!.event!).toEqual({ breadcrumbs: [normalizedBreadcrumb, normalizedBreadcrumb, normalizedBreadcrumb], contexts: normalizedObject, environment: 'production', @@ -742,7 +743,7 @@ describe('BaseClient', () => { // input transaction. const normalizedTransaction = JSON.parse(JSON.stringify(transaction)); // deep-copy client.captureEvent(transaction); - expect(TestBackend.instance!.event!).toEqual(normalizedTransaction); + expect(TestClient.instance!.event!).toEqual(normalizedTransaction); }); test('calls beforeSend and uses original event without any changes', () => { @@ -750,7 +751,7 @@ describe('BaseClient', () => { const beforeSend = jest.fn(event => event); const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); client.captureEvent({ message: 'hello' }); - expect(TestBackend.instance!.event!.message).toBe('hello'); + expect(TestClient.instance!.event!.message).toBe('hello'); }); test('calls beforeSend and uses the new one', () => { @@ -758,7 +759,7 @@ describe('BaseClient', () => { const beforeSend = jest.fn(() => ({ message: 'changed1' })); const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); client.captureEvent({ message: 'hello' }); - expect(TestBackend.instance!.event!.message).toBe('changed1'); + expect(TestClient.instance!.event!.message).toBe('changed1'); }); test('calls beforeSend and discards the event', () => { @@ -768,7 +769,7 @@ describe('BaseClient', () => { const captureExceptionSpy = jest.spyOn(client, 'captureException'); const loggerErrorSpy = jest.spyOn(logger, 'error'); client.captureEvent({ message: 'hello' }); - expect(TestBackend.instance!.event).toBeUndefined(); + expect(TestClient.instance!.event).toBeUndefined(); expect(captureExceptionSpy).not.toBeCalled(); expect(loggerErrorSpy).toBeCalledWith(new SentryError('`beforeSend` returned `null`, will not send event.')); }); @@ -783,7 +784,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); const loggerErrorSpy = jest.spyOn(logger, 'error'); client.captureEvent({ message: 'hello' }); - expect(TestBackend.instance!.event).toBeUndefined(); + expect(TestClient.instance!.event).toBeUndefined(); expect(loggerErrorSpy).toBeCalledWith( new SentryError('`beforeSend` method has to return `null` or a valid event.'), ); @@ -804,7 +805,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); client.captureEvent({ message: 'hello' }); jest.runOnlyPendingTimers(); - TestBackend.sendEventCalled = (event: Event) => { + TestClient.sendEventCalled = (event: Event) => { expect(event.message).toBe('hello'); }; setTimeout(() => { @@ -828,7 +829,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); client.captureEvent({ message: 'hello' }); jest.runOnlyPendingTimers(); - TestBackend.sendEventCalled = (event: Event) => { + TestClient.sendEventCalled = (event: Event) => { expect(event.message).toBe('changed2'); }; setTimeout(() => { @@ -851,7 +852,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); client.captureEvent({ message: 'hello' }); jest.runAllTimers(); - expect(TestBackend.instance!.event).toBeUndefined(); + expect(TestClient.instance!.event).toBeUndefined(); }); test('beforeSend gets access to a hint as a second argument', () => { @@ -859,8 +860,8 @@ describe('BaseClient', () => { const beforeSend = jest.fn((event, hint) => ({ ...event, data: hint.data })); const client = new TestClient({ dsn: PUBLIC_DSN, beforeSend }); client.captureEvent({ message: 'hello' }, { data: 'someRandomThing' }); - expect(TestBackend.instance!.event!.message).toBe('hello'); - expect((TestBackend.instance!.event! as any).data).toBe('someRandomThing'); + expect(TestClient.instance!.event!.message).toBe('hello'); + expect((TestClient.instance!.event! as any).data).toBe('someRandomThing'); }); test('beforeSend records dropped events', () => { @@ -893,7 +894,7 @@ describe('BaseClient', () => { const scope = new Scope(); scope.addEventProcessor(() => null); client.captureEvent({ message: 'hello' }, {}, scope); - expect(TestBackend.instance!.event).toBeUndefined(); + expect(TestClient.instance!.event).toBeUndefined(); expect(captureExceptionSpy).not.toBeCalled(); expect(loggerErrorSpy).toBeCalledWith(new SentryError('An event processor returned null, will not send event.')); }); @@ -928,7 +929,7 @@ describe('BaseClient', () => { throw exception; }); client.captureEvent({ message: 'hello' }, {}, scope); - expect(TestBackend.instance!.event!.exception!.values![0]).toStrictEqual({ type: 'Error', value: 'sorry' }); + expect(TestClient.instance!.event!.exception!.values![0]).toStrictEqual({ type: 'Error', value: 'sorry' }); expect(captureExceptionSpy).toBeCalledWith(exception, { data: { __sentry__: true, @@ -1054,7 +1055,8 @@ describe('BaseClient', () => { }); const delay = 300; - const spy = jest.spyOn(TestBackend.instance!, 'eventFromMessage'); + // @ts-ignore grabbing protected instance + const spy = jest.spyOn(TestClient.instance!, '_eventFromMessage'); spy.mockImplementationOnce( (message, level) => new SyncPromise(resolve => { @@ -1120,7 +1122,7 @@ describe('BaseClient', () => { const client = new TestClient({ dsn: PUBLIC_DSN }); const session = new Session({ release: 'test' }); client.captureSession(session); - expect(TestBackend.instance!.session).toEqual(session); + expect(TestClient.instance!.session).toEqual(session); }); test('skips when disabled', () => { @@ -1128,7 +1130,7 @@ describe('BaseClient', () => { const client = new TestClient({ enabled: false, dsn: PUBLIC_DSN }); const session = new Session({ release: 'test' }); client.captureSession(session); - expect(TestBackend.instance!.session).toBeUndefined(); + expect(TestClient.instance!.session).toBeUndefined(); }); }); }); From bd786cd8c4d8c9b66817265984e9f5e1b4c69e93 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:43:23 -0500 Subject: [PATCH 11/17] fix browser tests --- packages/browser/test/unit/index.test.ts | 6 +++--- .../test/unit/integrations/linkederrors.test.ts | 11 ++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/packages/browser/test/unit/index.test.ts b/packages/browser/test/unit/index.test.ts index f5f4554c552a..0f04fbbef21d 100644 --- a/packages/browser/test/unit/index.test.ts +++ b/packages/browser/test/unit/index.test.ts @@ -246,7 +246,7 @@ describe('SentryBrowser initialization', () => { it('should set SDK data when Sentry.init() is called', () => { init({ dsn }); - const sdkData = (getCurrentHub().getClient() as any)._backend._transport._api.metadata?.sdk; + const sdkData = (getCurrentHub().getClient() as any)._transport._api.metadata?.sdk; expect(sdkData.name).toBe('sentry.javascript.browser'); expect(sdkData.packages[0].name).toBe('npm:@sentry/browser'); @@ -257,7 +257,7 @@ describe('SentryBrowser initialization', () => { it('should set SDK data when instantiating a client directly', () => { const client = new BrowserClient({ dsn }); - const sdkData = (client as any)._backend._transport._api.metadata?.sdk; + const sdkData = (client as any)._transport._api.metadata?.sdk; expect(sdkData.name).toBe('sentry.javascript.browser'); expect(sdkData.packages[0].name).toBe('npm:@sentry/browser'); @@ -285,7 +285,7 @@ describe('SentryBrowser initialization', () => { }, }); - const sdkData = (getCurrentHub().getClient() as any)._backend._transport._api.metadata?.sdk; + const sdkData = (getCurrentHub().getClient() as any)._transport._api.metadata?.sdk; expect(sdkData.name).toBe('sentry.javascript.angular'); expect(sdkData.packages[0].name).toBe('npm:@sentry/angular'); diff --git a/packages/browser/test/unit/integrations/linkederrors.test.ts b/packages/browser/test/unit/integrations/linkederrors.test.ts index 1531aa6f77ed..df8a472102e2 100644 --- a/packages/browser/test/unit/integrations/linkederrors.test.ts +++ b/packages/browser/test/unit/integrations/linkederrors.test.ts @@ -1,7 +1,7 @@ import { ExtendedError } from '@sentry/types'; -import { BrowserBackend } from '../../../src/backend'; import * as LinkedErrorsModule from '../../../src/integrations/linkederrors'; +import { BrowserClient, eventFromException } from '../../../src'; describe('LinkedErrors', () => { describe('handler', () => { @@ -34,8 +34,7 @@ describe('LinkedErrors', () => { one.cause = two; const originalException = one; - const backend = new BrowserBackend({}); - return backend.eventFromException(originalException).then(event => { + return eventFromException({}, originalException).then(event => { const result = LinkedErrorsModule._handler('cause', 5, event, { originalException, }); @@ -64,8 +63,7 @@ describe('LinkedErrors', () => { one.reason = two; const originalException = one; - const backend = new BrowserBackend({}); - return backend.eventFromException(originalException).then(event => { + return eventFromException({}, originalException).then(event => { const result = LinkedErrorsModule._handler('reason', 5, event, { originalException, }); @@ -90,9 +88,8 @@ describe('LinkedErrors', () => { one.cause = two; two.cause = three; - const backend = new BrowserBackend({}); const originalException = one; - return backend.eventFromException(originalException).then(event => { + return eventFromException({}, originalException).then(event => { const result = LinkedErrorsModule._handler('cause', 2, event, { originalException, }); From 60835168406d778cc2a912033763004e5548148e Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:43:44 -0500 Subject: [PATCH 12/17] core: Adjust jsdoc --- packages/core/src/baseclient.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 62e112d8c889..53b1a502baae 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -53,9 +53,9 @@ const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been ca * {@link Client.addBreadcrumb}. * * @example - * class NodeClient extends BaseClient { + * class NodeClient extends BaseClient { * public constructor(options: NodeOptions) { - * super(NodeBackend, options); + * super(options); * } * * // ... From 0d44ce1710f4e03bbaf0b1a74374283545d462ad Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:44:31 -0500 Subject: [PATCH 13/17] core: adjust naming --- packages/core/test/lib/base.test.ts | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/core/test/lib/base.test.ts b/packages/core/test/lib/base.test.ts index d1655807247d..886f22cd0f6e 100644 --- a/packages/core/test/lib/base.test.ts +++ b/packages/core/test/lib/base.test.ts @@ -12,7 +12,7 @@ const PUBLIC_DSN = 'https://username@domain/123'; declare var global: any; // @ts-ignore inspecting protected method -const backendEventFromException = jest.spyOn(TestClient.prototype, '_eventFromException'); +const clientEventFromException = jest.spyOn(TestClient.prototype, '_eventFromException'); const clientProcess = jest.spyOn(TestClient.prototype as any, '_process'); jest.mock('@sentry/utils', () => { @@ -92,7 +92,7 @@ describe('BaseClient', () => { }); describe('getTransport()', () => { - test('returns the transport from backend', () => { + test('returns the transport from client', () => { expect.assertions(2); const options = { dsn: PUBLIC_DSN, transport: FakeTransport }; const client = new TestClient(options); @@ -269,12 +269,12 @@ describe('BaseClient', () => { client.captureException(thrown); expect(thrown.__sentry_captured__).toBe(true); - expect(backendEventFromException).toHaveBeenCalledTimes(1); + expect(clientEventFromException).toHaveBeenCalledTimes(1); client.captureException(thrown); // `captureException` should bail right away this second time around and not get as far as calling this again - expect(backendEventFromException).toHaveBeenCalledTimes(1); + expect(clientEventFromException).toHaveBeenCalledTimes(1); }); }); @@ -1117,7 +1117,7 @@ describe('BaseClient', () => { }); describe('captureSession()', () => { - test('sends sessions to the backend', () => { + test('sends sessions to the client', () => { expect.assertions(1); const client = new TestClient({ dsn: PUBLIC_DSN }); const session = new Session({ release: 'test' }); From 98b03d72534afa7183020088b3c8f3a2ffd17d9e Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 12:46:06 -0500 Subject: [PATCH 14/17] remove backend ref from node tests --- packages/node/test/index.test.ts | 11 +++++------ .../test/integrations/linkederrors.test.ts | 18 ++++++------------ 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/packages/node/test/index.test.ts b/packages/node/test/index.test.ts index 126bc617ccb7..f52d997f9790 100644 --- a/packages/node/test/index.test.ts +++ b/packages/node/test/index.test.ts @@ -15,7 +15,6 @@ import { NodeClient, Scope, } from '../src'; -import { NodeBackend } from '../src/backend'; jest.mock('@sentry/core', () => { const original = jest.requireActual('@sentry/core'); @@ -77,7 +76,7 @@ describe('SentryNode', () => { let s: jest.SpyInstance; beforeEach(() => { - s = jest.spyOn(NodeBackend.prototype, 'sendEvent').mockImplementation(async () => Promise.resolve({ code: 200 })); + s = jest.spyOn(NodeClient.prototype, 'sendEvent').mockImplementation(async () => Promise.resolve({ code: 200 })); }); afterEach(() => { @@ -106,7 +105,7 @@ describe('SentryNode', () => { let s: jest.SpyInstance; beforeEach(() => { - s = jest.spyOn(NodeBackend.prototype, 'sendEvent').mockImplementation(async () => Promise.resolve({ code: 200 })); + s = jest.spyOn(NodeClient.prototype, 'sendEvent').mockImplementation(async () => Promise.resolve({ code: 200 })); }); afterEach(() => { @@ -320,7 +319,7 @@ describe('SentryNode initialization', () => { init({ dsn }); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const sdkData = (getCurrentHub().getClient() as any)._backend._transport._api.metadata?.sdk; + const sdkData = (getCurrentHub().getClient() as any)._transport._api.metadata?.sdk; expect(sdkData.name).toEqual('sentry.javascript.node'); expect(sdkData.packages[0].name).toEqual('npm:@sentry/node'); @@ -332,7 +331,7 @@ describe('SentryNode initialization', () => { const client = new NodeClient({ dsn }); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const sdkData = (client as any)._backend._transport._api.metadata?.sdk; + const sdkData = (client as any)._transport._api.metadata?.sdk; expect(sdkData.name).toEqual('sentry.javascript.node'); expect(sdkData.packages[0].name).toEqual('npm:@sentry/node'); @@ -361,7 +360,7 @@ describe('SentryNode initialization', () => { }); // eslint-disable-next-line @typescript-eslint/no-explicit-any - const sdkData = (getCurrentHub().getClient() as any)._backend._transport._api.metadata?.sdk; + const sdkData = (getCurrentHub().getClient() as any)._transport._api.metadata?.sdk; expect(sdkData.name).toEqual('sentry.javascript.serverless'); expect(sdkData.packages[0].name).toEqual('npm:@sentry/serverless'); diff --git a/packages/node/test/integrations/linkederrors.test.ts b/packages/node/test/integrations/linkederrors.test.ts index 7dcaf077e4c6..78509b8e08f8 100644 --- a/packages/node/test/integrations/linkederrors.test.ts +++ b/packages/node/test/integrations/linkederrors.test.ts @@ -1,8 +1,8 @@ import { ExtendedError } from '@sentry/types'; import { Event } from '../../src'; -import { NodeBackend } from '../../src/backend'; import { LinkedErrors } from '../../src/integrations/linkederrors'; +import { eventFromException } from '../../../browser/src'; let linkedErrors: any; @@ -28,10 +28,8 @@ describe('LinkedErrors', () => { expect.assertions(2); const spy = jest.spyOn(linkedErrors, '_walkErrorTree'); const one = new Error('originalException'); - const backend = new NodeBackend({}); let event: Event | undefined; - return backend - .eventFromException(one) + return eventFromException({}, one) .then(eventFromException => { event = eventFromException; return linkedErrors._handler(eventFromException); @@ -51,8 +49,7 @@ describe('LinkedErrors', () => { }), ); const one = new Error('originalException'); - const backend = new NodeBackend({}); - return backend.eventFromException(one).then(event => + return eventFromException({}, one).then(event => linkedErrors ._handler(event, { originalException: one, @@ -71,8 +68,7 @@ describe('LinkedErrors', () => { one.cause = two; two.cause = three; - const backend = new NodeBackend({}); - return backend.eventFromException(one).then(event => + return eventFromException({}, one).then(event => linkedErrors ._handler(event, { originalException: one, @@ -104,8 +100,7 @@ describe('LinkedErrors', () => { one.reason = two; two.reason = three; - const backend = new NodeBackend({}); - return backend.eventFromException(one).then(event => + return eventFromException({}, one).then(event => linkedErrors ._handler(event, { originalException: one, @@ -137,8 +132,7 @@ describe('LinkedErrors', () => { one.cause = two; two.cause = three; - const backend = new NodeBackend({}); - return backend.eventFromException(one).then(event => + return eventFromException({}, one).then(event => linkedErrors ._handler(event, { originalException: one, From f839cc0e046c24789bff82ec021f0c9eae1aa142 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 13:00:22 -0500 Subject: [PATCH 15/17] make sendEvent and sendSession protected --- packages/browser/src/client.ts | 2 +- packages/core/src/baseclient.ts | 8 ++++---- packages/types/src/client.ts | 6 ------ 3 files changed, 5 insertions(+), 11 deletions(-) diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index d076176c18ca..29834e28954f 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -100,7 +100,7 @@ export class BrowserClient extends BaseClient { if (integration) { integration.addSentryBreadcrumb(event); } - super.sendEvent(event); + super._sendEvent(event); } /** diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 53b1a502baae..7b3f180e305d 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -170,7 +170,7 @@ export abstract class BaseClient implements Client { if (!(typeof session.release === 'string')) { logger.warn('Discarded session because of missing or non-string release'); } else { - this.sendSession(session); + this._sendSession(session); // After sending, we set init false to indicate it's not the first occurrence session.update({ init: false }); } @@ -244,7 +244,7 @@ export abstract class BaseClient implements Client { /** * @inheritDoc */ - public sendEvent(event: Event): void { + protected _sendEvent(event: Event): void { const transport = this.getTransport(); if (transport) { void transport.sendEvent(event).then(null, reason => { @@ -256,7 +256,7 @@ export abstract class BaseClient implements Client { /** * @inheritDoc */ - public sendSession(session: Session): void { + protected _sendSession(session: Session): void { const transport = this.getTransport(); if (!transport) { return; @@ -581,7 +581,7 @@ export abstract class BaseClient implements Client { this._updateSessionFromEvent(session, processedEvent); } - this.sendEvent(processedEvent); + this._sendEvent(processedEvent); return processedEvent; }) .then(null, reason => { diff --git a/packages/types/src/client.ts b/packages/types/src/client.ts index 8eb5afdfee3a..ffc172aa4c6d 100644 --- a/packages/types/src/client.ts +++ b/packages/types/src/client.ts @@ -88,10 +88,4 @@ export interface Client { /** This is an internal function to setup all integrations that should run on the client */ setupIntegrations(): void; - - /** Submits the event to Sentry */ - sendEvent(event: Event): void; - - /** Submits the session to Sentry */ - sendSession(session: Session): void; } From d2be299906cc076664737a62f6c1d90064915cb7 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 13:03:02 -0500 Subject: [PATCH 16/17] yarn fix --- packages/browser/test/unit/integrations/helpers.test.ts | 2 +- packages/browser/test/unit/integrations/linkederrors.test.ts | 2 +- packages/core/test/mocks/client.ts | 4 ++-- packages/node/test/integrations/linkederrors.test.ts | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/packages/browser/test/unit/integrations/helpers.test.ts b/packages/browser/test/unit/integrations/helpers.test.ts index 80c60021400d..4b68df34cd95 100644 --- a/packages/browser/test/unit/integrations/helpers.test.ts +++ b/packages/browser/test/unit/integrations/helpers.test.ts @@ -1,5 +1,5 @@ import { WrappedFunction } from '@sentry/types'; -import { SinonSpy, spy } from 'sinon'; +import { spy } from 'sinon'; import { wrap } from '../../../src/helpers'; diff --git a/packages/browser/test/unit/integrations/linkederrors.test.ts b/packages/browser/test/unit/integrations/linkederrors.test.ts index df8a472102e2..ae118ac13132 100644 --- a/packages/browser/test/unit/integrations/linkederrors.test.ts +++ b/packages/browser/test/unit/integrations/linkederrors.test.ts @@ -1,7 +1,7 @@ import { ExtendedError } from '@sentry/types'; +import { eventFromException } from '../../../src'; import * as LinkedErrorsModule from '../../../src/integrations/linkederrors'; -import { BrowserClient, eventFromException } from '../../../src'; describe('LinkedErrors', () => { describe('handler', () => { diff --git a/packages/core/test/mocks/client.ts b/packages/core/test/mocks/client.ts index 6ff86b402c22..2b8ac4c229b8 100644 --- a/packages/core/test/mocks/client.ts +++ b/packages/core/test/mocks/client.ts @@ -1,8 +1,8 @@ -import { Options, EventHint, Event, Session, SeverityLevel, Transport, Response } from '@sentry/types'; +import { Event, EventHint, Options, Response, Session, SeverityLevel, Transport } from '@sentry/types'; +import { resolvedSyncPromise } from '@sentry/utils'; import { BaseClient } from '../../src/baseclient'; import { initAndBind } from '../../src/sdk'; -import { resolvedSyncPromise } from '@sentry/utils'; export class NoopTransport implements Transport { /** diff --git a/packages/node/test/integrations/linkederrors.test.ts b/packages/node/test/integrations/linkederrors.test.ts index 78509b8e08f8..c8b1d10b8f55 100644 --- a/packages/node/test/integrations/linkederrors.test.ts +++ b/packages/node/test/integrations/linkederrors.test.ts @@ -1,8 +1,8 @@ import { ExtendedError } from '@sentry/types'; +import { eventFromException } from '../../../browser/src'; import { Event } from '../../src'; import { LinkedErrors } from '../../src/integrations/linkederrors'; -import { eventFromException } from '../../../browser/src'; let linkedErrors: any; From 57ead624630c6a76a28fd4a67949f935c9a35d04 Mon Sep 17 00:00:00 2001 From: Abhijeet Prasad Date: Mon, 20 Dec 2021 13:13:51 -0500 Subject: [PATCH 17/17] add noop transport back in node --- packages/core/test/mocks/client.ts | 2 +- packages/node/src/client.ts | 28 ++++++++++++++++++++++++---- packages/node/test/handlers.test.ts | 4 ++-- 3 files changed, 27 insertions(+), 7 deletions(-) diff --git a/packages/core/test/mocks/client.ts b/packages/core/test/mocks/client.ts index 2b8ac4c229b8..c896c2d92e01 100644 --- a/packages/core/test/mocks/client.ts +++ b/packages/core/test/mocks/client.ts @@ -4,7 +4,7 @@ import { resolvedSyncPromise } from '@sentry/utils'; import { BaseClient } from '../../src/baseclient'; import { initAndBind } from '../../src/sdk'; -export class NoopTransport implements Transport { +class NoopTransport implements Transport { /** * @inheritDoc */ diff --git a/packages/node/src/client.ts b/packages/node/src/client.ts index e70423b05dd9..e00fd67bcf39 100644 --- a/packages/node/src/client.ts +++ b/packages/node/src/client.ts @@ -1,7 +1,7 @@ import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; import { SessionFlusher } from '@sentry/hub'; -import { Event, EventHint, SeverityLevel, Transport, TransportOptions } from '@sentry/types'; -import { Dsn, logger } from '@sentry/utils'; +import { Event, EventHint, Response, SeverityLevel, Transport, TransportOptions } from '@sentry/types'; +import { Dsn, logger, resolvedSyncPromise } from '@sentry/utils'; import { eventFromException, eventFromMessage } from './eventbuilder'; import { HTTPSTransport, HTTPTransport } from './transports'; @@ -102,6 +102,7 @@ export class NodeClient extends BaseClient { logger.warn('Cannot initialise an instance of SessionFlusher if no transport is initialized!'); return; } + if (!release) { logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); return; @@ -154,9 +155,9 @@ export class NodeClient extends BaseClient { /** * @inheritDoc */ - protected _setupTransport(): Transport | undefined { + protected _setupTransport(): Transport { if (!this._options.dsn) { - return undefined; + return new NoopTransport(); } const dsn = new Dsn(this._options.dsn); @@ -180,3 +181,22 @@ export class NodeClient extends BaseClient { return new HTTPSTransport(transportOptions); } } + +class NoopTransport implements Transport { + /** + * @inheritDoc + */ + public sendEvent(_: Event): PromiseLike { + return resolvedSyncPromise({ + reason: `NoopTransport: Event has been skipped because no Dsn is configured.`, + status: 'skipped', + }); + } + + /** + * @inheritDoc + */ + public close(_?: number): PromiseLike { + return resolvedSyncPromise(true); + } +} diff --git a/packages/node/test/handlers.test.ts b/packages/node/test/handlers.test.ts index daef81e4d44c..425fd9ffa424 100644 --- a/packages/node/test/handlers.test.ts +++ b/packages/node/test/handlers.test.ts @@ -2,11 +2,11 @@ import * as sentryCore from '@sentry/core'; import { Hub } from '@sentry/hub'; import * as sentryHub from '@sentry/hub'; import { Transaction } from '@sentry/tracing'; -import { Runtime } from '@sentry/types'; +import { Runtime, Transport, Response } from '@sentry/types'; import * as http from 'http'; import * as net from 'net'; -import { Event, Request, User } from '../src'; +import { Event, Request, User, Transports } from '../src'; import { NodeClient } from '../src/client'; import { errorHandler,