diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7aee8627a350..e5573d07a8db 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -61,16 +61,12 @@ Pro tip: If any of your breakpoints are in code run by multiple tests, and you r ## Debug Build Flags -Throughout the codebase, you will find debug flags like `IS_DEBUG_BUILD` guarding various code sections. -These flags serve two purposes: +Throughout the codebase, you will find the `__DEBUG_BUILD__` flag guarding various code sections. This flag serves two purposes: -1. They enable us to remove debug code for our production browser bundles. -2. Enable users to tree-shake Sentry debug code for their production builds. +1. It enables us to remove debug code from our minified CDN bundles during build, by replacing the flag with `false` before tree-shaking occurs. +2. It enables users to remove Sentry debug code from their production bundles during their own build. When we build our npm packages, we replace the flag with `(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)`. If the user does nothing, this evaluates to `true` and logging is included. But if the user runs their own replacement during build (again replacing the flag with `false`), the build will tree-shake the logging away, just as our bundle builds do. -These debug flags need to be declared in each package individually and must not be imported across package boundaries, because some build tools have trouble tree-shaking imported guards. -As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. -The `flags.ts` file will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during our, or the user's build process. -Take care when introducing new flags - they must not throw if they are not replaced. +Note that the replacement flag, `__SENTRY_DEBUG__`, is different from the original flag . This is necessary because the replacement plugin runs twice, at two different stages of the build, and we don't want to run a replacement on our replacement (as would happen if we reused `__DEBUG_BUILD__`). ## Linting diff --git a/jest/jest.config.js b/jest/jest.config.js index 8b7b7f1f5b7c..3ce4af024a86 100644 --- a/jest/jest.config.js +++ b/jest/jest.config.js @@ -12,6 +12,7 @@ module.exports = { 'ts-jest': { tsconfig: '/tsconfig.test.json', }, + __DEBUG_BUILD__: true, }, testPathIgnorePatterns: ['/build/', '/node_modules/'], }; diff --git a/packages/angular/src/flags.ts b/packages/angular/src/flags.ts index fb99adbc2aa7..34c19e8476a1 100644 --- a/packages/angular/src/flags.ts +++ b/packages/angular/src/flags.ts @@ -2,14 +2,9 @@ * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking * for users. * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. + * We define "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during our, or the user's + * build process. Take care when introducing new flags - they must not throw if they are not replaced. See the Debug + * Build Flags section in CONTRIBUTING.md. */ declare const __SENTRY_DEBUG__: boolean; diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 9916ebd9c984..eef289c3b00a 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -10,7 +10,6 @@ import { } from '@sentry/utils'; import { eventFromException, eventFromMessage } from './eventbuilder'; -import { IS_DEBUG_BUILD } from './flags'; import { Breadcrumbs } from './integrations'; import { BREADCRUMB_INTEGRATION_ID } from './integrations/breadcrumbs'; import { BrowserTransportOptions } from './transports/types'; @@ -151,16 +150,16 @@ export class BrowserClient extends BaseClient { const outcomes = this._clearOutcomes(); if (outcomes.length === 0) { - IS_DEBUG_BUILD && logger.log('No outcomes to send'); + __DEBUG_BUILD__ && logger.log('No outcomes to send'); return; } if (!this._dsn) { - IS_DEBUG_BUILD && logger.log('No dsn provided, will not send outcomes'); + __DEBUG_BUILD__ && logger.log('No dsn provided, will not send outcomes'); return; } - IS_DEBUG_BUILD && logger.log('Sending outcomes:', outcomes); + __DEBUG_BUILD__ && logger.log('Sending outcomes:', outcomes); const url = getEnvelopeEndpointWithUrlEncodedAuth(this._dsn, this._options.tunnel); const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn)); @@ -168,7 +167,7 @@ export class BrowserClient extends BaseClient { try { sendReport(url, serializeEnvelope(envelope)); } catch (e) { - IS_DEBUG_BUILD && logger.error(e); + __DEBUG_BUILD__ && logger.error(e); } } } diff --git a/packages/browser/src/flags.ts b/packages/browser/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/browser/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/browser/src/integrations/dedupe.ts b/packages/browser/src/integrations/dedupe.ts index 48aa8411f268..aaaef31d7257 100644 --- a/packages/browser/src/integrations/dedupe.ts +++ b/packages/browser/src/integrations/dedupe.ts @@ -1,8 +1,6 @@ import { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; - /** Deduplication filter */ export class Dedupe implements Integration { /** @@ -30,7 +28,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, self._previousEvent)) { - IS_DEBUG_BUILD && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); return null; } } catch (_oO) { diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index 9452bf8f7103..79d5d3d6a444 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -13,7 +13,6 @@ import { import { BrowserClient } from '../client'; import { eventFromUnknownInput } from '../eventbuilder'; -import { IS_DEBUG_BUILD } from '../flags'; import { shouldIgnoreOnError } from '../helpers'; type GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection'; @@ -238,7 +237,7 @@ function _enhanceEventWithInitialFrame(event: Event, url: any, line: any, column } function globalHandlerLog(type: string): void { - IS_DEBUG_BUILD && logger.log(`Global Handler attached: ${type}`); + __DEBUG_BUILD__ && logger.log(`Global Handler attached: ${type}`); } function addMechanismAndCapture(hub: Hub, error: EventHint['originalException'], event: Event, type: string): void { diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 584742b26f69..e4cb2cfa279c 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -16,7 +16,6 @@ import { } from '@sentry/utils'; import { BrowserClient, BrowserClientOptions, BrowserOptions } from './client'; -import { IS_DEBUG_BUILD } from './flags'; import { ReportDialogOptions, wrap as internalWrap } from './helpers'; import { Breadcrumbs, Dedupe, GlobalHandlers, HttpContext, LinkedErrors, TryCatch } from './integrations'; import { defaultStackParser } from './stack-parsers'; @@ -131,14 +130,14 @@ export function showReportDialog(options: ReportDialogOptions = {}, hub: Hub = g // doesn't work without a document (React Native) const global = getGlobalObject(); if (!global.document) { - IS_DEBUG_BUILD && logger.error('Global document not defined in showReportDialog call'); + __DEBUG_BUILD__ && logger.error('Global document not defined in showReportDialog call'); return; } const { client, scope } = hub.getStackTop(); const dsn = options.dsn || (client && client.getDsn()); if (!dsn) { - IS_DEBUG_BUILD && logger.error('DSN not configured for showReportDialog call'); + __DEBUG_BUILD__ && logger.error('DSN not configured for showReportDialog call'); return; } @@ -166,7 +165,7 @@ export function showReportDialog(options: ReportDialogOptions = {}, hub: Hub = g if (injectionPoint) { injectionPoint.appendChild(script); } else { - IS_DEBUG_BUILD && logger.error('Not injecting report dialog. No injection point found in HTML'); + __DEBUG_BUILD__ && logger.error('Not injecting report dialog. No injection point found in HTML'); } } @@ -208,7 +207,7 @@ export function flush(timeout?: number): PromiseLike { if (client) { return client.flush(timeout); } - IS_DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.'); + __DEBUG_BUILD__ && logger.warn('Cannot flush events. No client defined.'); return resolvedSyncPromise(false); } @@ -225,7 +224,7 @@ export function close(timeout?: number): PromiseLike { if (client) { return client.close(timeout); } - IS_DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.'); + __DEBUG_BUILD__ && logger.warn('Cannot flush events and disable SDK. No client defined.'); return resolvedSyncPromise(false); } @@ -254,7 +253,8 @@ function startSessionTracking(): void { const document = window.document; if (typeof document === 'undefined') { - IS_DEBUG_BUILD && logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); + __DEBUG_BUILD__ && + logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); return; } diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index bd17ec097c28..a38f817691e4 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -1,7 +1,5 @@ import { getGlobalObject, isNativeFetch, logger, supportsFetch } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; - const global = getGlobalObject(); let cachedFetchImpl: FetchImpl; @@ -71,7 +69,7 @@ export function getNativeFetchImplementation(): FetchImpl { } document.head.removeChild(sandbox); } catch (e) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); } } @@ -101,6 +99,8 @@ export function sendReport(url: string, body: string | Uint8Array): void { method: 'POST', credentials: 'omit', keepalive: true, - }).then(null, error => logger.error(error)); + }).then(null, error => { + __DEBUG_BUILD__ && logger.error(error); + }); } } diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 1c8de1472a49..3f365f111ed9 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -39,7 +39,6 @@ import { import { getEnvelopeEndpointWithUrlEncodedAuth } from './api'; import { createEventEnvelope, createSessionEnvelope } from './envelope'; -import { IS_DEBUG_BUILD } from './flags'; import { IntegrationIndex, setupIntegrations } from './integration'; const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; @@ -112,7 +111,7 @@ export abstract class BaseClient implements Client { url, }); } else { - IS_DEBUG_BUILD && logger.warn('No DSN provided, client will not do anything.'); + __DEBUG_BUILD__ && logger.warn('No DSN provided, client will not do anything.'); } } @@ -123,7 +122,7 @@ export abstract class BaseClient implements Client { public captureException(exception: any, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (checkOrSetAlreadyCaught(exception)) { - IS_DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); + __DEBUG_BUILD__ && logger.log(ALREADY_SEEN_ERROR); return; } @@ -173,7 +172,7 @@ export abstract class BaseClient implements Client { public captureEvent(event: Event, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (hint && hint.originalException && checkOrSetAlreadyCaught(hint.originalException)) { - IS_DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); + __DEBUG_BUILD__ && logger.log(ALREADY_SEEN_ERROR); return; } @@ -193,12 +192,12 @@ export abstract class BaseClient implements Client { */ public captureSession(session: Session): void { if (!this._isEnabled()) { - IS_DEBUG_BUILD && logger.warn('SDK not enabled, will not capture session.'); + __DEBUG_BUILD__ && logger.warn('SDK not enabled, will not capture session.'); return; } if (!(typeof session.release === 'string')) { - IS_DEBUG_BUILD && logger.warn('Discarded session because of missing or non-string release'); + __DEBUG_BUILD__ && logger.warn('Discarded session because of missing or non-string release'); } else { this.sendSession(session); // After sending, we set init false to indicate it's not the first occurrence @@ -277,7 +276,7 @@ export abstract class BaseClient implements Client { try { return (this._integrations[integration.id] as T) || null; } catch (_oO) { - IS_DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); + __DEBUG_BUILD__ && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); return null; } } @@ -322,7 +321,7 @@ export abstract class BaseClient implements Client { // would be `Partial>>>` // With typescript 4.1 we could even use template literal types const key = `${reason}:${category}`; - IS_DEBUG_BUILD && logger.log(`Adding outcome: "${key}"`); + __DEBUG_BUILD__ && logger.log(`Adding outcome: "${key}"`); // The following works because undefined + 1 === NaN and NaN is falsy this._outcomes[key] = this._outcomes[key] + 1 || 1; @@ -575,7 +574,7 @@ export abstract class BaseClient implements Client { return finalEvent.event_id; }, reason => { - IS_DEBUG_BUILD && logger.warn(reason); + __DEBUG_BUILD__ && logger.warn(reason); return undefined; }, ); @@ -683,10 +682,10 @@ export abstract class BaseClient implements Client { protected _sendEnvelope(envelope: Envelope): void { if (this._transport && this._dsn) { this._transport.send(envelope).then(null, reason => { - IS_DEBUG_BUILD && logger.error('Error while sending event:', reason); + __DEBUG_BUILD__ && logger.error('Error while sending event:', reason); }); } else { - IS_DEBUG_BUILD && logger.error('Transport disabled'); + __DEBUG_BUILD__ && logger.error('Transport disabled'); } } diff --git a/packages/core/src/flags.ts b/packages/core/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/core/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index e45f4a7c09d7..811a3852c410 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -2,8 +2,6 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Integration, Options } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; - export const installedIntegrations: string[] = []; /** Map of integrations assigned to a client */ @@ -69,7 +67,7 @@ export function setupIntegrations(integrations: Integration[]): IntegrationIndex if (installedIntegrations.indexOf(integration.name) === -1) { integration.setupOnce(addGlobalEventProcessor, getCurrentHub); installedIntegrations.push(integration.name); - IS_DEBUG_BUILD && logger.log(`Integration installed: ${integration.name}`); + __DEBUG_BUILD__ && logger.log(`Integration installed: ${integration.name}`); } }); diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index 0e9dc859a3f8..f9f91415e18c 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -1,8 +1,6 @@ import { Event, EventProcessor, Hub, Integration, StackFrame } from '@sentry/types'; import { getEventDescription, isMatchingPattern, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; - // "Script error." is hard coded into browsers for errors that it can't read. // this is the result of a script being pulled in from an external domain and CORS. const DEFAULT_IGNORE_ERRORS = [/^Script error\.?$/, /^Javascript error: Script error\.? on line 0$/]; @@ -72,19 +70,19 @@ export function _mergeOptions( /** JSDoc */ export function _shouldDropEvent(event: Event, options: Partial): boolean { if (options.ignoreInternal && _isSentryError(event)) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); return true; } if (_isIgnoredError(event, options.ignoreErrors)) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( `Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`, ); return true; } if (_isDeniedUrl(event, options.denyUrls)) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( `Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription( event, @@ -93,7 +91,7 @@ export function _shouldDropEvent(event: Event, options: Partial = new (options: O) => F; @@ -19,7 +17,7 @@ export function initAndBind( options: O, ): void { if (options.debug === true) { - if (IS_DEBUG_BUILD) { + if (__DEBUG_BUILD__) { logger.enable(); } else { // use `console.warn` rather than `logger.warn` since by non-debug bundles have all `logger.x` statements stripped diff --git a/packages/core/src/transports/base.ts b/packages/core/src/transports/base.ts index fc83fb6b2855..e37365c89f63 100644 --- a/packages/core/src/transports/base.ts +++ b/packages/core/src/transports/base.ts @@ -21,8 +21,6 @@ import { updateRateLimits, } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; - export const DEFAULT_TRANSPORT_BUFFER_SIZE = 30; /** @@ -73,13 +71,13 @@ export function createTransport( response => { // We don't want to throw on NOK responses, but we want to at least log them if (response.statusCode !== undefined && (response.statusCode < 200 || response.statusCode >= 300)) { - IS_DEBUG_BUILD && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`); + __DEBUG_BUILD__ && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`); } rateLimits = updateRateLimits(rateLimits, response); }, error => { - IS_DEBUG_BUILD && logger.error('Failed while sending event:', error); + __DEBUG_BUILD__ && logger.error('Failed while sending event:', error); recordEnvelopeLoss('network_error'); }, ); @@ -88,7 +86,7 @@ export function createTransport( result => result, error => { if (error instanceof SentryError) { - IS_DEBUG_BUILD && logger.error('Skipped sending event due to full buffer'); + __DEBUG_BUILD__ && logger.error('Skipped sending event due to full buffer'); recordEnvelopeLoss('queue_overflow'); return resolvedSyncPromise(); } else { diff --git a/packages/hub/src/flags.ts b/packages/hub/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/hub/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/hub/src/hub.ts b/packages/hub/src/hub.ts index 7f591e44c2e8..9a2d306603c9 100644 --- a/packages/hub/src/hub.ts +++ b/packages/hub/src/hub.ts @@ -30,7 +30,6 @@ import { uuid4, } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; import { Scope } from './scope'; import { closeSession, makeSession, updateSession } from './session'; @@ -356,7 +355,7 @@ export class Hub implements HubInterface { try { return client.getIntegration(integration); } catch (_oO) { - IS_DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); + __DEBUG_BUILD__ && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); return null; } } @@ -479,7 +478,7 @@ export class Hub implements HubInterface { if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') { return sentry.extensions[method].apply(this, args); } - IS_DEBUG_BUILD && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); + __DEBUG_BUILD__ && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); } } diff --git a/packages/hub/src/scope.ts b/packages/hub/src/scope.ts index 98f80745004c..b58b45e1c4b6 100644 --- a/packages/hub/src/scope.ts +++ b/packages/hub/src/scope.ts @@ -30,7 +30,6 @@ import { SyncPromise, } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; import { updateSession } from './session'; /** @@ -501,7 +500,7 @@ export class Scope implements ScopeInterface { } else { const result = processor({ ...event }, hint) as Event | null; - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && processor.id && result === null && logger.log(`Event processor "${processor.id}" dropped event`); diff --git a/packages/integrations/scripts/buildBundles.sh b/packages/integrations/scripts/buildBundles.sh index 2b75b83ee670..15f1f15f0a59 100644 --- a/packages/integrations/scripts/buildBundles.sh +++ b/packages/integrations/scripts/buildBundles.sh @@ -6,7 +6,7 @@ for filepath in ./src/*; do # The index file is only there for the purposes of npm builds (for the CDN we create a separate bundle for each # integration) and the flags file is just a helper for including or not including debug logging, whose contents gets # incorporated into each of the individual integration bundles, so we can skip them both here. - if [[ $file == "index.ts" || $file == "flags.ts" ]]; then + if [[ $file == "index.ts" ]]; then continue fi diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index a29223f6832b..bd615fc084d2 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,8 +1,6 @@ import { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; - /** Deduplication filter */ export class Dedupe implements Integration { /** @@ -30,7 +28,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, self._previousEvent)) { - IS_DEBUG_BUILD && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + __DEBUG_BUILD__ && 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 0dfb8f39bbfc..ef4e6d49393f 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,8 +1,6 @@ import { Contexts, Event, EventHint, EventProcessor, ExtendedError, Hub, Integration } from '@sentry/types'; import { addNonEnumerableProperty, isError, isPlainObject, logger, normalize } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; - /** JSDoc */ interface ExtraErrorDataOptions { depth?: number; @@ -121,7 +119,7 @@ export class ExtraErrorData implements Integration { return extraErrorInfo; } catch (oO) { - IS_DEBUG_BUILD && logger.error('Unable to extract extra data from the Error object:', oO); + __DEBUG_BUILD__ && logger.error('Unable to extract extra data from the Error object:', oO); } return null; diff --git a/packages/integrations/src/flags.ts b/packages/integrations/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/integrations/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/integrations/src/offline.ts b/packages/integrations/src/offline.ts index 78d8ead05dd4..1da4f77b3a3a 100644 --- a/packages/integrations/src/offline.ts +++ b/packages/integrations/src/offline.ts @@ -4,8 +4,6 @@ import { Event, EventProcessor, Hub, Integration } from '@sentry/types'; import { getGlobalObject, logger, normalize, uuid4 } from '@sentry/utils'; import localForage from 'localforage'; -import { IS_DEBUG_BUILD } from './flags'; - type LocalForage = { setItem(key: string, value: T, callback?: (err: any, value: T) => void): Promise; iterate( @@ -75,7 +73,7 @@ export class Offline implements Integration { if ('addEventListener' in this.global) { this.global.addEventListener('online', () => { void this._sendEvents().catch(() => { - IS_DEBUG_BUILD && logger.warn('could not send cached events'); + __DEBUG_BUILD__ && logger.warn('could not send cached events'); }); }); } @@ -84,12 +82,12 @@ export class Offline implements Integration { if (this.hub && this.hub.getIntegration(Offline)) { // cache if we are positively offline if ('navigator' in this.global && 'onLine' in this.global.navigator && !this.global.navigator.onLine) { - IS_DEBUG_BUILD && logger.log('Event dropped due to being a offline - caching instead'); + __DEBUG_BUILD__ && logger.log('Event dropped due to being a offline - caching instead'); void this._cacheEvent(event) .then((_event: Event): Promise => this._enforceMaxEvents()) .catch((_error): void => { - IS_DEBUG_BUILD && logger.warn('could not cache event while offline'); + __DEBUG_BUILD__ && logger.warn('could not cache event while offline'); }); // return null on success or failure, because being offline will still result in an error @@ -106,7 +104,7 @@ export class Offline implements Integration { // if online now, send any events stored in a previous offline session if ('navigator' in this.global && 'onLine' in this.global.navigator && this.global.navigator.onLine) { void this._sendEvents().catch(() => { - IS_DEBUG_BUILD && logger.warn('could not send cached events'); + __DEBUG_BUILD__ && logger.warn('could not send cached events'); }); } } @@ -142,7 +140,7 @@ export class Offline implements Integration { ), ) .catch((_error): void => { - IS_DEBUG_BUILD && logger.warn('could not enforce max events'); + __DEBUG_BUILD__ && logger.warn('could not enforce max events'); }); } @@ -170,10 +168,10 @@ export class Offline implements Integration { this.hub.captureEvent(event); void this._purgeEvent(cacheKey).catch((_error): void => { - IS_DEBUG_BUILD && logger.warn('could not purge event from cache'); + __DEBUG_BUILD__ && logger.warn('could not purge event from cache'); }); } else { - IS_DEBUG_BUILD && logger.warn('no hub found - could not send cached event'); + __DEBUG_BUILD__ && logger.warn('no hub found - could not send cached event'); } }); } diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 568a23cf5d88..6b8ea8e94c4f 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -6,7 +6,6 @@ import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; -import { IS_DEBUG_BUILD } from '../flags'; import { BuildContext, EntryPropertyObject, @@ -245,7 +244,7 @@ function checkWebpackPluginOverrides( // warn if any of the default options for the webpack plugin are getting overridden const sentryWebpackPluginOptionOverrides = Object.keys(defaultOptions).filter(key => key in userOptions); if (sentryWebpackPluginOptionOverrides.length > 0) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( '[Sentry] You are overriding the following automatically-set SentryWebpackPlugin config options:\n' + `\t${sentryWebpackPluginOptionOverrides.toString()},\n` + diff --git a/packages/nextjs/src/flags.ts b/packages/nextjs/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/nextjs/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/nextjs/src/index.server.ts b/packages/nextjs/src/index.server.ts index 8d34a989264a..f572583edb2e 100644 --- a/packages/nextjs/src/index.server.ts +++ b/packages/nextjs/src/index.server.ts @@ -7,7 +7,6 @@ import { escapeStringForRegex, logger } from '@sentry/utils'; import * as domainModule from 'domain'; import * as path from 'path'; -import { IS_DEBUG_BUILD } from './flags'; import { buildMetadata } from './utils/metadata'; import { NextjsOptions } from './utils/nextjsOptions'; import { addIntegration } from './utils/userIntegrations'; @@ -42,14 +41,14 @@ const isVercel = !!process.env.VERCEL; /** Inits the Sentry NextJS SDK on node. */ export function init(options: NextjsOptions): void { - if (options.debug) { + if (__DEBUG_BUILD__ && options.debug) { logger.enable(); } - IS_DEBUG_BUILD && logger.log('Initializing SDK...'); + __DEBUG_BUILD__ && logger.log('Initializing SDK...'); if (sdkAlreadyInitialized()) { - IS_DEBUG_BUILD && logger.log('SDK already initialized'); + __DEBUG_BUILD__ && logger.log('SDK already initialized'); return; } @@ -100,7 +99,7 @@ export function init(options: NextjsOptions): void { domain.active = activeDomain; } - IS_DEBUG_BUILD && logger.log('SDK successfully initialized'); + __DEBUG_BUILD__ && logger.log('SDK successfully initialized'); } function sdkAlreadyInitialized(): boolean { @@ -153,6 +152,6 @@ if (!isVercel && !isBuild) { const { instrumentServer } = require('./utils/instrumentServer.js'); instrumentServer(); } catch (err) { - IS_DEBUG_BUILD && logger.warn(`Error: Unable to instrument server for tracing. Got ${err}.`); + __DEBUG_BUILD__ && logger.warn(`Error: Unable to instrument server for tracing. Got ${err}.`); } } diff --git a/packages/nextjs/src/utils/instrumentServer.ts b/packages/nextjs/src/utils/instrumentServer.ts index bf4adc9ec8b3..d56e8d735f71 100644 --- a/packages/nextjs/src/utils/instrumentServer.ts +++ b/packages/nextjs/src/utils/instrumentServer.ts @@ -22,8 +22,6 @@ import { default as createNextServer } from 'next'; import * as querystring from 'querystring'; import * as url from 'url'; -import { IS_DEBUG_BUILD } from '../flags'; - const { parseRequest } = Handlers; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -256,7 +254,7 @@ function makeWrappedReqHandler(origReqHandler: ReqHandler): WrappedReqHandler { let traceparentData; if (nextReq.headers && isString(nextReq.headers['sentry-trace'])) { traceparentData = extractTraceparentData(nextReq.headers['sentry-trace']); - IS_DEBUG_BUILD && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); + __DEBUG_BUILD__ && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); } const baggage = diff --git a/packages/nextjs/src/utils/withSentry.ts b/packages/nextjs/src/utils/withSentry.ts index 742d9f4c9280..fa56bbaf2867 100644 --- a/packages/nextjs/src/utils/withSentry.ts +++ b/packages/nextjs/src/utils/withSentry.ts @@ -12,8 +12,6 @@ import { import * as domain from 'domain'; import { NextApiHandler, NextApiRequest, NextApiResponse } from 'next'; -import { IS_DEBUG_BUILD } from '../flags'; - const { parseRequest } = Handlers; // This is the same as the `NextApiHandler` type, except instead of having a return type of `void | Promise`, it's @@ -52,7 +50,7 @@ export const withSentry = (origHandler: NextApiHandler): WrappedNextApiHandler = let traceparentData; if (req.headers && isString(req.headers['sentry-trace'])) { traceparentData = extractTraceparentData(req.headers['sentry-trace']); - IS_DEBUG_BUILD && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); + __DEBUG_BUILD__ && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); } const baggage = req.headers && isString(req.headers.baggage) && parseBaggageString(req.headers.baggage); @@ -198,10 +196,10 @@ async function finishSentryProcessing(res: AugmentedNextApiResponse): Promise { public initSessionFlusher(): void { const { release, environment } = this._options; if (!release) { - IS_DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); + __DEBUG_BUILD__ && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); } else { this._sessionFlusher = new SessionFlusher(this, { release, @@ -152,7 +151,7 @@ export class NodeClient extends BaseClient { */ protected _captureRequestSession(): void { if (!this._sessionFlusher) { - IS_DEBUG_BUILD && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); + __DEBUG_BUILD__ && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); } else { this._sessionFlusher.incrementSessionStatusCount(); } diff --git a/packages/node/src/flags.ts b/packages/node/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/node/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 27dbeb3fc9cf..9bd7c6035fd1 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -18,7 +18,6 @@ import * as os from 'os'; import * as url from 'url'; import { NodeClient } from './client'; -import { IS_DEBUG_BUILD } from './flags'; import { flush, isAutoSessionTrackingEnabled } from './sdk'; export interface ExpressRequest { @@ -413,7 +412,7 @@ export function requestHandler( _end.call(this, chunk, encoding, cb); }) .then(null, e => { - IS_DEBUG_BUILD && logger.error(e); + __DEBUG_BUILD__ && logger.error(e); _end.call(this, chunk, encoding, cb); }); }; diff --git a/packages/node/src/integrations/http.ts b/packages/node/src/integrations/http.ts index 074c81ffe842..9894e059b716 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -4,7 +4,6 @@ import { fill, logger, mergeAndSerializeBaggage, parseSemver } from '@sentry/uti import * as http from 'http'; import * as https from 'https'; -import { IS_DEBUG_BUILD } from '../flags'; import { cleanSpanDescription, extractUrl, @@ -119,7 +118,7 @@ function _createWrappedRequestMethodFactory( }); const sentryTraceHeader = span.toTraceparent(); - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log( `[Tracing] Adding sentry-trace header ${sentryTraceHeader} to outgoing request to ${requestUrl}: `, ); diff --git a/packages/node/src/integrations/onuncaughtexception.ts b/packages/node/src/integrations/onuncaughtexception.ts index dfff26fa0675..9c16e2e70fe2 100644 --- a/packages/node/src/integrations/onuncaughtexception.ts +++ b/packages/node/src/integrations/onuncaughtexception.ts @@ -3,7 +3,6 @@ import { Integration } from '@sentry/types'; import { logger } from '@sentry/utils'; import { NodeClient } from '../client'; -import { IS_DEBUG_BUILD } from '../flags'; import { logAndExitProcess } from './utils/errorhandling'; type OnFatalErrorHandler = (firstError: Error, secondError?: Error) => void; @@ -96,7 +95,7 @@ export class OnUncaughtException implements Integration { } } else if (calledFatalError) { // we hit an error *after* calling onFatalError - pretty boned at this point, just shut it down - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn('uncaught exception after calling fatal error shutdown callback - this is bad! forcing shutdown'); logAndExitProcess(error); } else if (!caughtSecondError) { diff --git a/packages/node/src/integrations/utils/errorhandling.ts b/packages/node/src/integrations/utils/errorhandling.ts index 587840d040b5..912b01c55ba9 100644 --- a/packages/node/src/integrations/utils/errorhandling.ts +++ b/packages/node/src/integrations/utils/errorhandling.ts @@ -2,7 +2,6 @@ import { getCurrentHub } from '@sentry/core'; import { logger } from '@sentry/utils'; import { NodeClient } from '../../client'; -import { IS_DEBUG_BUILD } from '../../flags'; const DEFAULT_SHUTDOWN_TIMEOUT = 2000; @@ -16,7 +15,7 @@ export function logAndExitProcess(error: Error): void { const client = getCurrentHub().getClient(); if (client === undefined) { - IS_DEBUG_BUILD && logger.warn('No NodeClient was defined, we are exiting the process now.'); + __DEBUG_BUILD__ && logger.warn('No NodeClient was defined, we are exiting the process now.'); global.process.exit(1); } @@ -27,10 +26,12 @@ export function logAndExitProcess(error: Error): void { client.close(timeout).then( (result: boolean) => { if (!result) { - IS_DEBUG_BUILD && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); + __DEBUG_BUILD__ && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); } global.process.exit(1); }, - error => logger.error(error), + error => { + __DEBUG_BUILD__ && logger.error(error); + }, ); } diff --git a/packages/node/src/sdk.ts b/packages/node/src/sdk.ts index e83320103cb6..e5993aa0d116 100644 --- a/packages/node/src/sdk.ts +++ b/packages/node/src/sdk.ts @@ -5,7 +5,6 @@ import { createStackParser, getGlobalObject, logger, stackParserFromStackParserO import * as domain from 'domain'; import { NodeClient } from './client'; -import { IS_DEBUG_BUILD } from './flags'; import { Console, ContextLines, Http, LinkedErrors, OnUncaughtException, OnUnhandledRejection } from './integrations'; import { getModule } from './module'; import { nodeStackLineParser } from './stack-parser'; @@ -165,7 +164,7 @@ export async function flush(timeout?: number): Promise { if (client) { return client.flush(timeout); } - IS_DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.'); + __DEBUG_BUILD__ && logger.warn('Cannot flush events. No client defined.'); return Promise.resolve(false); } @@ -182,7 +181,7 @@ export async function close(timeout?: number): Promise { if (client) { return client.close(timeout); } - IS_DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.'); + __DEBUG_BUILD__ && logger.warn('Cannot flush events and disable SDK. No client defined.'); return Promise.resolve(false); } diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 0a03cb822c8b..74670e25fa87 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -3,8 +3,6 @@ import { logger } from '@sentry/utils'; import hoistNonReactStatics from 'hoist-non-react-statics'; import * as React from 'react'; -import { IS_DEBUG_BUILD } from './flags'; - export function isAtLeastReact17(version: string): boolean { const major = version.match(/^([^.]+)/); return major !== null && parseInt(major[0]) >= 17; @@ -144,7 +142,7 @@ class ErrorBoundary extends React.Component, R !_matchRoutes || !_customStartTransaction ) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn('reactRouterV6Instrumentation was unable to wrap Routes because of one or more missing parameters.'); return Routes; diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index a2825b1e1e2e..2514510af067 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -22,7 +22,6 @@ import { performance } from 'perf_hooks'; import { types } from 'util'; import { AWSServices } from './awsservices'; -import { IS_DEBUG_BUILD } from './flags'; import { serverlessEventProcessor } from './utils'; export * from '@sentry/node'; @@ -126,7 +125,7 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { const handlerDesc = basename(handlerPath); const match = handlerDesc.match(/^([^.]*)\.(.*)$/); if (!match) { - IS_DEBUG_BUILD && logger.error(`Bad handler ${handlerDesc}`); + __DEBUG_BUILD__ && logger.error(`Bad handler ${handlerDesc}`); return; } @@ -137,7 +136,7 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { const handlerDir = handlerPath.substring(0, handlerPath.indexOf(handlerDesc)); obj = tryRequire(taskRoot, handlerDir, handlerMod); } catch (e) { - IS_DEBUG_BUILD && logger.error(`Cannot require ${handlerPath} in ${taskRoot}`, e); + __DEBUG_BUILD__ && logger.error(`Cannot require ${handlerPath} in ${taskRoot}`, e); return; } @@ -149,11 +148,11 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { functionName = name; }); if (!obj) { - IS_DEBUG_BUILD && logger.error(`${handlerPath} is undefined or not exported`); + __DEBUG_BUILD__ && logger.error(`${handlerPath} is undefined or not exported`); return; } if (typeof obj !== 'function') { - IS_DEBUG_BUILD && logger.error(`${handlerPath} is not a function`); + __DEBUG_BUILD__ && logger.error(`${handlerPath} is not a function`); return; } @@ -325,7 +324,7 @@ export function wrapHandler( transaction.finish(); hub.popScope(); await flush(options.flushTimeout).catch(e => { - IS_DEBUG_BUILD && logger.error(e); + __DEBUG_BUILD__ && logger.error(e); }); } return rv; diff --git a/packages/serverless/src/flags.ts b/packages/serverless/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/serverless/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/serverless/src/gcpfunction/cloud_events.ts b/packages/serverless/src/gcpfunction/cloud_events.ts index ae993128139f..82b941840d8d 100644 --- a/packages/serverless/src/gcpfunction/cloud_events.ts +++ b/packages/serverless/src/gcpfunction/cloud_events.ts @@ -1,7 +1,6 @@ import { captureException, flush, getCurrentHub, startTransaction } from '@sentry/node'; import { logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; import { domainify, getActiveDomain, proxyFunction } from '../utils'; import { CloudEventFunction, @@ -62,7 +61,7 @@ function _wrapCloudEventFunction( void flush(options.flushTimeout) .then(null, e => { - IS_DEBUG_BUILD && logger.error(e); + __DEBUG_BUILD__ && logger.error(e); }) .then(() => { callback(...args); diff --git a/packages/serverless/src/gcpfunction/events.ts b/packages/serverless/src/gcpfunction/events.ts index 4b29a26270e4..ac0de3e825c9 100644 --- a/packages/serverless/src/gcpfunction/events.ts +++ b/packages/serverless/src/gcpfunction/events.ts @@ -1,7 +1,6 @@ import { captureException, flush, getCurrentHub, startTransaction } from '@sentry/node'; import { logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; import { domainify, getActiveDomain, proxyFunction } from '../utils'; import { configureScopeWithContext, EventFunction, EventFunctionWithCallback, WrapperOptions } from './general'; @@ -57,7 +56,7 @@ function _wrapEventFunction( void flush(options.flushTimeout) .then(null, e => { - IS_DEBUG_BUILD && logger.error(e); + __DEBUG_BUILD__ && logger.error(e); }) .then(() => { callback(...args); diff --git a/packages/serverless/src/gcpfunction/http.ts b/packages/serverless/src/gcpfunction/http.ts index 26c32b4a21cb..8596774299e1 100644 --- a/packages/serverless/src/gcpfunction/http.ts +++ b/packages/serverless/src/gcpfunction/http.ts @@ -2,7 +2,6 @@ import { captureException, flush, getCurrentHub, Handlers, startTransaction } fr import { extractTraceparentData } from '@sentry/tracing'; import { isString, logger, parseBaggageString, stripUrlQueryAndFragment } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; import { domainify, getActiveDomain, proxyFunction } from './../utils'; import { HttpFunction, WrapperOptions } from './general'; @@ -99,7 +98,7 @@ function _wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial { - IS_DEBUG_BUILD && logger.error(e); + __DEBUG_BUILD__ && logger.error(e); }) .then(() => { _end.call(this, chunk, encoding, cb); diff --git a/packages/tracing/src/browser/backgroundtab.ts b/packages/tracing/src/browser/backgroundtab.ts index 64bb06d2d70f..137779e16168 100644 --- a/packages/tracing/src/browser/backgroundtab.ts +++ b/packages/tracing/src/browser/backgroundtab.ts @@ -1,6 +1,5 @@ import { getGlobalObject, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; import { IdleTransaction } from '../idletransaction'; import { SpanStatusType } from '../span'; import { getActiveTransaction } from '../utils'; @@ -18,7 +17,7 @@ export function registerBackgroundTabDetection(): void { if (global.document.hidden && activeTransaction) { const statusType: SpanStatusType = 'cancelled'; - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log( `[Tracing] Transaction: ${statusType} -> since tab moved to the background, op: ${activeTransaction.op}`, ); @@ -32,6 +31,7 @@ export function registerBackgroundTabDetection(): void { } }); } else { - IS_DEBUG_BUILD && logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); + __DEBUG_BUILD__ && + logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); } } diff --git a/packages/tracing/src/browser/browsertracing.ts b/packages/tracing/src/browser/browsertracing.ts index 8995775a8a41..94920d1c0594 100644 --- a/packages/tracing/src/browser/browsertracing.ts +++ b/packages/tracing/src/browser/browsertracing.ts @@ -2,7 +2,6 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration, Transaction, TransactionContext } from '@sentry/types'; import { getGlobalObject, logger, parseBaggageString } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; import { startIdleTransaction } from '../hubextensions'; import { DEFAULT_FINAL_TIMEOUT, DEFAULT_IDLE_TIMEOUT } from '../idletransaction'; import { extractTraceparentData } from '../utils'; @@ -137,7 +136,7 @@ export class BrowserTracing implements Integration { if (_options.tracingOrigins && Array.isArray(_options.tracingOrigins) && _options.tracingOrigins.length !== 0) { tracingOrigins = _options.tracingOrigins; } else { - IS_DEBUG_BUILD && (this._emitOptionsWarning = true); + __DEBUG_BUILD__ && (this._emitOptionsWarning = true); } } @@ -158,11 +157,11 @@ export class BrowserTracing implements Integration { this._getCurrentHub = getCurrentHub; if (this._emitOptionsWarning) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( '[Tracing] You need to define `tracingOrigins` in the options. Set an array of urls or patterns to trace.', ); - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( `[Tracing] We added a reasonable default for you: ${defaultRequestInstrumentationOptions.tracingOrigins}`, ); @@ -196,7 +195,7 @@ export class BrowserTracing implements Integration { /** Create routing idle transaction. */ private _createRouteTransaction(context: TransactionContext): Transaction | undefined { if (!this._getCurrentHub) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn(`[Tracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.`); return undefined; } @@ -218,10 +217,11 @@ export class BrowserTracing implements Integration { const finalContext = modifiedContext === undefined ? { ...expandedContext, sampled: false } : modifiedContext; if (finalContext.sampled === false) { - IS_DEBUG_BUILD && logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); + __DEBUG_BUILD__ && + logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); } - IS_DEBUG_BUILD && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); + __DEBUG_BUILD__ && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); const hub = this._getCurrentHub(); const { location } = getGlobalObject() as WindowOrWorkerGlobalScope & { location: Location }; diff --git a/packages/tracing/src/browser/metrics/index.ts b/packages/tracing/src/browser/metrics/index.ts index 48438ab7b719..e46d67c601b5 100644 --- a/packages/tracing/src/browser/metrics/index.ts +++ b/packages/tracing/src/browser/metrics/index.ts @@ -2,7 +2,6 @@ import { Measurements } from '@sentry/types'; import { browserPerformanceTimeOrigin, getGlobalObject, htmlTreeAsString, isNodeEnv, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../../flags'; import { Transaction } from '../../transaction'; import { msToSec } from '../../utils'; import { getCLS, LayoutShift } from '../web-vitals/getCLS'; @@ -50,7 +49,7 @@ function _trackCLS(): void { return; } - IS_DEBUG_BUILD && logger.log('[Measurements] Adding CLS'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding CLS'); _measurements['cls'] = { value: metric.value, unit: 'millisecond' }; _clsEntry = entry as LayoutShift; }); @@ -66,7 +65,7 @@ function _trackLCP(reportAllChanges: boolean): void { const timeOrigin = msToSec(browserPerformanceTimeOrigin as number); const startTime = msToSec(entry.startTime); - IS_DEBUG_BUILD && logger.log('[Measurements] Adding LCP'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding LCP'); _measurements['lcp'] = { value: metric.value, unit: 'millisecond' }; _measurements['mark.lcp'] = { value: timeOrigin + startTime, unit: 'second' }; _lcpEntry = entry as LargestContentfulPaint; @@ -83,7 +82,7 @@ function _trackFID(): void { const timeOrigin = msToSec(browserPerformanceTimeOrigin as number); const startTime = msToSec(entry.startTime); - IS_DEBUG_BUILD && logger.log('[Measurements] Adding FID'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding FID'); _measurements['fid'] = { value: metric.value, unit: 'millisecond' }; _measurements['mark.fid'] = { value: timeOrigin + startTime, unit: 'second' }; }); @@ -97,7 +96,7 @@ export function addPerformanceEntries(transaction: Transaction): void { return; } - IS_DEBUG_BUILD && logger.log('[Tracing] Adding & adjusting spans using Performance API'); + __DEBUG_BUILD__ && logger.log('[Tracing] Adding & adjusting spans using Performance API'); const timeOrigin = msToSec(browserPerformanceTimeOrigin); const performanceEntries = performance.getEntries(); @@ -132,12 +131,12 @@ export function addPerformanceEntries(transaction: Transaction): void { const shouldRecord = entry.startTime < firstHidden.firstHiddenTime; if (entry.name === 'first-paint' && shouldRecord) { - IS_DEBUG_BUILD && logger.log('[Measurements] Adding FP'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding FP'); _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' }; _measurements['mark.fp'] = { value: startTimestamp, unit: 'second' }; } if (entry.name === 'first-contentful-paint' && shouldRecord) { - IS_DEBUG_BUILD && logger.log('[Measurements] Adding FCP'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding FCP'); _measurements['fcp'] = { value: entry.startTime, unit: 'millisecond' }; _measurements['mark.fcp'] = { value: startTimestamp, unit: 'second' }; } @@ -162,7 +161,7 @@ export function addPerformanceEntries(transaction: Transaction): void { // Generate TTFB (Time to First Byte), which measured as the time between the beginning of the transaction and the // start of the response in milliseconds if (typeof responseStartTimestamp === 'number') { - IS_DEBUG_BUILD && logger.log('[Measurements] Adding TTFB'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding TTFB'); _measurements['ttfb'] = { value: (responseStartTimestamp - transaction.startTimestamp) * 1000, unit: 'millisecond', @@ -192,7 +191,7 @@ export function addPerformanceEntries(transaction: Transaction): void { const normalizedValue = Math.abs((measurementTimestamp - transaction.startTimestamp) * 1000); const delta = normalizedValue - oldValue; - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); _measurements[name].value = normalizedValue; }); @@ -391,7 +390,7 @@ function _trackNavigator(transaction: Transaction): void { /** Add LCP / CLS data to transaction to allow debugging */ function _tagMetricInfo(transaction: Transaction): void { if (_lcpEntry) { - IS_DEBUG_BUILD && logger.log('[Measurements] Adding LCP Data'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding LCP Data'); // Capture Properties of the LCP element that contributes to the LCP. @@ -413,7 +412,7 @@ function _tagMetricInfo(transaction: Transaction): void { // See: https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift if (_clsEntry && _clsEntry.sources) { - IS_DEBUG_BUILD && logger.log('[Measurements] Adding CLS Data'); + __DEBUG_BUILD__ && logger.log('[Measurements] Adding CLS Data'); _clsEntry.sources.forEach((source, index) => transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)), ); diff --git a/packages/tracing/src/browser/router.ts b/packages/tracing/src/browser/router.ts index fe1442b1c396..20add62319fd 100644 --- a/packages/tracing/src/browser/router.ts +++ b/packages/tracing/src/browser/router.ts @@ -1,8 +1,6 @@ import { Transaction, TransactionContext } from '@sentry/types'; import { addInstrumentationHandler, getGlobalObject, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../flags'; - const global = getGlobalObject(); /** @@ -14,7 +12,7 @@ export function instrumentRoutingWithDefaults( startTransactionOnLocationChange: boolean = true, ): void { if (!global || !global.location) { - IS_DEBUG_BUILD && logger.warn('Could not initialize routing instrumentation due to invalid location'); + __DEBUG_BUILD__ && logger.warn('Could not initialize routing instrumentation due to invalid location'); return; } @@ -44,7 +42,7 @@ export function instrumentRoutingWithDefaults( if (from !== to) { startingUrl = undefined; if (activeTransaction) { - IS_DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); + __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); // If there's an open transaction on the scope, we need to finish it before creating an new one. activeTransaction.finish(); } diff --git a/packages/tracing/src/errors.ts b/packages/tracing/src/errors.ts index ed8e6e9cbec9..5a406500ffee 100644 --- a/packages/tracing/src/errors.ts +++ b/packages/tracing/src/errors.ts @@ -1,6 +1,5 @@ import { addInstrumentationHandler, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; import { SpanStatusType } from './span'; import { getActiveTransaction } from './utils'; @@ -19,7 +18,7 @@ function errorCallback(): void { const activeTransaction = getActiveTransaction(); if (activeTransaction) { const status: SpanStatusType = 'internal_error'; - IS_DEBUG_BUILD && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); + __DEBUG_BUILD__ && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); activeTransaction.setStatus(status); } } diff --git a/packages/tracing/src/flags.ts b/packages/tracing/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/tracing/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/tracing/src/hubextensions.ts b/packages/tracing/src/hubextensions.ts index dbcb4fb66029..cfc886932696 100644 --- a/packages/tracing/src/hubextensions.ts +++ b/packages/tracing/src/hubextensions.ts @@ -12,7 +12,6 @@ import { import { dynamicRequire, isNaN, isNodeEnv, loadModule, logger } from '@sentry/utils'; import { registerErrorInstrumentation } from './errors'; -import { IS_DEBUG_BUILD } from './flags'; import { IdleTransaction } from './idletransaction'; import { Transaction } from './transaction'; import { hasTracingEnabled } from './utils'; @@ -93,14 +92,14 @@ function sample( // Since this is coming from the user (or from a function provided by the user), who knows what we might get. (The // only valid values are booleans or numbers between 0 and 1.) if (!isValidSampleRate(sampleRate)) { - IS_DEBUG_BUILD && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); + __DEBUG_BUILD__ && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); transaction.sampled = false; return transaction; } // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped if (!sampleRate) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log( `[Tracing] Discarding transaction because ${ typeof options.tracesSampler === 'function' @@ -118,7 +117,7 @@ function sample( // if we're not going to keep it, we're done if (!transaction.sampled) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log( `[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${Number( sampleRate, @@ -127,7 +126,7 @@ function sample( return transaction; } - IS_DEBUG_BUILD && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); + __DEBUG_BUILD__ && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); return transaction; } @@ -138,7 +137,7 @@ function isValidSampleRate(rate: unknown): boolean { // we need to check NaN explicitly because it's of type 'number' and therefore wouldn't get caught by this typecheck // eslint-disable-next-line @typescript-eslint/no-explicit-any if (isNaN(rate) || !(typeof rate === 'number' || typeof rate === 'boolean')) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -149,7 +148,7 @@ function isValidSampleRate(rate: unknown): boolean { // in case sampleRate is a boolean, it will get automatically cast to 1 if it's true and 0 if it's false if (rate < 0 || rate > 1) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } diff --git a/packages/tracing/src/idletransaction.ts b/packages/tracing/src/idletransaction.ts index 9353f552fcc9..b12ba4b34601 100644 --- a/packages/tracing/src/idletransaction.ts +++ b/packages/tracing/src/idletransaction.ts @@ -3,7 +3,6 @@ import { Hub } from '@sentry/hub'; import { TransactionContext } from '@sentry/types'; import { logger, timestampWithMs } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; import { Span, SpanRecorder } from './span'; import { Transaction } from './transaction'; @@ -97,7 +96,7 @@ export class IdleTransaction extends Transaction { // We set the transaction here on the scope so error events pick up the trace // context and attach it to the error. - IS_DEBUG_BUILD && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); + __DEBUG_BUILD__ && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); _idleHub.configureScope(scope => scope.setSpan(this)); } @@ -116,7 +115,7 @@ export class IdleTransaction extends Transaction { this.activities = {}; if (this.spanRecorder) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log('[Tracing] finishing IdleTransaction', new Date(endTimestamp * 1000).toISOString(), this.op); for (const callback of this._beforeFinishCallbacks) { @@ -133,13 +132,13 @@ export class IdleTransaction extends Transaction { if (!span.endTimestamp) { span.endTimestamp = endTimestamp; span.setStatus('cancelled'); - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2)); } const keepSpan = span.startTimestamp < endTimestamp; if (!keepSpan) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log( '[Tracing] discarding Span since it happened after Transaction was finished', JSON.stringify(span, undefined, 2), @@ -148,9 +147,9 @@ export class IdleTransaction extends Transaction { return keepSpan; }); - IS_DEBUG_BUILD && logger.log('[Tracing] flushing IdleTransaction'); + __DEBUG_BUILD__ && logger.log('[Tracing] flushing IdleTransaction'); } else { - IS_DEBUG_BUILD && logger.log('[Tracing] No active IdleTransaction'); + __DEBUG_BUILD__ && logger.log('[Tracing] No active IdleTransaction'); } // if `this._onScope` is `true`, the transaction put itself on the scope when it started @@ -193,7 +192,7 @@ export class IdleTransaction extends Transaction { this.spanRecorder = new IdleTransactionSpanRecorder(pushActivity, popActivity, this.spanId, maxlen); // Start heartbeat so that transactions do not run forever. - IS_DEBUG_BUILD && logger.log('Starting heartbeat'); + __DEBUG_BUILD__ && logger.log('Starting heartbeat'); this._pingHeartbeat(); } this.spanRecorder.add(this); @@ -227,9 +226,9 @@ export class IdleTransaction extends Transaction { */ private _pushActivity(spanId: string): void { this._cancelIdleTimeout(); - IS_DEBUG_BUILD && logger.log(`[Tracing] pushActivity: ${spanId}`); + __DEBUG_BUILD__ && logger.log(`[Tracing] pushActivity: ${spanId}`); this.activities[spanId] = true; - IS_DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } /** @@ -238,10 +237,10 @@ export class IdleTransaction extends Transaction { */ private _popActivity(spanId: string): void { if (this.activities[spanId]) { - IS_DEBUG_BUILD && logger.log(`[Tracing] popActivity ${spanId}`); + __DEBUG_BUILD__ && logger.log(`[Tracing] popActivity ${spanId}`); // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete this.activities[spanId]; - IS_DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } if (Object.keys(this.activities).length === 0) { @@ -273,7 +272,7 @@ export class IdleTransaction extends Transaction { this._prevHeartbeatString = heartbeatString; if (this._heartbeatCounter >= 3) { - IS_DEBUG_BUILD && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); + __DEBUG_BUILD__ && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); this.setStatus('deadline_exceeded'); this.finish(); } else { @@ -285,7 +284,7 @@ export class IdleTransaction extends Transaction { * Pings the heartbeat */ private _pingHeartbeat(): void { - IS_DEBUG_BUILD && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); + __DEBUG_BUILD__ && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); setTimeout(() => { this._beat(); }, HEARTBEAT_INTERVAL); diff --git a/packages/tracing/src/integrations/node/express.ts b/packages/tracing/src/integrations/node/express.ts index 33a492cc1df6..df9af31f00c9 100644 --- a/packages/tracing/src/integrations/node/express.ts +++ b/packages/tracing/src/integrations/node/express.ts @@ -1,8 +1,6 @@ import { Integration, Transaction } from '@sentry/types'; import { logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../../flags'; - type Method = | 'all' | 'get' @@ -81,7 +79,7 @@ export class Express implements Integration { */ public setupOnce(): void { if (!this._router) { - IS_DEBUG_BUILD && logger.error('ExpressIntegration is missing an Express instance'); + __DEBUG_BUILD__ && logger.error('ExpressIntegration is missing an Express instance'); return; } instrumentMiddlewares(this._router, this._methods); diff --git a/packages/tracing/src/integrations/node/mongo.ts b/packages/tracing/src/integrations/node/mongo.ts index a3bebce5d7bb..624ac2ed4478 100644 --- a/packages/tracing/src/integrations/node/mongo.ts +++ b/packages/tracing/src/integrations/node/mongo.ts @@ -2,8 +2,6 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration, SpanContext } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../../flags'; - // This allows us to use the same array for both defaults options and the type itself. // (note `as const` at the end to make it a union of string literal types (i.e. "a" | "b" | ... ) // and not just a string[]) @@ -123,7 +121,7 @@ export class Mongo implements Integration { const pkg = loadModule<{ Collection: MongoCollection }>(moduleName); if (!pkg) { - IS_DEBUG_BUILD && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); + __DEBUG_BUILD__ && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); return; } diff --git a/packages/tracing/src/integrations/node/mysql.ts b/packages/tracing/src/integrations/node/mysql.ts index 596b9df80b03..3a2a3f626293 100644 --- a/packages/tracing/src/integrations/node/mysql.ts +++ b/packages/tracing/src/integrations/node/mysql.ts @@ -2,8 +2,6 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration } from '@sentry/types'; import { fill, loadModule, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../../flags'; - interface MysqlConnection { createQuery: () => void; } @@ -27,7 +25,7 @@ export class Mysql implements Integration { const pkg = loadModule('mysql/lib/Connection.js'); if (!pkg) { - IS_DEBUG_BUILD && logger.error('Mysql Integration was unable to require `mysql` package.'); + __DEBUG_BUILD__ && logger.error('Mysql Integration was unable to require `mysql` package.'); return; } diff --git a/packages/tracing/src/integrations/node/postgres.ts b/packages/tracing/src/integrations/node/postgres.ts index 014fd2266a11..4c88be67014a 100644 --- a/packages/tracing/src/integrations/node/postgres.ts +++ b/packages/tracing/src/integrations/node/postgres.ts @@ -2,8 +2,6 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../../flags'; - interface PgClient { prototype: { query: () => void | Promise; @@ -39,12 +37,12 @@ export class Postgres implements Integration { const pkg = loadModule<{ Client: PgClient; native: { Client: PgClient } }>('pg'); if (!pkg) { - IS_DEBUG_BUILD && logger.error('Postgres Integration was unable to require `pg` package.'); + __DEBUG_BUILD__ && logger.error('Postgres Integration was unable to require `pg` package.'); return; } if (this._usePgNative && !pkg.native?.Client) { - IS_DEBUG_BUILD && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); + __DEBUG_BUILD__ && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); return; } diff --git a/packages/tracing/src/integrations/node/prisma.ts b/packages/tracing/src/integrations/node/prisma.ts index 3aa7a07f4da3..963c14206e9e 100644 --- a/packages/tracing/src/integrations/node/prisma.ts +++ b/packages/tracing/src/integrations/node/prisma.ts @@ -2,8 +2,6 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration } from '@sentry/types'; import { isThenable, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from '../../flags'; - type PrismaAction = | 'findUnique' | 'findMany' @@ -66,9 +64,10 @@ export class Prisma implements Integration { if (isValidPrismaClient(options.client)) { this._client = options.client; } else { - logger.warn( - `Unsupported Prisma client provided to PrismaIntegration. Provided client: ${JSON.stringify(options.client)}`, - ); + __DEBUG_BUILD__ && + logger.warn( + `Unsupported Prisma client provided to PrismaIntegration. Provided client: ${JSON.stringify(options.client)}`, + ); } } @@ -77,7 +76,7 @@ export class Prisma implements Integration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (!this._client) { - IS_DEBUG_BUILD && logger.error('PrismaIntegration is missing a Prisma Client Instance'); + __DEBUG_BUILD__ && logger.error('PrismaIntegration is missing a Prisma Client Instance'); return; } diff --git a/packages/tracing/src/transaction.ts b/packages/tracing/src/transaction.ts index fb6cd9d02b6c..e9f388516555 100644 --- a/packages/tracing/src/transaction.ts +++ b/packages/tracing/src/transaction.ts @@ -8,7 +8,6 @@ import { } from '@sentry/types'; import { dropUndefinedKeys, logger } from '@sentry/utils'; -import { IS_DEBUG_BUILD } from './flags'; import { Span as SpanClass, SpanRecorder } from './span'; /** JSDoc */ @@ -90,7 +89,7 @@ export class Transaction extends SpanClass implements TransactionInterface { } if (!this.name) { - IS_DEBUG_BUILD && logger.warn('Transaction has no name, falling back to ``.'); + __DEBUG_BUILD__ && logger.warn('Transaction has no name, falling back to ``.'); this.name = ''; } @@ -99,7 +98,7 @@ export class Transaction extends SpanClass implements TransactionInterface { if (this.sampled !== true) { // At this point if `sampled !== true` we want to discard the transaction. - IS_DEBUG_BUILD && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); + __DEBUG_BUILD__ && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); const client = this._hub.getClient(); if (client) { @@ -136,7 +135,7 @@ export class Transaction extends SpanClass implements TransactionInterface { const hasMeasurements = Object.keys(this._measurements).length > 0; if (hasMeasurements) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.log( '[Measurements] Adding measurements to transaction', JSON.stringify(this._measurements, undefined, 2), @@ -144,7 +143,7 @@ export class Transaction extends SpanClass implements TransactionInterface { transaction.measurements = this._measurements; } - IS_DEBUG_BUILD && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); + __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); return this._hub.captureEvent(transaction); } diff --git a/packages/types/src/globals.ts b/packages/types/src/globals.ts new file mode 100644 index 000000000000..4a3e239f8a2f --- /dev/null +++ b/packages/types/src/globals.ts @@ -0,0 +1,18 @@ +/* + * This file adds variables to the global namespace when it's loaded. We do this in order to be able to use flags and + * constants to facilitate tree shaking for users without having to import them, since the imports can confuse some + * tree-shaking algorithms. + * + * "Magic strings" like `__DEBUG_BUILD__` are declared here, but only replaced with actual values during our build + * process. + * + * See https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html and + * the Debug Build Flags section in CONTRIBUTING.md. + */ + +declare global { + const __DEBUG_BUILD__: boolean; +} + +// We need this empty export because of --isolatedModules +export type {}; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 3032d7d6cdec..aa3876e5e8ea 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -29,6 +29,10 @@ export type { Event, EventHint } from './event'; export type { EventProcessor } from './eventprocessor'; export type { Exception } from './exception'; export type { Extra, Extras } from './extra'; +// This is a dummy export, purely for the purpose of loading `globals.ts`, in order to take advantage of its side effect +// of putting variables into the global namespace. See +// https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html. +export type {} from './globals'; export type { Hub } from './hub'; export type { Integration, IntegrationClass } from './integration'; export type { Mechanism } from './mechanism'; diff --git a/packages/utils/src/baggage.ts b/packages/utils/src/baggage.ts index bc2f6568ff1f..fc8cc10ba69a 100644 --- a/packages/utils/src/baggage.ts +++ b/packages/utils/src/baggage.ts @@ -1,6 +1,5 @@ import { Baggage, BaggageObj } from '@sentry/types'; -import { IS_DEBUG_BUILD } from './flags'; import { logger } from './logger'; export const BAGGAGE_HEADER_NAME = 'baggage'; @@ -56,7 +55,7 @@ export function serializeBaggage(baggage: Baggage): string { const baggageEntry = `${SENTRY_BAGGAGE_KEY_PREFIX}${encodeURIComponent(key)}=${encodeURIComponent(val)}`; const newVal = prev === '' ? baggageEntry : `${prev},${baggageEntry}`; if (newVal.length > MAX_BAGGAGE_STRING_LENGTH) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn(`Not adding key: ${key} with val: ${val} to baggage due to exceeding baggage size limits.`); return prev; } else { diff --git a/packages/utils/src/dsn.ts b/packages/utils/src/dsn.ts index 2c43c2934fb4..35c3f0d5d141 100644 --- a/packages/utils/src/dsn.ts +++ b/packages/utils/src/dsn.ts @@ -1,7 +1,6 @@ import { DsnComponents, DsnLike, DsnProtocol } from '@sentry/types'; import { SentryError } from './error'; -import { IS_DEBUG_BUILD } from './flags'; /** Regular expression used to parse a Dsn. */ const DSN_REGEX = /^(?:(\w+):)\/\/(?:(\w+)(?::(\w+))?@)([\w.-]+)(?::(\d+))?\/(.+)/; @@ -73,7 +72,7 @@ function dsnFromComponents(components: DsnComponents): DsnComponents { } function validateDsn(dsn: DsnComponents): boolean | void { - if (!IS_DEBUG_BUILD) { + if (!__DEBUG_BUILD__) { return; } diff --git a/packages/utils/src/flags.ts b/packages/utils/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/utils/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index a77e0c8222f3..05a2a0abdf3c 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -3,7 +3,6 @@ /* eslint-disable @typescript-eslint/ban-types */ import { WrappedFunction } from '@sentry/types'; -import { IS_DEBUG_BUILD } from './flags'; import { getGlobalObject } from './global'; import { isInstanceOf, isString } from './is'; import { CONSOLE_LEVELS, logger } from './logger'; @@ -69,7 +68,7 @@ function instrument(type: InstrumentHandlerType): void { instrumentUnhandledRejection(); break; default: - IS_DEBUG_BUILD && logger.warn('unknown instrumentation type:', type); + __DEBUG_BUILD__ && logger.warn('unknown instrumentation type:', type); return; } } @@ -95,7 +94,7 @@ function triggerHandlers(type: InstrumentHandlerType, data: any): void { try { handler(data); } catch (e) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.error( `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`, e, diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index b4855c219531..4aafa404b052 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,6 +1,5 @@ import { WrappedFunction } from '@sentry/types'; -import { IS_DEBUG_BUILD } from './flags'; import { getGlobalObject, getGlobalSingleton } from './global'; // TODO: Implement different loggers for different environments @@ -68,7 +67,7 @@ function makeLogger(): Logger { }, }; - if (IS_DEBUG_BUILD) { + if (__DEBUG_BUILD__) { CONSOLE_LEVELS.forEach(name => { // eslint-disable-next-line @typescript-eslint/no-explicit-any logger[name] = (...args: any[]) => { @@ -90,7 +89,7 @@ function makeLogger(): Logger { // Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used let logger: Logger; -if (IS_DEBUG_BUILD) { +if (__DEBUG_BUILD__) { logger = getGlobalSingleton('logger', makeLogger); } else { logger = makeLogger(); diff --git a/packages/utils/src/supports.ts b/packages/utils/src/supports.ts index e9109da84ec2..e42ac6443c67 100644 --- a/packages/utils/src/supports.ts +++ b/packages/utils/src/supports.ts @@ -1,4 +1,3 @@ -import { IS_DEBUG_BUILD } from './flags'; import { getGlobalObject } from './global'; import { logger } from './logger'; @@ -113,7 +112,7 @@ export function supportsNativeFetch(): boolean { } doc.head.removeChild(sandbox); } catch (err) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err); } } diff --git a/packages/utils/test/dsn.test.ts b/packages/utils/test/dsn.test.ts index d5d5d1c11c54..c9088c878e18 100644 --- a/packages/utils/test/dsn.test.ts +++ b/packages/utils/test/dsn.test.ts @@ -1,6 +1,5 @@ import { dsnToString, makeDsn } from '../src/dsn'; import { SentryError } from '../src/error'; -import { IS_DEBUG_BUILD } from '../src/flags'; function testIf(condition: boolean): jest.It { return condition ? test : test.skip; @@ -42,7 +41,7 @@ describe('Dsn', () => { expect(dsn.projectId).toBe('123'); }); - testIf(IS_DEBUG_BUILD)('throws for missing components', () => { + testIf(__DEBUG_BUILD__)('throws for missing components', () => { expect(() => makeDsn({ host: '', @@ -77,7 +76,7 @@ describe('Dsn', () => { ).toThrow(SentryError); }); - testIf(IS_DEBUG_BUILD)('throws for invalid components', () => { + testIf(__DEBUG_BUILD__)('throws for invalid components', () => { expect(() => makeDsn({ host: 'sentry.io', @@ -143,18 +142,18 @@ describe('Dsn', () => { expect(dsn.projectId).toBe('321'); }); - testIf(IS_DEBUG_BUILD)('throws when provided invalid Dsn', () => { + testIf(__DEBUG_BUILD__)('throws when provided invalid Dsn', () => { expect(() => makeDsn('some@random.dsn')).toThrow(SentryError); }); - testIf(IS_DEBUG_BUILD)('throws without mandatory fields', () => { + testIf(__DEBUG_BUILD__)('throws without mandatory fields', () => { expect(() => makeDsn('://abc@sentry.io/123')).toThrow(SentryError); expect(() => makeDsn('https://@sentry.io/123')).toThrow(SentryError); expect(() => makeDsn('https://abc@123')).toThrow(SentryError); expect(() => makeDsn('https://abc@sentry.io/')).toThrow(SentryError); }); - testIf(IS_DEBUG_BUILD)('throws for invalid fields', () => { + testIf(__DEBUG_BUILD__)('throws for invalid fields', () => { expect(() => makeDsn('httpx://abc@sentry.io/123')).toThrow(SentryError); expect(() => makeDsn('httpx://abc@sentry.io:xxx/123')).toThrow(SentryError); expect(() => makeDsn('http://abc@sentry.io/abc')).toThrow(SentryError); diff --git a/packages/vue/src/flags.ts b/packages/vue/src/flags.ts deleted file mode 100644 index fb99adbc2aa7..000000000000 --- a/packages/vue/src/flags.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file defines flags and constants that can be modified during compile time in order to facilitate tree shaking - * for users. - * - * Debug flags need to be declared in each package individually and must not be imported across package boundaries, - * because some build tools have trouble tree-shaking imported guards. - * - * As a convention, we define debug flags in a `flags.ts` file in the root of a package's `src` folder. - * - * Debug flag files will contain "magic strings" like `__SENTRY_DEBUG__` that may get replaced with actual values during - * our, or the user's build process. Take care when introducing new flags - they must not throw if they are not - * replaced. - */ - -declare const __SENTRY_DEBUG__: boolean; - -/** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/vue/src/sdk.ts b/packages/vue/src/sdk.ts index 0cd7701ad3db..1de282d8de54 100644 --- a/packages/vue/src/sdk.ts +++ b/packages/vue/src/sdk.ts @@ -3,7 +3,6 @@ import { getGlobalObject, logger } from '@sentry/utils'; import { DEFAULT_HOOKS } from './constants'; import { attachErrorHandler } from './errorhandler'; -import { IS_DEBUG_BUILD } from './flags'; import { createTracingMixins } from './tracing'; import { Options, TracingOptions, Vue } from './types'; @@ -42,7 +41,7 @@ export function init( browserInit(options); if (!options.Vue && !options.app) { - IS_DEBUG_BUILD && + __DEBUG_BUILD__ && logger.warn( 'Misconfigured SDK. Vue specific errors will not be captured.\n' + 'Update your `Sentry.init` call with an appropriate config option:\n' + diff --git a/packages/vue/src/tracing.ts b/packages/vue/src/tracing.ts index 304d379a4983..30baf205daf5 100644 --- a/packages/vue/src/tracing.ts +++ b/packages/vue/src/tracing.ts @@ -4,7 +4,6 @@ import { logger, timestampInSeconds } from '@sentry/utils'; import { formatComponentName } from './components'; import { DEFAULT_HOOKS } from './constants'; -import { IS_DEBUG_BUILD } from './flags'; import { Hook, Operation, TracingOptions, ViewModel, Vue } from './types'; const VUE_OP = 'ui.vue'; @@ -61,7 +60,7 @@ export const createTracingMixins = (options: TracingOptions): Mixins => { // eg. mount => ['beforeMount', 'mounted'] const internalHooks = HOOKS[operation]; if (!internalHooks) { - IS_DEBUG_BUILD && logger.warn(`Unknown hook: ${operation}`); + __DEBUG_BUILD__ && logger.warn(`Unknown hook: ${operation}`); continue; } diff --git a/rollup/bundleHelpers.js b/rollup/bundleHelpers.js index a406ae6905de..33555c3ae5ad 100644 --- a/rollup/bundleHelpers.js +++ b/rollup/bundleHelpers.js @@ -157,7 +157,7 @@ export function makeBundleConfigVariants(baseConfig, options = {}) { output: { entryFileNames: chunkInfo => `${baseConfig.output.entryFileNames(chunkInfo)}.debug.min.js`, }, - plugins: [terserPlugin], + plugins: [includeDebuggingPlugin, terserPlugin], }, }; diff --git a/rollup/npmHelpers.js b/rollup/npmHelpers.js index c0b983dac158..05ecf8ffafbf 100644 --- a/rollup/npmHelpers.js +++ b/rollup/npmHelpers.js @@ -14,6 +14,7 @@ import { makeRemoveBlankLinesPlugin, makeRemoveESLintCommentsPlugin, makeSucrasePlugin, + makeDebugBuildStatementReplacePlugin, } from './plugins/index.js'; import { mergePlugins } from './utils'; @@ -29,6 +30,7 @@ export function makeBaseNPMConfig(options = {}) { const nodeResolvePlugin = makeNodeResolvePlugin(); const sucrasePlugin = makeSucrasePlugin(); + const debugBuildStatementReplacePlugin = makeDebugBuildStatementReplacePlugin(); const constToVarPlugin = makeConstToVarPlugin(); const removeESLintCommentsPlugin = makeRemoveESLintCommentsPlugin(); const removeBlankLinesPlugin = makeRemoveBlankLinesPlugin(); @@ -80,6 +82,7 @@ export function makeBaseNPMConfig(options = {}) { plugins: [ nodeResolvePlugin, sucrasePlugin, + debugBuildStatementReplacePlugin, constToVarPlugin, removeESLintCommentsPlugin, removeBlankLinesPlugin, diff --git a/rollup/plugins/bundlePlugins.js b/rollup/plugins/bundlePlugins.js index 59f3fec01cd1..7d4c7a9023cd 100644 --- a/rollup/plugins/bundlePlugins.js +++ b/rollup/plugins/bundlePlugins.js @@ -46,9 +46,12 @@ export function makeLicensePlugin(title) { */ export function makeIsDebugBuildPlugin(includeDebugging) { return replace({ - // __SENTRY_DEBUG__ should be save to replace in any case, so no checks for assignments necessary + // __DEBUG_BUILD__ and __SENTRY_DEBUG__ are safe to replace in any case, so no checks for assignments necessary preventAssignment: false, values: { + // Flags in current package + __DEBUG_BUILD__: includeDebugging, + // Flags in built monorepo dependencies, from which the bundle pulls __SENTRY_DEBUG__: includeDebugging, }, }); diff --git a/rollup/plugins/npmPlugins.js b/rollup/plugins/npmPlugins.js index ccdb99bb2ba1..87e2927d53bd 100644 --- a/rollup/plugins/npmPlugins.js +++ b/rollup/plugins/npmPlugins.js @@ -127,4 +127,20 @@ export function makeRemoveBlankLinesPlugin() { }); } +/** + * Creates a plugin to replace all instances of "__DEBUG_BUILD__" with a safe statement that + * a) evaluates to `true` + * b) can easily be modified by our users' bundlers to evaluate to false, facilitating the treeshaking of logger code. + * + * @returns A `@rollup/plugin-replace` instance. + */ +export function makeDebugBuildStatementReplacePlugin() { + return replace({ + preventAssignment: false, + values: { + __DEBUG_BUILD__: "(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)", + }, + }); +} + export { makeExtractPolyfillsPlugin } from './extractPolyfillsPlugin.js';