From 09b2736334fc78d4327885e7ab83d88dec98d90c Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 14 Dec 2021 21:27:11 +0100 Subject: [PATCH 01/12] ref: Refactorings for the logger to be less bloaty --- packages/integrations/src/captureconsole.ts | 8 ++ packages/utils/src/global.ts | 1 + packages/utils/src/logger.ts | 128 ++++++++------------ 3 files changed, 57 insertions(+), 80 deletions(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index 79b7c2431f51..9643b655f1ef 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -37,6 +37,9 @@ export class CaptureConsole implements Integration { return; } + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const rawConsole: { [key: string]: any } = {}; + this._levels.forEach((level: string) => { if (!(level in global.console)) { return; @@ -70,11 +73,16 @@ export class CaptureConsole implements Integration { }); } + rawConsole[level] = originalConsoleLevel; + // this fails for some browsers. :( if (originalConsoleLevel) { Function.prototype.apply.call(originalConsoleLevel, global.console, args); } }); }); + + // @ts-ignore we're stashing away the raw console here for later. + global.console.__rawConsole = rawConsole; } } diff --git a/packages/utils/src/global.ts b/packages/utils/src/global.ts index 4e63babf1dbd..1b4a1eee1bb7 100644 --- a/packages/utils/src/global.ts +++ b/packages/utils/src/global.ts @@ -11,6 +11,7 @@ import { isNodeEnv } from './node'; /** Internal */ interface SentryGlobal { + console: Console; Sentry?: { Integrations?: Integration[]; }; diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 9c4d366ecb62..3eef7a2ed4bb 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,6 +1,4 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { WrappedFunction } from '@sentry/types'; - import { getGlobalObject } from './global'; // TODO: Implement different loggers for different environments @@ -9,11 +7,6 @@ const global = getGlobalObject(); /** Prefix for logging strings */ const PREFIX = 'Sentry Logger '; -/** JSDoc */ -interface ExtensibleConsole extends Console { - [key: string]: any; -} - /** * Temporarily unwrap `console.log` and friends in order to perform the given callback using the original methods. * Restores wrapping after the callback completes. @@ -22,90 +15,65 @@ interface ExtensibleConsole extends Console { * @returns The results of the callback */ export function consoleSandbox(callback: () => any): any { - const global = getGlobalObject(); - const levels = ['debug', 'info', 'warn', 'error', 'log', 'assert']; - - if (!('console' in global)) { - return callback(); - } - - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - const originalConsole = (global as any).console as ExtensibleConsole; - const wrappedLevels: { [key: string]: any } = {}; - - // Restore all wrapped console methods - levels.forEach(level => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - if (level in (global as any).console && (originalConsole[level] as WrappedFunction).__sentry_original__) { - wrappedLevels[level] = originalConsole[level] as WrappedFunction; - originalConsole[level] = (originalConsole[level] as WrappedFunction).__sentry_original__; + let result; + const originalConsole = global.console; + if (originalConsole) { + result = callback(); + } else { + // @ts-ignore this is placed here by captureconsole.ts + const rawConsole = global.console.__rawConsole as Console; + + // @ts-ignore meh + global.console = rawConsole; + + try { + result = callback(); + } finally { + // @ts-ignore meh + global.console = originalConsole; } - }); + } - // Perform callback manipulations - const result = callback(); + return result; +} - // Revert restoration to wrapped state - Object.keys(wrappedLevels).forEach(level => { - originalConsole[level] = wrappedLevels[level]; +function makeLogger(): Logger { + let enabled = false; + const logger: Logger = { + enable: () => { + enabled = true; + }, + disable: () => { + enabled = false; + }, + } as any; + + ['log', 'warn', 'error'].forEach(name => { + // @ts-ignore meh + logger[name] = (...args: any[]) => { + if (enabled) { + consoleSandbox(() => { + // @ts-ignore meh + global.console[name](`${PREFIX}[${name}]: ${args.join(' ')}`); + }); + } + }; }); - return result; + return logger; } /** JSDoc */ -class Logger { - /** JSDoc */ - private _enabled: boolean; - - /** JSDoc */ - public constructor() { - this._enabled = false; - } - - /** JSDoc */ - public disable(): void { - this._enabled = false; - } - - /** JSDoc */ - public enable(): void { - this._enabled = true; - } - - /** JSDoc */ - public log(...args: any[]): void { - if (!this._enabled) { - return; - } - consoleSandbox(() => { - global.console.log(`${PREFIX}[Log]: ${args.join(' ')}`); - }); - } - - /** JSDoc */ - public warn(...args: any[]): void { - if (!this._enabled) { - return; - } - consoleSandbox(() => { - global.console.warn(`${PREFIX}[Warn]: ${args.join(' ')}`); - }); - } - - /** JSDoc */ - public error(...args: any[]): void { - if (!this._enabled) { - return; - } - consoleSandbox(() => { - global.console.error(`${PREFIX}[Error]: ${args.join(' ')}`); - }); - } +interface Logger { + disable(): void; + enable(): void; + log(...args: any[]): void; + warn(...args: any[]): void; + error(...args: any[]): void; } // Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used global.__SENTRY__ = global.__SENTRY__ || {}; -const logger = (global.__SENTRY__.logger as Logger) || (global.__SENTRY__.logger = new Logger()); +const logger = (global.__SENTRY__.logger as Logger) || (global.__SENTRY__.logger = makeLogger()); export { logger }; From 657da5e9f2350060e3c35d2704bba2bbfe22f792 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 14 Dec 2021 21:58:07 +0100 Subject: [PATCH 02/12] feat: disable the logger on disabled debug mode --- packages/integrations/src/captureconsole.ts | 2 +- packages/utils/src/logger.ts | 41 +++++++++++++-------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index 9643b655f1ef..12669cf63c65 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -83,6 +83,6 @@ export class CaptureConsole implements Integration { }); // @ts-ignore we're stashing away the raw console here for later. - global.console.__rawConsole = rawConsole; + global.console.__orig = rawConsole; } } diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 3eef7a2ed4bb..f0ce4de0e129 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,5 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { getGlobalObject } from './global'; +import { isDebugBuild } from './env'; // TODO: Implement different loggers for different environments const global = getGlobalObject(); @@ -21,7 +22,7 @@ export function consoleSandbox(callback: () => any): any { result = callback(); } else { // @ts-ignore this is placed here by captureconsole.ts - const rawConsole = global.console.__rawConsole as Console; + const rawConsole = global.console.__orig as Console; // @ts-ignore meh global.console = rawConsole; @@ -41,24 +42,34 @@ function makeLogger(): Logger { let enabled = false; const logger: Logger = { enable: () => { - enabled = true; + enabled = !isDebugBuild(); }, disable: () => { enabled = false; }, } as any; - ['log', 'warn', 'error'].forEach(name => { - // @ts-ignore meh - logger[name] = (...args: any[]) => { - if (enabled) { - consoleSandbox(() => { - // @ts-ignore meh - global.console[name](`${PREFIX}[${name}]: ${args.join(' ')}`); - }); - } - }; - }); + const methods = ['log', 'warn', 'error']; + + if (isDebugBuild()) { + methods.forEach(name => { + // @ts-ignore meh + logger[name] = (...args: any[]) => { + if (enabled) { + consoleSandbox(() => { + // @ts-ignore meh + global.console[name](`${PREFIX}[${name}]:`, ...args); + }); + } + }; + }); + } else { + methods.forEach(name => { + // @ts-ignore meh + // eslint-disable-next-line @typescript-eslint/no-empty-function + logger[name] = function() {}; + }); + } return logger; } @@ -73,7 +84,7 @@ interface Logger { } // Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used -global.__SENTRY__ = global.__SENTRY__ || {}; -const logger = (global.__SENTRY__.logger as Logger) || (global.__SENTRY__.logger = makeLogger()); +const sentry = (global.__SENTRY__ = global.__SENTRY__ || {}); +const logger = (sentry.logger as Logger) || (sentry.logger = makeLogger()); export { logger }; From ae2804416f293c1d1ae1695b4ef4fa24bb58be9e Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 14 Dec 2021 22:23:08 +0100 Subject: [PATCH 03/12] feat: Disable a lot of debug logs in non debug builds --- packages/browser/src/helpers.ts | 10 ++-- packages/browser/src/integrations/dedupe.ts | 6 ++- packages/browser/src/sdk.ts | 14 ++++-- packages/browser/src/transports/base.ts | 17 +++++-- packages/browser/src/transports/utils.ts | 6 ++- packages/core/src/basebackend.ts | 16 +++++-- packages/core/src/baseclient.ts | 21 +++++++-- packages/core/src/integration.ts | 6 ++- .../core/src/integrations/inboundfilters.ts | 46 ++++++++++++------- packages/core/src/sdk.ts | 6 ++- packages/hub/src/sessionflusher.ts | 10 ++-- packages/integrations/src/dedupe.ts | 6 ++- packages/integrations/src/extraerrordata.ts | 6 ++- packages/utils/src/instrument.ts | 5 +- packages/utils/src/supports.ts | 5 +- 15 files changed, 126 insertions(+), 54 deletions(-) diff --git a/packages/browser/src/helpers.ts b/packages/browser/src/helpers.ts index 773c933eb1cf..d062c68b070c 100644 --- a/packages/browser/src/helpers.ts +++ b/packages/browser/src/helpers.ts @@ -1,6 +1,6 @@ import { captureException, getReportDialogEndpoint, withScope } from '@sentry/core'; import { DsnLike, Event as SentryEvent, Mechanism, Scope, WrappedFunction } from '@sentry/types'; -import { addExceptionMechanism, addExceptionTypeValue, getGlobalObject, logger } from '@sentry/utils'; +import { addExceptionMechanism, addExceptionTypeValue, getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; const global = getGlobalObject(); let ignoreOnError: number = 0; @@ -199,12 +199,16 @@ export function injectReportDialog(options: ReportDialogOptions = {}): void { } if (!options.eventId) { - logger.error(`Missing eventId option in showReportDialog call`); + if (isDebugBuild()) { + logger.error(`Missing eventId option in showReportDialog call`); + } return; } if (!options.dsn) { - logger.error(`Missing dsn option in showReportDialog call`); + if (isDebugBuild()) { + logger.error(`Missing dsn option in showReportDialog call`); + } return; } diff --git a/packages/browser/src/integrations/dedupe.ts b/packages/browser/src/integrations/dedupe.ts index 07fe3eccfb6a..62ef059c3a4c 100644 --- a/packages/browser/src/integrations/dedupe.ts +++ b/packages/browser/src/integrations/dedupe.ts @@ -1,5 +1,5 @@ import { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; -import { logger } from '@sentry/utils'; +import { isDebugBuild, logger } from '@sentry/utils'; /** Deduplication filter */ export class Dedupe implements Integration { @@ -28,7 +28,9 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (self._shouldDropEvent(currentEvent, self._previousEvent)) { - logger.warn(`Event dropped due to being a duplicate of previously captured event.`); + if (isDebugBuild()) { + logger.warn(`Event dropped due to being a duplicate of previously captured event.`); + } return null; } } catch (_oO) { diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 518052ac71ad..749c85744a03 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -1,5 +1,5 @@ import { getCurrentHub, initAndBind, Integrations as CoreIntegrations } from '@sentry/core'; -import { addInstrumentationHandler, getGlobalObject, logger, SyncPromise } from '@sentry/utils'; +import { addInstrumentationHandler, getGlobalObject, isDebugBuild, logger, SyncPromise } from '@sentry/utils'; import { BrowserOptions } from './backend'; import { BrowserClient } from './client'; @@ -161,7 +161,9 @@ export function flush(timeout?: number): PromiseLike { if (client) { return client.flush(timeout); } - logger.warn('Cannot flush events. No client defined.'); + if (isDebugBuild()) { + logger.warn('Cannot flush events. No client defined.'); + } return SyncPromise.resolve(false); } @@ -178,7 +180,9 @@ export function close(timeout?: number): PromiseLike { if (client) { return client.close(timeout); } - logger.warn('Cannot flush events and disable SDK. No client defined.'); + if (isDebugBuild()) { + logger.warn('Cannot flush events and disable SDK. No client defined.'); + } return SyncPromise.resolve(false); } @@ -202,7 +206,9 @@ function startSessionTracking(): void { const document = window.document; if (typeof document === 'undefined') { - logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); + if (isDebugBuild()) { + logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); + } return; } diff --git a/packages/browser/src/transports/base.ts b/packages/browser/src/transports/base.ts index 8fd960593ac5..9eeb8ec77a14 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -16,6 +16,7 @@ import { import { dateTimestampInSeconds, getGlobalObject, + isDebugBuild, logger, parseRetryAfterHeader, PromiseBuffer, @@ -94,7 +95,9 @@ export abstract class BaseTransport implements Transport { // A correct type for map-based implementation if we want to go that route // would be `Partial>>>` const key = `${CATEGORY_MAPPING[category]}:${reason}`; - logger.log(`Adding outcome: ${key}`); + if (isDebugBuild()) { + logger.log(`Adding outcome: ${key}`); + } this._outcomes[key] = (this._outcomes[key] ?? 0) + 1; } @@ -111,11 +114,15 @@ export abstract class BaseTransport implements Transport { // Nothing to send if (!Object.keys(outcomes).length) { - logger.log('No outcomes to flush'); + if (isDebugBuild()) { + logger.log('No outcomes to flush'); + } return; } - logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); + if (isDebugBuild()) { + logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); + } const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn, this._api.tunnel); // Envelope header is required to be at least an empty object @@ -166,7 +173,9 @@ export abstract class BaseTransport implements Transport { */ const limited = this._handleRateLimit(headers); if (limited) - logger.warn(`Too many ${requestType} requests, backing off until: ${this._disabledUntil(requestType)}`); + if (isDebugBuild()) { + logger.warn(`Too many ${requestType} requests, backing off until: ${this._disabledUntil(requestType)}`); + } if (status === Status.Success) { resolve({ status }); diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index 336ed942a2ec..d6911ab3d78e 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -1,4 +1,4 @@ -import { forget, getGlobalObject, isNativeFetch, logger, supportsFetch } from '@sentry/utils'; +import { forget, getGlobalObject, isDebugBuild, isNativeFetch, logger, supportsFetch } from '@sentry/utils'; const global = getGlobalObject(); let cachedFetchImpl: FetchImpl; @@ -68,7 +68,9 @@ export function getNativeFetchImplementation(): FetchImpl { } document.head.removeChild(sandbox); } catch (e) { - logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); + if (isDebugBuild()) { + logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); + } } } diff --git a/packages/core/src/basebackend.ts b/packages/core/src/basebackend.ts index eb7e598a02ad..024cad6e466a 100644 --- a/packages/core/src/basebackend.ts +++ b/packages/core/src/basebackend.ts @@ -1,5 +1,5 @@ import { Event, EventHint, Options, Session, Severity, Transport } from '@sentry/types'; -import { logger, SentryError } from '@sentry/utils'; +import { isDebugBuild, logger, SentryError } from '@sentry/utils'; import { NoopTransport } from './transports/noop'; @@ -66,7 +66,7 @@ export abstract class BaseBackend implements Backend { /** Creates a new backend instance. */ public constructor(options: O) { this._options = options; - if (!this._options.dsn) { + if (isDebugBuild() && !this._options.dsn) { logger.warn('No DSN provided, backend will not do anything.'); } this._transport = this._setupTransport(); @@ -92,7 +92,9 @@ export abstract class BaseBackend implements Backend { */ public sendEvent(event: Event): void { void this._transport.sendEvent(event).then(null, reason => { - logger.error(`Error while sending event: ${reason}`); + if (isDebugBuild()) { + logger.error(`Error while sending event: ${reason}`); + } }); } @@ -101,12 +103,16 @@ export abstract class BaseBackend implements Backend { */ public sendSession(session: Session): void { if (!this._transport.sendSession) { - logger.warn("Dropping session because custom transport doesn't implement sendSession"); + if (isDebugBuild()) { + 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}`); + if (isDebugBuild()) { + logger.error(`Error while sending session: ${reason}`); + } }); } diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 1b58ad5c318f..115dfb6a0929 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -16,6 +16,7 @@ import { checkOrSetAlreadyCaught, dateTimestampInSeconds, Dsn, + isDebugBuild, isPlainObject, isPrimitive, isThenable, @@ -106,7 +107,9 @@ export abstract class BaseClient implement public captureException(exception: any, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (checkOrSetAlreadyCaught(exception)) { - logger.log(ALREADY_SEEN_ERROR); + if (isDebugBuild()) { + logger.log(ALREADY_SEEN_ERROR); + } return; } @@ -151,7 +154,9 @@ export abstract class BaseClient implement public captureEvent(event: Event, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (hint?.originalException && checkOrSetAlreadyCaught(hint.originalException)) { - logger.log(ALREADY_SEEN_ERROR); + if (isDebugBuild()) { + logger.log(ALREADY_SEEN_ERROR); + } return; } @@ -171,12 +176,16 @@ export abstract class BaseClient implement */ public captureSession(session: Session): void { if (!this._isEnabled()) { - logger.warn('SDK not enabled, will not capture session.'); + if (isDebugBuild()) { + logger.warn('SDK not enabled, will not capture session.'); + } return; } if (!(typeof session.release === 'string')) { - logger.warn('Discarded session because of missing or non-string release'); + if (isDebugBuild()) { + logger.warn('Discarded session because of missing or non-string release'); + } } else { this._sendSession(session); // After sending, we set init false to indicate it's not the first occurrence @@ -242,7 +251,9 @@ export abstract class BaseClient implement try { return (this._integrations[integration.id] as T) || null; } catch (_oO) { - logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); + if (isDebugBuild()) { + logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); + } return null; } } diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 1eea0a2d1084..b647d0f4ca83 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,6 +1,6 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Integration, Options } from '@sentry/types'; -import { logger } from '@sentry/utils'; +import { isDebugBuild, logger } from '@sentry/utils'; export const installedIntegrations: string[] = []; @@ -59,7 +59,9 @@ export function setupIntegration(integration: Integration): void { } integration.setupOnce(addGlobalEventProcessor, getCurrentHub); installedIntegrations.push(integration.name); - logger.log(`Integration installed: ${integration.name}`); + if (isDebugBuild()) { + logger.log(`Integration installed: ${integration.name}`); + } } /** diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index ca4135545c39..1ebee189c1e7 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -1,6 +1,6 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Event, Integration, StackFrame } from '@sentry/types'; -import { getEventDescription, isMatchingPattern, logger } from '@sentry/utils'; +import { getEventDescription, isDebugBuild, isMatchingPattern, logger } from '@sentry/utils'; // "Script error." is hard coded into browsers for errors that it can't read. // this is the result of a script being pulled in from an external domain and CORS. @@ -64,29 +64,37 @@ export class InboundFilters implements Integration { /** JSDoc */ private _shouldDropEvent(event: Event, options: Partial): boolean { if (this._isSentryError(event, options)) { - logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); + if (isDebugBuild()) { + logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); + } return true; } if (this._isIgnoredError(event, options)) { - logger.warn( - `Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`, - ); + if (isDebugBuild()) { + logger.warn( + `Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`, + ); + } return true; } if (this._isDeniedUrl(event, options)) { - logger.warn( - `Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription( - event, - )}.\nUrl: ${this._getEventFilterUrl(event)}`, - ); + if (isDebugBuild()) { + logger.warn( + `Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription( + event, + )}.\nUrl: ${this._getEventFilterUrl(event)}`, + ); + } return true; } if (!this._isAllowedUrl(event, options)) { - logger.warn( - `Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription( - event, - )}.\nUrl: ${this._getEventFilterUrl(event)}`, - ); + if (isDebugBuild()) { + logger.warn( + `Event dropped due to not being matched by \`allowUrls\` option.\nEvent: ${getEventDescription( + event, + )}.\nUrl: ${this._getEventFilterUrl(event)}`, + ); + } return true; } return false; @@ -182,7 +190,9 @@ export class InboundFilters implements Integration { const { type = '', value = '' } = (event.exception.values && event.exception.values[0]) || {}; return [`${value}`, `${type}: ${value}`]; } catch (oO) { - logger.error(`Cannot extract message for event ${getEventDescription(event)}`); + if (isDebugBuild()) { + logger.error(`Cannot extract message for event ${getEventDescription(event)}`); + } return []; } } @@ -216,7 +226,9 @@ export class InboundFilters implements Integration { } return null; } catch (oO) { - logger.error(`Cannot extract url for event ${getEventDescription(event)}`); + if (isDebugBuild()) { + logger.error(`Cannot extract url for event ${getEventDescription(event)}`); + } return null; } } diff --git a/packages/core/src/sdk.ts b/packages/core/src/sdk.ts index f674a3e900f4..637f36267cd3 100644 --- a/packages/core/src/sdk.ts +++ b/packages/core/src/sdk.ts @@ -1,6 +1,6 @@ import { getCurrentHub } from '@sentry/hub'; import { Client, Options } from '@sentry/types'; -import { logger } from '@sentry/utils'; +import { isDebugBuild, logger } from '@sentry/utils'; /** A class object that can instantiate Client objects. */ export type ClientClass = new (options: O) => F; @@ -14,6 +14,10 @@ export type ClientClass = new (options: O) */ export function initAndBind(clientClass: ClientClass, options: O): void { if (options.debug === true) { + if (!isDebugBuild()) { + // eslint-disable-next-line no-console + console.warn('warning: non debug Sentry SDK loaded, debug mode unavailable!'); + } logger.enable(); } const hub = getCurrentHub(); diff --git a/packages/hub/src/sessionflusher.ts b/packages/hub/src/sessionflusher.ts index f3571f24ec0a..8d6766955ae6 100644 --- a/packages/hub/src/sessionflusher.ts +++ b/packages/hub/src/sessionflusher.ts @@ -5,7 +5,7 @@ import { SessionFlusherLike, Transport, } from '@sentry/types'; -import { dropUndefinedKeys, logger } from '@sentry/utils'; +import { dropUndefinedKeys, isDebugBuild, logger } from '@sentry/utils'; import { getCurrentHub } from './hub'; @@ -35,11 +35,15 @@ export class SessionFlusher implements SessionFlusherLike { /** Sends session aggregates to Transport */ public sendSessionAggregates(sessionAggregates: SessionAggregates): void { if (!this._transport.sendSession) { - logger.warn("Dropping session because custom transport doesn't implement sendSession"); + if (isDebugBuild()) { + logger.warn("Dropping session because custom transport doesn't implement sendSession"); + } return; } void this._transport.sendSession(sessionAggregates).then(null, reason => { - logger.error(`Error while sending session: ${reason}`); + if (isDebugBuild()) { + logger.error(`Error while sending session: ${reason}`); + } }); } diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index 07fe3eccfb6a..62ef059c3a4c 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,5 +1,5 @@ import { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; -import { logger } from '@sentry/utils'; +import { isDebugBuild, logger } from '@sentry/utils'; /** Deduplication filter */ export class Dedupe implements Integration { @@ -28,7 +28,9 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (self._shouldDropEvent(currentEvent, self._previousEvent)) { - logger.warn(`Event dropped due to being a duplicate of previously captured event.`); + if (isDebugBuild()) { + logger.warn(`Event dropped due to being a duplicate of previously captured event.`); + } return null; } } catch (_oO) { diff --git a/packages/integrations/src/extraerrordata.ts b/packages/integrations/src/extraerrordata.ts index de01df6605c0..fee6e13c14d6 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,5 +1,5 @@ import { Event, EventHint, EventProcessor, ExtendedError, Hub, Integration } from '@sentry/types'; -import { isError, isPlainObject, logger, normalize } from '@sentry/utils'; +import { isDebugBuild, isError, isPlainObject, logger, normalize } from '@sentry/utils'; /** JSDoc */ interface ExtraErrorDataOptions { @@ -112,7 +112,9 @@ export class ExtraErrorData implements Integration { return extraErrorInfo; } catch (oO) { - logger.error('Unable to extract extra data from the Error object:', oO); + if (isDebugBuild()) { + logger.error('Unable to extract extra data from the Error object:', oO); + } } return null; diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index 18dce47726f9..e4ec42e9570d 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -2,6 +2,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ import { WrappedFunction } from '@sentry/types'; +import { isDebugBuild } from '.'; import { getGlobalObject } from './global'; import { isInstanceOf, isString } from './is'; @@ -73,7 +74,9 @@ function instrument(type: InstrumentHandlerType): void { instrumentUnhandledRejection(); break; default: - logger.warn('unknown instrumentation type:', type); + if (isDebugBuild()) { + logger.warn('unknown instrumentation type:', type); + } } } diff --git a/packages/utils/src/supports.ts b/packages/utils/src/supports.ts index 1a548b45f0d0..d422df7622a2 100644 --- a/packages/utils/src/supports.ts +++ b/packages/utils/src/supports.ts @@ -1,3 +1,4 @@ +import { isDebugBuild } from '.'; import { getGlobalObject } from './global'; import { logger } from './logger'; @@ -112,7 +113,9 @@ export function supportsNativeFetch(): boolean { } doc.head.removeChild(sandbox); } catch (err) { - logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err); + if (isDebugBuild()) { + logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err); + } } } From 77ca75ecd2e818d1708e068780bb4de0d38e3e49 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Tue, 14 Dec 2021 23:33:48 +0100 Subject: [PATCH 04/12] fix: lint --- packages/utils/src/instrument.ts | 2 +- packages/utils/src/logger.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index e4ec42e9570d..245ef7055df7 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -2,8 +2,8 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/ban-types */ import { WrappedFunction } from '@sentry/types'; -import { isDebugBuild } from '.'; +import { isDebugBuild } from '.'; import { getGlobalObject } from './global'; import { isInstanceOf, isString } from './is'; import { logger } from './logger'; diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index f0ce4de0e129..916b3d2eb10c 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ -import { getGlobalObject } from './global'; import { isDebugBuild } from './env'; +import { getGlobalObject } from './global'; // TODO: Implement different loggers for different environments const global = getGlobalObject(); From 4e493c7db865c11a25c902568a419241aa0db43b Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 15 Dec 2021 14:18:30 +0100 Subject: [PATCH 05/12] ref: slightly less weird code for console sandbox --- packages/integrations/src/captureconsole.ts | 3 +-- packages/utils/src/logger.ts | 23 ++++++++------------- 2 files changed, 10 insertions(+), 16 deletions(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index 12669cf63c65..055e6517fa22 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -37,8 +37,7 @@ export class CaptureConsole implements Integration { return; } - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const rawConsole: { [key: string]: any } = {}; + const rawConsole: { [key: string]: () => any } = {}; this._levels.forEach((level: string) => { if (!(level in global.console)) { diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 916b3d2eb10c..0b398f88c402 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -16,26 +16,21 @@ const PREFIX = 'Sentry Logger '; * @returns The results of the callback */ export function consoleSandbox(callback: () => any): any { - let result; - const originalConsole = global.console; - if (originalConsole) { - result = callback(); + const currentConsole = global.console; + // @ts-ignore this is placed here by captureconsole.ts + const rawConsole = currentConsole.__orig as Console; + if (!rawConsole) { + return callback(); } else { - // @ts-ignore this is placed here by captureconsole.ts - const rawConsole = global.console.__orig as Console; - - // @ts-ignore meh + // @ts-ignore this is in fact writable global.console = rawConsole; - try { - result = callback(); + return callback(); } finally { - // @ts-ignore meh - global.console = originalConsole; + // @ts-ignore this is in fact writable + global.console = currentConsole; } } - - return result; } function makeLogger(): Logger { From e861b7a55617b39046d88d9c8e1cab5d8652da10 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 15 Dec 2021 14:22:10 +0100 Subject: [PATCH 06/12] fix: copy all console methods over --- packages/integrations/src/captureconsole.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index 055e6517fa22..00091cbfe114 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -37,7 +37,7 @@ export class CaptureConsole implements Integration { return; } - const rawConsole: { [key: string]: () => any } = {}; + const rawConsole: { [key: string]: unknown } = { ...console }; this._levels.forEach((level: string) => { if (!(level in global.console)) { From 3035368c56c242e817d437f5d435067c350bce77 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 15 Dec 2021 14:38:28 +0100 Subject: [PATCH 07/12] ref: simplify console sandbox --- packages/integrations/src/captureconsole.ts | 11 ++----- packages/utils/src/logger.ts | 33 +++++++++++---------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index 00091cbfe114..d31319a14dd5 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -1,5 +1,5 @@ import { EventProcessor, Hub, Integration, Severity } from '@sentry/types'; -import { fill, getGlobalObject, safeJoin } from '@sentry/utils'; +import { fill, getGlobalObject, safeJoin, bypassConsoleInstrumentation } from '@sentry/utils'; const global = getGlobalObject(); @@ -37,8 +37,6 @@ export class CaptureConsole implements Integration { return; } - const rawConsole: { [key: string]: unknown } = { ...console }; - this._levels.forEach((level: string) => { if (!(level in global.console)) { return; @@ -48,7 +46,7 @@ export class CaptureConsole implements Integration { fill(global.console, level, (originalConsoleLevel: () => any) => (...args: any[]): void => { const hub = getCurrentHub(); - if (hub.getIntegration(CaptureConsole)) { + if (hub.getIntegration(CaptureConsole) && !bypassConsoleInstrumentation()) { hub.withScope(scope => { scope.setLevel(Severity.fromString(level)); scope.setExtra('arguments', args); @@ -72,16 +70,11 @@ export class CaptureConsole implements Integration { }); } - rawConsole[level] = originalConsoleLevel; - // this fails for some browsers. :( if (originalConsoleLevel) { Function.prototype.apply.call(originalConsoleLevel, global.console, args); } }); }); - - // @ts-ignore we're stashing away the raw console here for later. - global.console.__orig = rawConsole; } } diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 0b398f88c402..6dbe4b529b53 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -8,28 +8,31 @@ const global = getGlobalObject(); /** Prefix for logging strings */ const PREFIX = 'Sentry Logger '; +let _bypassConsoleInstrumentation = false; + /** - * Temporarily unwrap `console.log` and friends in order to perform the given callback using the original methods. - * Restores wrapping after the callback completes. + * Returns true if the console should be bypassed. This is used by the + * captureconsole integration to disable itself. + * + * @returns true if the console instrumentation is bypassed. + */ +export function bypassConsoleInstrumentation(): boolean { + return _bypassConsoleInstrumentation; +} + +/** + * Temporarily disable sentry console instrumentations. * * @param callback The function to run against the original `console` messages * @returns The results of the callback */ export function consoleSandbox(callback: () => any): any { - const currentConsole = global.console; - // @ts-ignore this is placed here by captureconsole.ts - const rawConsole = currentConsole.__orig as Console; - if (!rawConsole) { + const old = _bypassConsoleInstrumentation; + _bypassConsoleInstrumentation = true; + try { return callback(); - } else { - // @ts-ignore this is in fact writable - global.console = rawConsole; - try { - return callback(); - } finally { - // @ts-ignore this is in fact writable - global.console = currentConsole; - } + } finally { + _bypassConsoleInstrumentation = old; } } From 468402256fe96a28315d68124b12e61076325d2d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Wed, 15 Dec 2021 14:59:10 +0100 Subject: [PATCH 08/12] fix: lint --- packages/integrations/src/captureconsole.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/integrations/src/captureconsole.ts b/packages/integrations/src/captureconsole.ts index d31319a14dd5..c026820de041 100644 --- a/packages/integrations/src/captureconsole.ts +++ b/packages/integrations/src/captureconsole.ts @@ -1,5 +1,5 @@ import { EventProcessor, Hub, Integration, Severity } from '@sentry/types'; -import { fill, getGlobalObject, safeJoin, bypassConsoleInstrumentation } from '@sentry/utils'; +import { bypassConsoleInstrumentation, fill, getGlobalObject, safeJoin } from '@sentry/utils'; const global = getGlobalObject(); From dbc96f0a1cbe1bfd2f75e06dacd7c65a586057a1 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 17 Dec 2021 12:38:23 +0100 Subject: [PATCH 09/12] fix: remember integrations globally --- packages/core/src/integration.ts | 10 +++++++--- packages/utils/src/global.ts | 1 + 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 148d22622d32..bec3e36fd152 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,8 +1,12 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Integration, Options } from '@sentry/types'; -import { addNonEnumerableProperty, isDebugBuild, logger } from '@sentry/utils'; +import { addNonEnumerableProperty, isDebugBuild, logger, getGlobalObject } from '@sentry/utils'; -export const installedIntegrations: string[] = []; +// we have to remember integrations globally on the __SENTRY__ object in case +// sentry is bundled twice. In that case integrations would patch over themselves. +const global = getGlobalObject(); +const sentry = (global.__SENTRY__ = global.__SENTRY__ || {}); +const installedIntegrations = sentry.patchedIntegrations || (sentry.patchedIntegrations = []); /** Map of integrations assigned to a client */ export type IntegrationIndex = { @@ -54,7 +58,7 @@ export function getIntegrationsToSetup(options: Options): Integration[] { /** Setup given integration */ export function setupIntegration(integration: Integration): void { - if (installedIntegrations.indexOf(integration.name) !== -1) { + if (installedIntegrations.indexOf(integration.name) >= 0) { return; } integration.setupOnce(addGlobalEventProcessor, getCurrentHub); diff --git a/packages/utils/src/global.ts b/packages/utils/src/global.ts index 1b4a1eee1bb7..dffbc59b0ab1 100644 --- a/packages/utils/src/global.ts +++ b/packages/utils/src/global.ts @@ -24,6 +24,7 @@ interface SentryGlobal { globalEventProcessors: any; hub: any; logger: any; + patchedIntegrations?: Array; }; } From a70ac85d38997cf5b363bab03b857de0df18526e Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 17 Dec 2021 13:32:38 +0100 Subject: [PATCH 10/12] ref: try to refactor the use of global singletons --- packages/core/src/integration.ts | 12 ++++++------ packages/hub/src/hub.ts | 15 ++++++++------- packages/hub/src/scope.ts | 9 ++------- packages/utils/src/global.ts | 17 +++++++++++++++-- packages/utils/src/logger.ts | 5 ++--- 5 files changed, 33 insertions(+), 25 deletions(-) diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index bec3e36fd152..5f638b3520b6 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,12 +1,12 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Integration, Options } from '@sentry/types'; -import { addNonEnumerableProperty, isDebugBuild, logger, getGlobalObject } from '@sentry/utils'; +import { addNonEnumerableProperty, isDebugBuild, logger, getGlobalSingleton } from '@sentry/utils'; // we have to remember integrations globally on the __SENTRY__ object in case // sentry is bundled twice. In that case integrations would patch over themselves. -const global = getGlobalObject(); -const sentry = (global.__SENTRY__ = global.__SENTRY__ || {}); -const installedIntegrations = sentry.patchedIntegrations || (sentry.patchedIntegrations = []); +// this is problematic because it's unclear if sentry versions will agree on this +// behavior. There are likely to be better ways to accomplish this. +const onceInitializedIntegrations: Array = getGlobalSingleton('_integrations', () => []); /** Map of integrations assigned to a client */ export type IntegrationIndex = { @@ -58,11 +58,11 @@ export function getIntegrationsToSetup(options: Options): Integration[] { /** Setup given integration */ export function setupIntegration(integration: Integration): void { - if (installedIntegrations.indexOf(integration.name) >= 0) { + if (onceInitializedIntegrations.indexOf(integration.name) >= 0) { return; } integration.setupOnce(addGlobalEventProcessor, getCurrentHub); - installedIntegrations.push(integration.name); + onceInitializedIntegrations.push(integration.name); if (isDebugBuild()) { logger.log(`Integration installed: ${integration.name}`); } diff --git a/packages/hub/src/hub.ts b/packages/hub/src/hub.ts index c7fd4cac85e4..40986a898e95 100644 --- a/packages/hub/src/hub.ts +++ b/packages/hub/src/hub.ts @@ -20,6 +20,7 @@ import { TransactionContext, User, } from '@sentry/types'; +import { getGlobalSingleton } from '@sentry/utils'; import { consoleSandbox, dateTimestampInSeconds, getGlobalObject, isNodeEnv, logger, uuid4 } from '@sentry/utils'; import { Scope } from './scope'; @@ -515,7 +516,10 @@ export class Hub implements HubInterface { * at the call-site. We always access the carrier through this function, so we can guarantee that `__SENTRY__` is there. **/ export function getMainCarrier(): Carrier { - const carrier = getGlobalObject(); + // FIXME: this makes no sense. getGlobalObject return value's __SENTRY__ + // type does not match up with the carrier's __SENTRY__ type. This all + // needs cleaning up. + const carrier = getGlobalObject() as Carrier; carrier.__SENTRY__ = carrier.__SENTRY__ || { extensions: {}, hub: undefined, @@ -616,10 +620,7 @@ function hasHubOnCarrier(carrier: Carrier): boolean { * @hidden */ export function getHubFromCarrier(carrier: Carrier): Hub { - if (carrier && carrier.__SENTRY__ && carrier.__SENTRY__.hub) return carrier.__SENTRY__.hub; - carrier.__SENTRY__ = carrier.__SENTRY__ || {}; - carrier.__SENTRY__.hub = new Hub(); - return carrier.__SENTRY__.hub; + return getGlobalSingleton('hub', () => new Hub(), carrier); } /** @@ -630,7 +631,7 @@ export function getHubFromCarrier(carrier: Carrier): Hub { */ export function setHubOnCarrier(carrier: Carrier, hub: Hub): boolean { if (!carrier) return false; - carrier.__SENTRY__ = carrier.__SENTRY__ || {}; - carrier.__SENTRY__.hub = hub; + const sentry = (carrier.__SENTRY__ = carrier.__SENTRY__ || {}); + sentry.hub = hub; return true; } diff --git a/packages/hub/src/scope.ts b/packages/hub/src/scope.ts index 940d0443c9f7..116583c3f7ce 100644 --- a/packages/hub/src/scope.ts +++ b/packages/hub/src/scope.ts @@ -18,7 +18,7 @@ import { Transaction, User, } from '@sentry/types'; -import { dateTimestampInSeconds, getGlobalObject, isPlainObject, isThenable, SyncPromise } from '@sentry/utils'; +import { dateTimestampInSeconds, getGlobalSingleton, isPlainObject, isThenable, SyncPromise } from '@sentry/utils'; import { Session } from './session'; @@ -516,12 +516,7 @@ export class Scope implements ScopeInterface { * Returns the global event processors. */ function getGlobalEventProcessors(): EventProcessor[] { - /* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */ - const global = getGlobalObject(); - global.__SENTRY__ = global.__SENTRY__ || {}; - global.__SENTRY__.globalEventProcessors = global.__SENTRY__.globalEventProcessors || []; - return global.__SENTRY__.globalEventProcessors; - /* eslint-enable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access */ + return getGlobalSingleton('globalEventProcessors', () => []); } /** diff --git a/packages/utils/src/global.ts b/packages/utils/src/global.ts index dffbc59b0ab1..194da048d3b0 100644 --- a/packages/utils/src/global.ts +++ b/packages/utils/src/global.ts @@ -23,8 +23,8 @@ interface SentryGlobal { __SENTRY__: { globalEventProcessors: any; hub: any; - logger: any; - patchedIntegrations?: Array; + logger?: any; + _integrations?: Array; }; } @@ -44,3 +44,16 @@ export function getGlobalObject(): T & SentryGlobal { ? self : fallbackGlobalObject) as T & SentryGlobal; } + +/** + * Retains a global singleton. + * + * @param name name of the global singleton on __SENTRY__ + * @param creator creation function + * @returns the singleton + */ +export function getGlobalSingleton(name: keyof SentryGlobal['__SENTRY__'], creator: () => T, obj?: unknown): T { + const global = (obj || getGlobalObject()) as SentryGlobal; + const sentry = (global.__SENTRY__ = global.__SENTRY__ || {}); + return sentry[name] || sentry[name] == creator(); +} diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 6dbe4b529b53..1218726e6165 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,6 +1,6 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { isDebugBuild } from './env'; -import { getGlobalObject } from './global'; +import { getGlobalObject, getGlobalSingleton } from './global'; // TODO: Implement different loggers for different environments const global = getGlobalObject(); @@ -82,7 +82,6 @@ interface Logger { } // Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used -const sentry = (global.__SENTRY__ = global.__SENTRY__ || {}); -const logger = (sentry.logger as Logger) || (sentry.logger = makeLogger()); +const logger = getGlobalSingleton('logger', makeLogger); export { logger }; From 9f52f2e110b2daa612d0ed7e87a94f08320af2b0 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 17 Dec 2021 13:49:35 +0100 Subject: [PATCH 11/12] fix: getGlobalSingleton --- packages/core/src/integration.ts | 2 +- packages/hub/src/hub.ts | 11 +++++++++-- packages/utils/src/global.ts | 2 +- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 5f638b3520b6..cd3dd4128328 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,6 +1,6 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Integration, Options } from '@sentry/types'; -import { addNonEnumerableProperty, isDebugBuild, logger, getGlobalSingleton } from '@sentry/utils'; +import { addNonEnumerableProperty, getGlobalSingleton, isDebugBuild, logger } from '@sentry/utils'; // we have to remember integrations globally on the __SENTRY__ object in case // sentry is bundled twice. In that case integrations would patch over themselves. diff --git a/packages/hub/src/hub.ts b/packages/hub/src/hub.ts index 40986a898e95..57ce451daad7 100644 --- a/packages/hub/src/hub.ts +++ b/packages/hub/src/hub.ts @@ -20,8 +20,15 @@ import { TransactionContext, User, } from '@sentry/types'; -import { getGlobalSingleton } from '@sentry/utils'; -import { consoleSandbox, dateTimestampInSeconds, getGlobalObject, isNodeEnv, logger, uuid4 } from '@sentry/utils'; +import { + consoleSandbox, + dateTimestampInSeconds, + getGlobalObject, + getGlobalSingleton, + isNodeEnv, + logger, + uuid4, +} from '@sentry/utils'; import { Scope } from './scope'; import { Session } from './session'; diff --git a/packages/utils/src/global.ts b/packages/utils/src/global.ts index 194da048d3b0..1c72c4c9faa5 100644 --- a/packages/utils/src/global.ts +++ b/packages/utils/src/global.ts @@ -55,5 +55,5 @@ export function getGlobalObject(): T & SentryGlobal { export function getGlobalSingleton(name: keyof SentryGlobal['__SENTRY__'], creator: () => T, obj?: unknown): T { const global = (obj || getGlobalObject()) as SentryGlobal; const sentry = (global.__SENTRY__ = global.__SENTRY__ || {}); - return sentry[name] || sentry[name] == creator(); + return sentry[name] || (sentry[name] = creator()); } From 8a9f2d0784dde8c4c85d3864061b90291728d488 Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Fri, 17 Dec 2021 14:33:27 +0100 Subject: [PATCH 12/12] fix: need to export a const for another module --- packages/core/src/integration.ts | 2 +- packages/core/test/lib/sdk.test.ts | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index cd3dd4128328..4dce113d747d 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -6,7 +6,7 @@ import { addNonEnumerableProperty, getGlobalSingleton, isDebugBuild, logger } fr // sentry is bundled twice. In that case integrations would patch over themselves. // this is problematic because it's unclear if sentry versions will agree on this // behavior. There are likely to be better ways to accomplish this. -const onceInitializedIntegrations: Array = getGlobalSingleton('_integrations', () => []); +export const onceInitializedIntegrations: Array = getGlobalSingleton('_integrations', () => []); /** Map of integrations assigned to a client */ export type IntegrationIndex = { diff --git a/packages/core/test/lib/sdk.test.ts b/packages/core/test/lib/sdk.test.ts index 04f704d0698e..32c0d549d688 100644 --- a/packages/core/test/lib/sdk.test.ts +++ b/packages/core/test/lib/sdk.test.ts @@ -1,7 +1,7 @@ import { Scope } from '@sentry/hub'; import { Client, Integration } from '@sentry/types'; -import { installedIntegrations } from '../../src/integration'; +import { onceInitializedIntegrations } from '../../src/integration'; import { initAndBind } from '../../src/sdk'; import { TestClient } from '../mocks/client'; @@ -46,7 +46,7 @@ class MockIntegration implements Integration { describe('SDK', () => { beforeEach(() => { global.__SENTRY__ = {}; - installedIntegrations.splice(0); + onceInitializedIntegrations.splice(0); }); describe('initAndBind', () => {