From 45835328ddae5880bb59307ec6f0ff6a4a3c4623 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 Apr 2022 09:39:33 +0000 Subject: [PATCH 1/4] ref(build): Add debug constants in each package --- packages/angular/src/flags.ts | 9 ++++++ packages/angular/src/tracing.ts | 5 ++-- packages/browser/src/client.ts | 5 ++-- packages/browser/src/flags.ts | 9 ++++++ packages/browser/src/helpers.ts | 7 +++-- packages/browser/src/integrations/dedupe.ts | 6 ++-- .../src/integrations/globalhandlers.ts | 4 +-- packages/browser/src/sdk.ts | 9 +++--- packages/browser/src/transports/base.ts | 12 ++++---- packages/browser/src/transports/utils.ts | 6 ++-- packages/core/src/basebackend.ts | 15 +++++----- packages/core/src/baseclient.ts | 14 ++++----- packages/core/src/flags.ts | 9 ++++++ packages/core/src/integration.ts | 6 ++-- .../core/src/integrations/inboundfilters.ts | 16 +++++----- packages/core/src/sdk.ts | 6 ++-- packages/hub/src/flags.ts | 9 ++++++ packages/hub/src/hub.ts | 17 ++++------- packages/hub/src/sessionflusher.ts | 7 +++-- packages/integrations/src/angular.ts | 8 +++-- packages/integrations/src/dedupe.ts | 6 ++-- packages/integrations/src/ember.ts | 6 ++-- packages/integrations/src/extraerrordata.ts | 6 ++-- packages/integrations/src/flags.ts | 9 ++++++ packages/integrations/src/offline.ts | 16 +++++----- packages/integrations/src/vue.ts | 14 +++++---- packages/nextjs/src/config/webpack.ts | 5 ++-- packages/nextjs/src/flags.ts | 9 ++++++ packages/nextjs/src/index.server.ts | 11 +++---- packages/nextjs/src/utils/instrumentServer.ts | 6 ++-- packages/nextjs/src/utils/withSentry.ts | 19 +++++------- packages/node/src/client.ts | 7 +++-- packages/node/src/flags.ts | 9 ++++++ packages/node/src/handlers.ts | 4 +-- packages/node/src/integrations/http.ts | 5 ++-- .../src/integrations/onuncaughtexception.ts | 5 ++-- .../src/integrations/utils/errorhandling.ts | 7 +++-- packages/node/src/sdk.ts | 7 +++-- packages/node/src/transports/base/index.ts | 4 +-- packages/react/src/errorboundary.tsx | 6 ++-- packages/react/src/flags.ts | 9 ++++++ packages/serverless/src/awslambda.ts | 13 ++++---- packages/serverless/src/flags.ts | 9 ++++++ .../src/gcpfunction/cloud_events.ts | 5 ++-- packages/serverless/src/gcpfunction/events.ts | 5 ++-- packages/serverless/src/gcpfunction/http.ts | 5 ++-- packages/tracing/src/browser/backgroundtab.ts | 7 +++-- .../tracing/src/browser/browsertracing.ts | 15 +++++----- packages/tracing/src/browser/metrics.ts | 30 ++++++++----------- packages/tracing/src/browser/router.ts | 8 +++-- packages/tracing/src/errors.ts | 5 ++-- packages/tracing/src/flags.ts | 9 ++++++ packages/tracing/src/hubextensions.ts | 15 +++++----- packages/tracing/src/idletransaction.ts | 29 +++++++++--------- .../tracing/src/integrations/node/express.ts | 6 ++-- .../tracing/src/integrations/node/mongo.ts | 6 ++-- .../tracing/src/integrations/node/mysql.ts | 6 ++-- .../tracing/src/integrations/node/postgres.ts | 8 +++-- packages/tracing/src/transaction.ts | 11 +++---- packages/utils/src/dsn.ts | 4 +-- packages/utils/src/env.ts | 20 +++++-------- packages/utils/src/flags.ts | 9 ++++++ packages/utils/src/instrument.ts | 6 ++-- packages/utils/src/logger.ts | 4 +-- packages/utils/src/supports.ts | 4 +-- packages/utils/test/dsn.test.ts | 13 ++++---- packages/vue/src/flags.ts | 9 ++++++ packages/vue/src/sdk.ts | 5 ++-- packages/vue/src/tracing.ts | 5 ++-- rollup.config.js | 5 ++-- 70 files changed, 385 insertions(+), 240 deletions(-) create mode 100644 packages/angular/src/flags.ts create mode 100644 packages/browser/src/flags.ts create mode 100644 packages/core/src/flags.ts create mode 100644 packages/hub/src/flags.ts create mode 100644 packages/integrations/src/flags.ts create mode 100644 packages/nextjs/src/flags.ts create mode 100644 packages/node/src/flags.ts create mode 100644 packages/react/src/flags.ts create mode 100644 packages/serverless/src/flags.ts create mode 100644 packages/tracing/src/flags.ts create mode 100644 packages/utils/src/flags.ts create mode 100644 packages/vue/src/flags.ts diff --git a/packages/angular/src/flags.ts b/packages/angular/src/flags.ts new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/angular/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/angular/src/tracing.ts b/packages/angular/src/tracing.ts index df45270f14d3..1a4352e6994a 100644 --- a/packages/angular/src/tracing.ts +++ b/packages/angular/src/tracing.ts @@ -2,11 +2,12 @@ import { AfterViewInit, Directive, Injectable, Input, NgModule, OnDestroy, OnIni import { Event, NavigationEnd, NavigationStart, Router } from '@angular/router'; import { getCurrentHub } from '@sentry/browser'; import { Span, Transaction, TransactionContext } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, logger, stripUrlQueryAndFragment, timestampWithMs } from '@sentry/utils'; +import { getGlobalObject, logger, stripUrlQueryAndFragment, timestampWithMs } from '@sentry/utils'; import { Observable, Subscription } from 'rxjs'; import { filter, tap } from 'rxjs/operators'; import { ANGULAR_INIT_OP, ANGULAR_OP, ANGULAR_ROUTING_OP } from './constants'; +import { IS_DEBUG_BUILD } from './flags'; import { runOutsideAngular } from './zone'; let instrumentationInitialized: boolean; @@ -63,7 +64,7 @@ export class TraceService implements OnDestroy { filter(event => event instanceof NavigationStart), tap(event => { if (!instrumentationInitialized) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.error('Angular integration has tracing enabled, but Tracing integration is not configured'); return; } diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index e036e5d67879..75aab49db77b 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -1,8 +1,9 @@ import { BaseClient, Scope, SDK_VERSION } from '@sentry/core'; import { Event, EventHint } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +import { getGlobalObject, logger } from '@sentry/utils'; import { BrowserBackend, BrowserOptions } from './backend'; +import { IS_DEBUG_BUILD } from './flags'; import { injectReportDialog, ReportDialogOptions } from './helpers'; import { Breadcrumbs } from './integrations'; @@ -47,7 +48,7 @@ export class BrowserClient extends BaseClient { } if (!this._isEnabled()) { - isDebugBuild() && logger.error('Trying to call showReportDialog with Sentry Client disabled'); + IS_DEBUG_BUILD && logger.error('Trying to call showReportDialog with Sentry Client disabled'); return; } diff --git a/packages/browser/src/flags.ts b/packages/browser/src/flags.ts new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/browser/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/browser/src/helpers.ts b/packages/browser/src/helpers.ts index 46a8919ee7c6..d0b3f8f5c9aa 100644 --- a/packages/browser/src/helpers.ts +++ b/packages/browser/src/helpers.ts @@ -6,11 +6,12 @@ import { addNonEnumerableProperty, getGlobalObject, getOriginalFunction, - isDebugBuild, logger, markFunctionWrapped, } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from './flags'; + const global = getGlobalObject(); let ignoreOnError: number = 0; @@ -192,12 +193,12 @@ export function injectReportDialog(options: ReportDialogOptions = {}): void { } if (!options.eventId) { - isDebugBuild() && logger.error('Missing eventId option in showReportDialog call'); + IS_DEBUG_BUILD && logger.error('Missing eventId option in showReportDialog call'); return; } if (!options.dsn) { - isDebugBuild() && logger.error('Missing dsn option in showReportDialog call'); + IS_DEBUG_BUILD && 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 e2e22c3975cd..24e01d2f1226 100644 --- a/packages/browser/src/integrations/dedupe.ts +++ b/packages/browser/src/integrations/dedupe.ts @@ -1,5 +1,7 @@ import { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; -import { isDebugBuild, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from '../flags'; /** Deduplication filter */ export class Dedupe implements Integration { @@ -28,7 +30,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, self._previousEvent)) { - isDebugBuild() && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + IS_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 09ee6f16a643..19ee594afaf3 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -5,7 +5,6 @@ import { addExceptionMechanism, addInstrumentationHandler, getLocationHref, - isDebugBuild, isErrorEvent, isPrimitive, isString, @@ -13,6 +12,7 @@ import { } from '@sentry/utils'; import { eventFromUnknownInput } from '../eventbuilder'; +import { IS_DEBUG_BUILD } from '../flags'; import { shouldIgnoreOnError } from '../helpers'; type GlobalHandlersIntegrationsOptionKeys = 'onerror' | 'onunhandledrejection'; @@ -237,7 +237,7 @@ function _enhanceEventWithInitialFrame(event: Event, url: any, line: any, column } function globalHandlerLog(type: string): void { - isDebugBuild() && logger.log(`Global Handler attached: ${type}`); + IS_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 f776df5a8392..3f05a646c96f 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -1,9 +1,10 @@ import { getCurrentHub, initAndBind, Integrations as CoreIntegrations } from '@sentry/core'; import { Hub } from '@sentry/types'; -import { addInstrumentationHandler, getGlobalObject, isDebugBuild, logger, resolvedSyncPromise } from '@sentry/utils'; +import { addInstrumentationHandler, getGlobalObject, logger, resolvedSyncPromise } from '@sentry/utils'; import { BrowserOptions } from './backend'; import { BrowserClient } from './client'; +import { IS_DEBUG_BUILD } from './flags'; import { ReportDialogOptions, wrap as internalWrap } from './helpers'; import { Breadcrumbs, Dedupe, GlobalHandlers, LinkedErrors, TryCatch, UserAgent } from './integrations'; @@ -162,7 +163,7 @@ export function flush(timeout?: number): PromiseLike { if (client) { return client.flush(timeout); } - isDebugBuild() && logger.warn('Cannot flush events. No client defined.'); + IS_DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.'); return resolvedSyncPromise(false); } @@ -179,7 +180,7 @@ export function close(timeout?: number): PromiseLike { if (client) { return client.close(timeout); } - isDebugBuild() && logger.warn('Cannot flush events and disable SDK. No client defined.'); + IS_DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.'); return resolvedSyncPromise(false); } @@ -208,7 +209,7 @@ function startSessionTracking(): void { const document = window.document; if (typeof document === 'undefined') { - isDebugBuild() && logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); + IS_DEBUG_BUILD && 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 3728012a4bb3..c7785b4eb7c5 100644 --- a/packages/browser/src/transports/base.ts +++ b/packages/browser/src/transports/base.ts @@ -23,7 +23,6 @@ import { dsnToString, eventStatusFromHttpCode, getGlobalObject, - isDebugBuild, isRateLimited, logger, makePromiseBuffer, @@ -33,6 +32,7 @@ import { updateRateLimits, } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from '../flags'; import { sendReport } from './utils'; function requestTypeToCategory(ty: SentryRequestType): string { @@ -108,7 +108,7 @@ 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 = `${requestTypeToCategory(category)}:${reason}`; - isDebugBuild() && logger.log(`Adding outcome: ${key}`); + IS_DEBUG_BUILD && logger.log(`Adding outcome: ${key}`); this._outcomes[key] = (this._outcomes[key] ?? 0) + 1; } @@ -125,11 +125,11 @@ export abstract class BaseTransport implements Transport { // Nothing to send if (!Object.keys(outcomes).length) { - isDebugBuild() && logger.log('No outcomes to flush'); + IS_DEBUG_BUILD && logger.log('No outcomes to flush'); return; } - isDebugBuild() && logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); + IS_DEBUG_BUILD && logger.log(`Flushing outcomes:\n${JSON.stringify(outcomes, null, 2)}`); const url = getEnvelopeEndpointWithUrlEncodedAuth(this._api.dsn, this._api.tunnel); @@ -147,7 +147,7 @@ export abstract class BaseTransport implements Transport { try { sendReport(url, serializeEnvelope(envelope)); } catch (e) { - isDebugBuild() && logger.error(e); + IS_DEBUG_BUILD && logger.error(e); } } @@ -172,7 +172,7 @@ export abstract class BaseTransport implements Transport { this._rateLimits = updateRateLimits(this._rateLimits, headers); // eslint-disable-next-line deprecation/deprecation if (this._isRateLimited(requestType)) { - isDebugBuild() && + IS_DEBUG_BUILD && // eslint-disable-next-line deprecation/deprecation logger.warn(`Too many ${requestType} requests, backing off until: ${this._disabledUntil(requestType)}`); } diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index 962a05208466..5fc614d6b86f 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -1,4 +1,6 @@ -import { forget, getGlobalObject, isDebugBuild, isNativeFetch, logger, supportsFetch } from '@sentry/utils'; +import { forget, getGlobalObject, isNativeFetch, logger, supportsFetch } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from '../flags'; const global = getGlobalObject(); let cachedFetchImpl: FetchImpl; @@ -69,7 +71,7 @@ export function getNativeFetchImplementation(): FetchImpl { } document.head.removeChild(sandbox); } catch (e) { - isDebugBuild() && + IS_DEBUG_BUILD && 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 f770c5aa0d8c..92bdd4e7f65c 100644 --- a/packages/core/src/basebackend.ts +++ b/packages/core/src/basebackend.ts @@ -1,7 +1,8 @@ import { Event, EventHint, Options, Session, Severity, Transport } from '@sentry/types'; -import { isDebugBuild, logger, SentryError } from '@sentry/utils'; +import { logger, SentryError } from '@sentry/utils'; import { initAPIDetails } from './api'; +import { IS_DEBUG_BUILD } from './flags'; import { createEventEnvelope, createSessionEnvelope } from './request'; import { NewTransport } from './transports/base'; import { NoopTransport } from './transports/noop'; @@ -73,7 +74,7 @@ export abstract class BaseBackend implements Backend { public constructor(options: O) { this._options = options; if (!this._options.dsn) { - isDebugBuild() && logger.warn('No DSN provided, backend will not do anything.'); + IS_DEBUG_BUILD && logger.warn('No DSN provided, backend will not do anything.'); } this._transport = this._setupTransport(); } @@ -107,11 +108,11 @@ export abstract class BaseBackend implements Backend { const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel); const env = createEventEnvelope(event, api); void this._newTransport.send(env).then(null, reason => { - isDebugBuild() && logger.error('Error while sending event:', reason); + IS_DEBUG_BUILD && logger.error('Error while sending event:', reason); }); } else { void this._transport.sendEvent(event).then(null, reason => { - isDebugBuild() && logger.error('Error while sending event:', reason); + IS_DEBUG_BUILD && logger.error('Error while sending event:', reason); }); } } @@ -121,7 +122,7 @@ export abstract class BaseBackend implements Backend { */ public sendSession(session: Session): void { if (!this._transport.sendSession) { - isDebugBuild() && logger.warn("Dropping session because custom transport doesn't implement sendSession"); + IS_DEBUG_BUILD && logger.warn("Dropping session because custom transport doesn't implement sendSession"); return; } @@ -135,11 +136,11 @@ export abstract class BaseBackend implements Backend { const api = initAPIDetails(this._options.dsn, this._options._metadata, this._options.tunnel); const [env] = createSessionEnvelope(session, api); void this._newTransport.send(env).then(null, reason => { - isDebugBuild() && logger.error('Error while sending session:', reason); + IS_DEBUG_BUILD && logger.error('Error while sending session:', reason); }); } else { void this._transport.sendSession(session).then(null, reason => { - isDebugBuild() && logger.error('Error while sending session:', reason); + IS_DEBUG_BUILD && logger.error('Error while sending session:', reason); }); } } diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 1195d7473c39..89c133116c3b 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -14,7 +14,6 @@ import { import { checkOrSetAlreadyCaught, dateTimestampInSeconds, - isDebugBuild, isPlainObject, isPrimitive, isThenable, @@ -30,6 +29,7 @@ import { } from '@sentry/utils'; import { Backend, BackendClass } from './basebackend'; +import { IS_DEBUG_BUILD } from './flags'; import { IntegrationIndex, setupIntegrations } from './integration'; const ALREADY_SEEN_ERROR = "Not capturing exception because it's already been captured."; @@ -108,7 +108,7 @@ 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)) { - isDebugBuild() && logger.log(ALREADY_SEEN_ERROR); + IS_DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); return; } @@ -153,7 +153,7 @@ 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 && hint.originalException && checkOrSetAlreadyCaught(hint.originalException)) { - isDebugBuild() && logger.log(ALREADY_SEEN_ERROR); + IS_DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); return; } @@ -173,12 +173,12 @@ export abstract class BaseClient implement */ public captureSession(session: Session): void { if (!this._isEnabled()) { - isDebugBuild() && logger.warn('SDK not enabled, will not capture session.'); + IS_DEBUG_BUILD && logger.warn('SDK not enabled, will not capture session.'); return; } if (!(typeof session.release === 'string')) { - isDebugBuild() && logger.warn('Discarded session because of missing or non-string release'); + IS_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 @@ -244,7 +244,7 @@ export abstract class BaseClient implement try { return (this._integrations[integration.id] as T) || null; } catch (_oO) { - isDebugBuild() && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); + IS_DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); return null; } } @@ -503,7 +503,7 @@ export abstract class BaseClient implement return finalEvent.event_id; }, reason => { - isDebugBuild() && logger.error(reason); + IS_DEBUG_BUILD && logger.error(reason); return undefined; }, ); diff --git a/packages/core/src/flags.ts b/packages/core/src/flags.ts new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/core/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 6d8b9fe3fd50..cc694c815289 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,6 +1,8 @@ import { addGlobalEventProcessor, getCurrentHub } from '@sentry/hub'; import { Integration, Options } from '@sentry/types'; -import { addNonEnumerableProperty, isDebugBuild, logger } from '@sentry/utils'; +import { addNonEnumerableProperty, logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from './flags'; export const installedIntegrations: string[] = []; @@ -59,7 +61,7 @@ export function setupIntegration(integration: Integration): void { } integration.setupOnce(addGlobalEventProcessor, getCurrentHub); installedIntegrations.push(integration.name); - isDebugBuild() && logger.log(`Integration installed: ${integration.name}`); + IS_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 04d395b69534..ff6c616c442d 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -1,5 +1,7 @@ import { Event, EventProcessor, Hub, Integration, StackFrame } from '@sentry/types'; -import { getEventDescription, isDebugBuild, isMatchingPattern, logger } from '@sentry/utils'; +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. @@ -86,19 +88,19 @@ export function _mergeOptions( /** JSDoc */ export function _shouldDropEvent(event: Event, options: Partial): boolean { if (options.ignoreInternal && _isSentryError(event)) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); return true; } if (_isIgnoredError(event, options.ignoreErrors)) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`, ); return true; } if (_isDeniedUrl(event, options.denyUrls)) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription( event, @@ -107,7 +109,7 @@ export function _shouldDropEvent(event: Event, options: Partial = new (options: O) => F; @@ -14,7 +16,7 @@ export type ClientClass = new (options: O) */ export function initAndBind(clientClass: ClientClass, options: O): void { if (options.debug === true) { - if (isDebugBuild()) { + if (IS_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/hub/src/flags.ts b/packages/hub/src/flags.ts new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/hub/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/hub/src/hub.ts b/packages/hub/src/hub.ts index 22d284f54acd..5aee3969afed 100644 --- a/packages/hub/src/hub.ts +++ b/packages/hub/src/hub.ts @@ -20,16 +20,9 @@ import { TransactionContext, User, } from '@sentry/types'; -import { - consoleSandbox, - dateTimestampInSeconds, - getGlobalObject, - isDebugBuild, - isNodeEnv, - logger, - uuid4, -} from '@sentry/utils'; +import { consoleSandbox, dateTimestampInSeconds, getGlobalObject, isNodeEnv, logger, uuid4 } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from './flags'; import { Scope } from './scope'; import { Session } from './session'; @@ -379,7 +372,7 @@ export class Hub implements HubInterface { try { return client.getIntegration(integration); } catch (_oO) { - isDebugBuild() && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); + IS_DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); return null; } } @@ -511,7 +504,7 @@ export class Hub implements HubInterface { if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') { return sentry.extensions[method].apply(this, args); } - isDebugBuild() && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); + IS_DEBUG_BUILD && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); } } @@ -574,7 +567,7 @@ export function getCurrentHub(): Hub { */ // eslint-disable-next-line deprecation/deprecation export function getActiveDomain(): DomainAsCarrier | undefined { - isDebugBuild() && logger.warn('Function `getActiveDomain` is deprecated and will be removed in a future version.'); + IS_DEBUG_BUILD && logger.warn('Function `getActiveDomain` is deprecated and will be removed in a future version.'); const sentry = getMainCarrier().__SENTRY__; diff --git a/packages/hub/src/sessionflusher.ts b/packages/hub/src/sessionflusher.ts index fd5f82548f89..fcc4386c70d8 100644 --- a/packages/hub/src/sessionflusher.ts +++ b/packages/hub/src/sessionflusher.ts @@ -5,8 +5,9 @@ import { SessionFlusherLike, Transport, } from '@sentry/types'; -import { dropUndefinedKeys, isDebugBuild, logger } from '@sentry/utils'; +import { dropUndefinedKeys, logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from './flags'; import { getCurrentHub } from './hub'; type ReleaseHealthAttributes = { @@ -35,11 +36,11 @@ export class SessionFlusher implements SessionFlusherLike { /** Sends session aggregates to Transport */ public sendSessionAggregates(sessionAggregates: SessionAggregates): void { if (!this._transport.sendSession) { - isDebugBuild() && logger.warn("Dropping session because custom transport doesn't implement sendSession"); + IS_DEBUG_BUILD && logger.warn("Dropping session because custom transport doesn't implement sendSession"); return; } void this._transport.sendSession(sessionAggregates).then(null, reason => { - isDebugBuild() && logger.error('Error while sending session:', reason); + IS_DEBUG_BUILD && logger.error('Error while sending session:', reason); }); } diff --git a/packages/integrations/src/angular.ts b/packages/integrations/src/angular.ts index 727937d67a33..dc71042700ff 100644 --- a/packages/integrations/src/angular.ts +++ b/packages/integrations/src/angular.ts @@ -1,5 +1,7 @@ import { Event, EventProcessor, Hub, Integration } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +import { getGlobalObject, logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from './flags'; // See https://github.com/angular/angular.js/blob/v1.4.7/src/minErr.js const angularPattern = /^\[((?:[$a-zA-Z0-9]+:)?(?:[$a-zA-Z0-9]+))\] (.*?)\n?(\S+)$/; @@ -47,13 +49,13 @@ export class Angular implements Integration { */ // eslint-disable-next-line @typescript-eslint/no-explicit-any public constructor(options: { angular?: any } = {}) { - isDebugBuild() && logger.log('You are still using the Angular integration, consider moving to @sentry/angular'); + IS_DEBUG_BUILD && logger.log('You are still using the Angular integration, consider moving to @sentry/angular'); // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-member-access this._angular = options.angular || getGlobalObject().angular; if (!this._angular) { - isDebugBuild() && logger.error('AngularIntegration is missing an Angular instance'); + IS_DEBUG_BUILD && logger.error('AngularIntegration is missing an Angular instance'); return; } diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index c6817a71ec39..2ce72a6b636c 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,5 +1,7 @@ import { Event, EventProcessor, Exception, Hub, Integration, StackFrame } from '@sentry/types'; -import { isDebugBuild, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from './flags'; /** Deduplication filter */ export class Dedupe implements Integration { @@ -28,7 +30,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, self._previousEvent)) { - isDebugBuild() && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + IS_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/ember.ts b/packages/integrations/src/ember.ts index c045b8ffabcc..81bbd1a0036b 100644 --- a/packages/integrations/src/ember.ts +++ b/packages/integrations/src/ember.ts @@ -1,5 +1,7 @@ import { EventProcessor, Hub, Integration } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, isInstanceOf, logger } from '@sentry/utils'; +import { getGlobalObject, isInstanceOf, logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from './flags'; /** JSDoc */ export class Ember implements Integration { @@ -33,7 +35,7 @@ export class Ember implements Integration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (!this._Ember) { - isDebugBuild() && logger.error('EmberIntegration is missing an Ember instance'); + IS_DEBUG_BUILD && logger.error('EmberIntegration is missing an Ember instance'); return; } diff --git a/packages/integrations/src/extraerrordata.ts b/packages/integrations/src/extraerrordata.ts index 6ed5c06b9de9..aad7210a85b2 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,5 +1,7 @@ import { Event, EventHint, EventProcessor, ExtendedError, Hub, Integration } from '@sentry/types'; -import { isDebugBuild, isError, isPlainObject, logger, normalize } from '@sentry/utils'; +import { isError, isPlainObject, logger, normalize } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from './flags'; /** JSDoc */ interface ExtraErrorDataOptions { @@ -120,7 +122,7 @@ export class ExtraErrorData implements Integration { return extraErrorInfo; } catch (oO) { - isDebugBuild() && logger.error('Unable to extract extra data from the Error object:', oO); + IS_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 new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/integrations/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/integrations/src/offline.ts b/packages/integrations/src/offline.ts index 383e4901e5c9..0d2da0841805 100644 --- a/packages/integrations/src/offline.ts +++ b/packages/integrations/src/offline.ts @@ -1,9 +1,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ /* eslint-disable @typescript-eslint/no-unsafe-member-access */ import { Event, EventProcessor, Hub, Integration } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, logger, normalize, uuid4 } from '@sentry/utils'; +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( @@ -73,7 +75,7 @@ export class Offline implements Integration { if ('addEventListener' in this.global) { this.global.addEventListener('online', () => { void this._sendEvents().catch(() => { - isDebugBuild() && logger.warn('could not send cached events'); + IS_DEBUG_BUILD && logger.warn('could not send cached events'); }); }); } @@ -85,7 +87,7 @@ export class Offline implements Integration { void this._cacheEvent(event) .then((_event: Event): Promise => this._enforceMaxEvents()) .catch((_error): void => { - isDebugBuild() && logger.warn('could not cache event while offline'); + IS_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 @@ -99,7 +101,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(() => { - isDebugBuild() && logger.warn('could not send cached events'); + IS_DEBUG_BUILD && logger.warn('could not send cached events'); }); } } @@ -135,7 +137,7 @@ export class Offline implements Integration { ), ) .catch((_error): void => { - isDebugBuild() && logger.warn('could not enforce max events'); + IS_DEBUG_BUILD && logger.warn('could not enforce max events'); }); } @@ -163,10 +165,10 @@ export class Offline implements Integration { this.hub.captureEvent(event); void this._purgeEvent(cacheKey).catch((_error): void => { - isDebugBuild() && logger.warn('could not purge event from cache'); + IS_DEBUG_BUILD && logger.warn('could not purge event from cache'); }); } else { - isDebugBuild() && logger.warn('no hub found - could not send cached event'); + IS_DEBUG_BUILD && logger.warn('no hub found - could not send cached event'); } }); } diff --git a/packages/integrations/src/vue.ts b/packages/integrations/src/vue.ts index aefc8a89767b..1b1cf3caa63a 100644 --- a/packages/integrations/src/vue.ts +++ b/packages/integrations/src/vue.ts @@ -1,7 +1,9 @@ /* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { EventProcessor, Hub, Integration, IntegrationClass, Scope, Span, Transaction } from '@sentry/types'; -import { basename, getGlobalObject, isDebugBuild, logger, timestampWithMs } from '@sentry/utils'; +import { basename, getGlobalObject, logger, timestampWithMs } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from './flags'; /** * Used to extract Tracing integration from the current client, @@ -156,7 +158,7 @@ export class Vue implements Integration { public constructor( options: Partial & { tracingOptions: Partial }>, ) { - isDebugBuild() && logger.log('You are still using the Vue.js integration, consider moving to @sentry/vue'); + IS_DEBUG_BUILD && logger.log('You are still using the Vue.js integration, consider moving to @sentry/vue'); this._options = { // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access Vue: getGlobalObject().Vue, @@ -178,7 +180,7 @@ export class Vue implements Integration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (!this._options.Vue) { - isDebugBuild() && logger.error('Vue integration is missing a Vue instance'); + IS_DEBUG_BUILD && logger.error('Vue integration is missing a Vue instance'); return; } @@ -325,7 +327,7 @@ export class Vue implements Integration { const internalHooks = HOOKS[operation]; if (!internalHooks) { - isDebugBuild() && logger.warn(`Unknown hook: ${operation}`); + IS_DEBUG_BUILD && logger.warn(`Unknown hook: ${operation}`); return; } @@ -382,7 +384,7 @@ export class Vue implements Integration { // `this` points to currently rendered component applyTracingHooks(this, getCurrentHub); } else { - isDebugBuild() && + IS_DEBUG_BUILD && logger.error('Vue integration has tracing enabled, but Tracing integration is not configured'); } }, @@ -405,7 +407,7 @@ export class Vue implements Integration { metadata.propsData = vm.$options.propsData; } } catch (_oO) { - isDebugBuild() && logger.warn('Unable to extract metadata from Vue component.'); + IS_DEBUG_BUILD && logger.warn('Unable to extract metadata from Vue component.'); } } diff --git a/packages/nextjs/src/config/webpack.ts b/packages/nextjs/src/config/webpack.ts index 6ed4bdade36c..d98d7ec3503c 100644 --- a/packages/nextjs/src/config/webpack.ts +++ b/packages/nextjs/src/config/webpack.ts @@ -1,11 +1,12 @@ /* eslint-disable max-lines */ import { getSentryRelease } from '@sentry/node'; -import { dropUndefinedKeys, isDebugBuild, logger } from '@sentry/utils'; +import { dropUndefinedKeys, logger } from '@sentry/utils'; import { default as SentryWebpackPlugin } from '@sentry/webpack-plugin'; import * as fs from 'fs'; import * as os from 'os'; import * as path from 'path'; +import { IS_DEBUG_BUILD } from '../flags'; import { BuildContext, EntryPropertyObject, @@ -244,7 +245,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) { - isDebugBuild() && + IS_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 new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/nextjs/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/nextjs/src/index.server.ts b/packages/nextjs/src/index.server.ts index bc2996fcfd97..a57ee89443a5 100644 --- a/packages/nextjs/src/index.server.ts +++ b/packages/nextjs/src/index.server.ts @@ -3,10 +3,11 @@ import { RewriteFrames } from '@sentry/integrations'; import { configureScope, getCurrentHub, init as nodeInit, Integrations } from '@sentry/node'; import { hasTracingEnabled } from '@sentry/tracing'; import { Event } from '@sentry/types'; -import { escapeStringForRegex, isDebugBuild, logger } from '@sentry/utils'; +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'; @@ -45,10 +46,10 @@ export function init(options: NextjsOptions): void { logger.enable(); } - isDebugBuild() && logger.log('Initializing SDK...'); + IS_DEBUG_BUILD && logger.log('Initializing SDK...'); if (sdkAlreadyInitialized()) { - isDebugBuild() && logger.log('SDK already initialized'); + IS_DEBUG_BUILD && logger.log('SDK already initialized'); return; } @@ -93,7 +94,7 @@ export function init(options: NextjsOptions): void { domain.active = activeDomain; } - isDebugBuild() && logger.log('SDK successfully initialized'); + IS_DEBUG_BUILD && logger.log('SDK successfully initialized'); } function sdkAlreadyInitialized(): boolean { @@ -150,6 +151,6 @@ if (!isVercel && !isBuild) { const { instrumentServer } = require('./utils/instrumentServer.js'); instrumentServer(); } catch (err) { - isDebugBuild() && logger.warn(`Error: Unable to instrument server for tracing. Got ${err}.`); + IS_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 d5079209bdee..cba8e0ab9423 100644 --- a/packages/nextjs/src/utils/instrumentServer.ts +++ b/packages/nextjs/src/utils/instrumentServer.ts @@ -8,13 +8,15 @@ import { startTransaction, } from '@sentry/node'; import { extractTraceparentData, getActiveTransaction, hasTracingEnabled } from '@sentry/tracing'; -import { addExceptionMechanism, fill, isDebugBuild, isString, logger, stripUrlQueryAndFragment } from '@sentry/utils'; +import { addExceptionMechanism, fill, isString, logger, stripUrlQueryAndFragment } from '@sentry/utils'; import * as domain from 'domain'; import * as http from 'http'; 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 @@ -247,7 +249,7 @@ function makeWrappedReqHandler(origReqHandler: ReqHandler): WrappedReqHandler { let traceparentData; if (nextReq.headers && isString(nextReq.headers['sentry-trace'])) { traceparentData = extractTraceparentData(nextReq.headers['sentry-trace']); - isDebugBuild() && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); + IS_DEBUG_BUILD && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); } // pull off query string, if any diff --git a/packages/nextjs/src/utils/withSentry.ts b/packages/nextjs/src/utils/withSentry.ts index 7ef2e5ed8991..00e76ec40b69 100644 --- a/packages/nextjs/src/utils/withSentry.ts +++ b/packages/nextjs/src/utils/withSentry.ts @@ -1,17 +1,12 @@ import { captureException, flush, getCurrentHub, Handlers, startTransaction } from '@sentry/node'; import { extractTraceparentData, hasTracingEnabled } from '@sentry/tracing'; import { Transaction } from '@sentry/types'; -import { - addExceptionMechanism, - isDebugBuild, - isString, - logger, - objectify, - stripUrlQueryAndFragment, -} from '@sentry/utils'; +import { addExceptionMechanism, isString, logger, objectify, stripUrlQueryAndFragment } from '@sentry/utils'; 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 @@ -50,7 +45,7 @@ export const withSentry = (origHandler: NextApiHandler): WrappedNextApiHandler = let traceparentData; if (req.headers && isString(req.headers['sentry-trace'])) { traceparentData = extractTraceparentData(req.headers['sentry-trace']); - isDebugBuild() && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); + IS_DEBUG_BUILD && logger.log(`[Tracing] Continuing trace ${traceparentData?.traceId}.`); } const url = `${req.url}`; @@ -193,10 +188,10 @@ async function finishSentryProcessing(res: AugmentedNextApiResponse): Promise { public initSessionFlusher(): void { const { release, environment } = this._options; if (!release) { - isDebugBuild() && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); + IS_DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); } else { this._sessionFlusher = new SessionFlusher(this.getTransport(), { release, @@ -122,7 +123,7 @@ export class NodeClient extends BaseClient { */ protected _captureRequestSession(): void { if (!this._sessionFlusher) { - isDebugBuild() && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); + IS_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 new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/node/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 259bd64ffd06..451ef14e9223 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -4,7 +4,6 @@ import { captureException, getCurrentHub, startTransaction, withScope } from '@s import { Event, ExtractedNodeRequestData, Span, Transaction } from '@sentry/types'; import { extractTraceparentData, - isDebugBuild, isPlainObject, isString, logger, @@ -18,6 +17,7 @@ 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 { @@ -412,7 +412,7 @@ export function requestHandler( _end.call(this, chunk, encoding, cb); }) .then(null, e => { - isDebugBuild() && logger.error(e); + IS_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 d0c820d787f7..19a4e6ba1423 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -1,9 +1,10 @@ import { getCurrentHub } from '@sentry/core'; import { Integration, Span } from '@sentry/types'; -import { fill, isDebugBuild, logger, parseSemver } from '@sentry/utils'; +import { fill, logger, parseSemver } from '@sentry/utils'; import * as http from 'http'; import * as https from 'https'; +import { IS_DEBUG_BUILD } from '../flags'; import { cleanSpanDescription, extractUrl, @@ -118,7 +119,7 @@ function _createWrappedRequestMethodFactory( }); const sentryTraceHeader = span.toTraceparent(); - isDebugBuild() && + IS_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 4fd52cba3e3f..9c8d33913315 100644 --- a/packages/node/src/integrations/onuncaughtexception.ts +++ b/packages/node/src/integrations/onuncaughtexception.ts @@ -1,8 +1,9 @@ import { getCurrentHub, Scope } from '@sentry/core'; import { Integration, Severity } from '@sentry/types'; -import { isDebugBuild, logger } from '@sentry/utils'; +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; @@ -95,7 +96,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 - isDebugBuild() && + IS_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 cb1983ffb819..aa79eebcaee8 100644 --- a/packages/node/src/integrations/utils/errorhandling.ts +++ b/packages/node/src/integrations/utils/errorhandling.ts @@ -1,7 +1,8 @@ import { getCurrentHub } from '@sentry/core'; -import { forget, isDebugBuild, logger } from '@sentry/utils'; +import { forget, logger } from '@sentry/utils'; import { NodeClient } from '../../client'; +import { IS_DEBUG_BUILD } from '../../flags'; const DEFAULT_SHUTDOWN_TIMEOUT = 2000; @@ -15,7 +16,7 @@ export function logAndExitProcess(error: Error): void { const client = getCurrentHub().getClient(); if (client === undefined) { - isDebugBuild() && logger.warn('No NodeClient was defined, we are exiting the process now.'); + IS_DEBUG_BUILD && logger.warn('No NodeClient was defined, we are exiting the process now.'); global.process.exit(1); } @@ -26,7 +27,7 @@ export function logAndExitProcess(error: Error): void { forget( client.close(timeout).then((result: boolean) => { if (!result) { - isDebugBuild() && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); + IS_DEBUG_BUILD && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); } global.process.exit(1); }), diff --git a/packages/node/src/sdk.ts b/packages/node/src/sdk.ts index 201b4b073f86..7dd660a44048 100644 --- a/packages/node/src/sdk.ts +++ b/packages/node/src/sdk.ts @@ -1,10 +1,11 @@ import { getCurrentHub, initAndBind, Integrations as CoreIntegrations } from '@sentry/core'; import { getMainCarrier, setHubOnCarrier } from '@sentry/hub'; import { SessionStatus } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +import { getGlobalObject, logger } from '@sentry/utils'; 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 { NodeOptions } from './types'; @@ -153,7 +154,7 @@ export async function flush(timeout?: number): Promise { if (client) { return client.flush(timeout); } - isDebugBuild() && logger.warn('Cannot flush events. No client defined.'); + IS_DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.'); return Promise.resolve(false); } @@ -170,7 +171,7 @@ export async function close(timeout?: number): Promise { if (client) { return client.close(timeout); } - isDebugBuild() && logger.warn('Cannot flush events and disable SDK. No client defined.'); + IS_DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.'); return Promise.resolve(false); } diff --git a/packages/node/src/transports/base/index.ts b/packages/node/src/transports/base/index.ts index 5cc15ee8fe09..0cbe39c42b2b 100644 --- a/packages/node/src/transports/base/index.ts +++ b/packages/node/src/transports/base/index.ts @@ -12,7 +12,6 @@ import { } from '@sentry/types'; import { eventStatusFromHttpCode, - isDebugBuild, logger, makePromiseBuffer, parseRetryAfterHeader, @@ -24,6 +23,7 @@ import * as http from 'http'; import * as https from 'https'; import { URL } from 'url'; +import { IS_DEBUG_BUILD } from '../../flags'; import { SDK_NAME } from '../../version'; import { HTTPModule } from './http-module'; @@ -237,7 +237,7 @@ export abstract class BaseTransport implements Transport { const limited = this._handleRateLimit(headers); if (limited) - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn( `Too many ${sentryRequest.type} requests, backing off until: ${this._disabledUntil( sentryRequest.type, diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 6941588f794b..fb3987d316cb 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -1,8 +1,10 @@ import { captureException, ReportDialogOptions, Scope, showReportDialog, withScope } from '@sentry/browser'; -import { isDebugBuild, logger } from '@sentry/utils'; +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; @@ -141,7 +143,7 @@ class ErrorBoundary extends React.Component( hub.popScope(); await flush(options.flushTimeout).catch(e => { if (options.ignoreSentryErrors && e instanceof SentryError) { - isDebugBuild() && logger.error(e); + IS_DEBUG_BUILD && logger.error(e); return; } throw e; diff --git a/packages/serverless/src/flags.ts b/packages/serverless/src/flags.ts new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/serverless/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/serverless/src/gcpfunction/cloud_events.ts b/packages/serverless/src/gcpfunction/cloud_events.ts index 362cb5a78563..f4c79c410d9c 100644 --- a/packages/serverless/src/gcpfunction/cloud_events.ts +++ b/packages/serverless/src/gcpfunction/cloud_events.ts @@ -1,6 +1,7 @@ import { captureException, flush, getCurrentHub, startTransaction } from '@sentry/node'; -import { isDebugBuild, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from '../flags'; import { domainify, getActiveDomain, proxyFunction } from '../utils'; import { CloudEventFunction, @@ -64,7 +65,7 @@ function _wrapCloudEventFunction( callback(...args); }) .then(null, e => { - isDebugBuild() && logger.error(e); + IS_DEBUG_BUILD && logger.error(e); }); }); diff --git a/packages/serverless/src/gcpfunction/events.ts b/packages/serverless/src/gcpfunction/events.ts index f89fcbbd267f..e47efc1571eb 100644 --- a/packages/serverless/src/gcpfunction/events.ts +++ b/packages/serverless/src/gcpfunction/events.ts @@ -1,6 +1,7 @@ import { captureException, flush, getCurrentHub, startTransaction } from '@sentry/node'; -import { isDebugBuild, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from '../flags'; import { domainify, getActiveDomain, proxyFunction } from '../utils'; import { configureScopeWithContext, EventFunction, EventFunctionWithCallback, WrapperOptions } from './general'; @@ -59,7 +60,7 @@ function _wrapEventFunction( callback(...args); }) .then(null, e => { - isDebugBuild() && logger.error(e); + IS_DEBUG_BUILD && logger.error(e); }); }); diff --git a/packages/serverless/src/gcpfunction/http.ts b/packages/serverless/src/gcpfunction/http.ts index a7136b8e20a6..607656fb3dbd 100644 --- a/packages/serverless/src/gcpfunction/http.ts +++ b/packages/serverless/src/gcpfunction/http.ts @@ -1,7 +1,8 @@ import { captureException, flush, getCurrentHub, Handlers, startTransaction } from '@sentry/node'; import { extractTraceparentData } from '@sentry/tracing'; -import { isDebugBuild, isString, logger, stripUrlQueryAndFragment } from '@sentry/utils'; +import { isString, logger, stripUrlQueryAndFragment } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from '../flags'; import { domainify, getActiveDomain, proxyFunction } from './../utils'; import { HttpFunction, WrapperOptions } from './general'; @@ -94,7 +95,7 @@ function _wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial { - isDebugBuild() && logger.error(e); + IS_DEBUG_BUILD && logger.error(e); }); }; diff --git a/packages/tracing/src/browser/backgroundtab.ts b/packages/tracing/src/browser/backgroundtab.ts index 9295d83a2998..2448247188bd 100644 --- a/packages/tracing/src/browser/backgroundtab.ts +++ b/packages/tracing/src/browser/backgroundtab.ts @@ -1,6 +1,7 @@ -import { getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +import { getGlobalObject, logger } from '@sentry/utils'; import { FINISH_REASON_TAG, IDLE_TRANSACTION_FINISH_REASONS } from '../constants'; +import { IS_DEBUG_BUILD } from '../flags'; import { IdleTransaction } from '../idletransaction'; import { SpanStatusType } from '../span'; import { getActiveTransaction } from '../utils'; @@ -18,7 +19,7 @@ export function registerBackgroundTabDetection(): void { if (global.document.hidden && activeTransaction) { const statusType: SpanStatusType = 'cancelled'; - isDebugBuild() && + IS_DEBUG_BUILD && logger.log( `[Tracing] Transaction: ${statusType} -> since tab moved to the background, op: ${activeTransaction.op}`, ); @@ -33,6 +34,6 @@ export function registerBackgroundTabDetection(): void { } }); } else { - isDebugBuild() && logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); + IS_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 0b5b8be40b0e..e9d02db6d7d7 100644 --- a/packages/tracing/src/browser/browsertracing.ts +++ b/packages/tracing/src/browser/browsertracing.ts @@ -1,7 +1,8 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration, Transaction, TransactionContext } from '@sentry/types'; -import { getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +import { getGlobalObject, logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from '../flags'; import { startIdleTransaction } from '../hubextensions'; import { DEFAULT_IDLE_TIMEOUT, IdleTransaction } from '../idletransaction'; import { extractTraceparentData, secToMs } from '../utils'; @@ -139,7 +140,7 @@ export class BrowserTracing implements Integration { if (_options.tracingOrigins && Array.isArray(_options.tracingOrigins) && _options.tracingOrigins.length !== 0) { tracingOrigins = _options.tracingOrigins; } else { - isDebugBuild() && (this._emitOptionsWarning = true); + IS_DEBUG_BUILD && (this._emitOptionsWarning = true); } } @@ -160,11 +161,11 @@ export class BrowserTracing implements Integration { this._getCurrentHub = getCurrentHub; if (this._emitOptionsWarning) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn( '[Tracing] You need to define `tracingOrigins` in the options. Set an array of urls or patterns to trace.', ); - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn( `[Tracing] We added a reasonable default for you: ${defaultRequestInstrumentationOptions.tracingOrigins}`, ); @@ -198,7 +199,7 @@ export class BrowserTracing implements Integration { /** Create routing idle transaction. */ private _createRouteTransaction(context: TransactionContext): Transaction | undefined { if (!this._getCurrentHub) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.`); return undefined; } @@ -220,10 +221,10 @@ export class BrowserTracing implements Integration { const finalContext = modifiedContext === undefined ? { ...expandedContext, sampled: false } : modifiedContext; if (finalContext.sampled === false) { - isDebugBuild() && logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); + IS_DEBUG_BUILD && logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); } - isDebugBuild() && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); + IS_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.ts b/packages/tracing/src/browser/metrics.ts index 6485b98ae0f9..8386b608f247 100644 --- a/packages/tracing/src/browser/metrics.ts +++ b/packages/tracing/src/browser/metrics.ts @@ -1,15 +1,9 @@ /* eslint-disable max-lines */ /* eslint-disable @typescript-eslint/no-explicit-any */ import { Measurements, SpanContext } from '@sentry/types'; -import { - browserPerformanceTimeOrigin, - getGlobalObject, - htmlTreeAsString, - isDebugBuild, - isNodeEnv, - logger, -} from '@sentry/utils'; +import { browserPerformanceTimeOrigin, getGlobalObject, htmlTreeAsString, isNodeEnv, logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from '../flags'; import { Span } from '../span'; import { Transaction } from '../transaction'; import { msToSec } from '../utils'; @@ -48,7 +42,7 @@ export class MetricsInstrumentation { return; } - isDebugBuild() && logger.log('[Tracing] Adding & adjusting spans using Performance API'); + IS_DEBUG_BUILD && logger.log('[Tracing] Adding & adjusting spans using Performance API'); const timeOrigin = msToSec(browserPerformanceTimeOrigin); @@ -84,13 +78,13 @@ export class MetricsInstrumentation { const shouldRecord = entry.startTime < firstHidden.firstHiddenTime; if (entry.name === 'first-paint' && shouldRecord) { - isDebugBuild() && logger.log('[Measurements] Adding FP'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding FP'); this._measurements['fp'] = { value: entry.startTime }; this._measurements['mark.fp'] = { value: startTimestamp }; } if (entry.name === 'first-contentful-paint' && shouldRecord) { - isDebugBuild() && logger.log('[Measurements] Adding FCP'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding FCP'); this._measurements['fcp'] = { value: entry.startTime }; this._measurements['mark.fcp'] = { value: startTimestamp }; } @@ -120,7 +114,7 @@ export class MetricsInstrumentation { // 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') { - isDebugBuild() && logger.log('[Measurements] Adding TTFB'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding TTFB'); this._measurements['ttfb'] = { value: (responseStartTimestamp - transaction.startTimestamp) * 1000 }; if (typeof requestStartTimestamp === 'number' && requestStartTimestamp <= responseStartTimestamp) { @@ -145,7 +139,7 @@ export class MetricsInstrumentation { const normalizedValue = Math.abs((measurementTimestamp - transaction.startTimestamp) * 1000); const delta = normalizedValue - oldValue; - isDebugBuild() && + IS_DEBUG_BUILD && logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); this._measurements[name].value = normalizedValue; @@ -223,7 +217,7 @@ export class MetricsInstrumentation { return; } - isDebugBuild() && logger.log('[Measurements] Adding CLS'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding CLS'); this._measurements['cls'] = { value: metric.value }; this._clsEntry = entry as LayoutShift; }); @@ -239,7 +233,7 @@ export class MetricsInstrumentation { const timeOrigin = msToSec(browserPerformanceTimeOrigin as number); const startTime = msToSec(entry.startTime); - isDebugBuild() && logger.log('[Measurements] Adding LCP'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding LCP'); this._measurements['lcp'] = { value: metric.value }; this._measurements['mark.lcp'] = { value: timeOrigin + startTime }; this._lcpEntry = entry as LargestContentfulPaint; @@ -256,7 +250,7 @@ export class MetricsInstrumentation { const timeOrigin = msToSec(browserPerformanceTimeOrigin as number); const startTime = msToSec(entry.startTime); - isDebugBuild() && logger.log('[Measurements] Adding FID'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding FID'); this._measurements['fid'] = { value: metric.value }; this._measurements['mark.fid'] = { value: timeOrigin + startTime }; }); @@ -409,7 +403,7 @@ function tagMetricInfo( clsEntry: MetricsInstrumentation['_clsEntry'], ): void { if (lcpEntry) { - isDebugBuild() && logger.log('[Measurements] Adding LCP Data'); + IS_DEBUG_BUILD && logger.log('[Measurements] Adding LCP Data'); // Capture Properties of the LCP element that contributes to the LCP. @@ -431,7 +425,7 @@ function tagMetricInfo( // See: https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift if (clsEntry && clsEntry.sources) { - isDebugBuild() && logger.log('[Measurements] Adding CLS Data'); + IS_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 ff1324f5709f..fe1442b1c396 100644 --- a/packages/tracing/src/browser/router.ts +++ b/packages/tracing/src/browser/router.ts @@ -1,5 +1,7 @@ import { Transaction, TransactionContext } from '@sentry/types'; -import { addInstrumentationHandler, getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +import { addInstrumentationHandler, getGlobalObject, logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from '../flags'; const global = getGlobalObject(); @@ -12,7 +14,7 @@ export function instrumentRoutingWithDefaults( startTransactionOnLocationChange: boolean = true, ): void { if (!global || !global.location) { - isDebugBuild() && logger.warn('Could not initialize routing instrumentation due to invalid location'); + IS_DEBUG_BUILD && logger.warn('Could not initialize routing instrumentation due to invalid location'); return; } @@ -42,7 +44,7 @@ export function instrumentRoutingWithDefaults( if (from !== to) { startingUrl = undefined; if (activeTransaction) { - isDebugBuild() && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); + IS_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 b64d0ffb85d9..ed8e6e9cbec9 100644 --- a/packages/tracing/src/errors.ts +++ b/packages/tracing/src/errors.ts @@ -1,5 +1,6 @@ -import { addInstrumentationHandler, isDebugBuild, logger } from '@sentry/utils'; +import { addInstrumentationHandler, logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from './flags'; import { SpanStatusType } from './span'; import { getActiveTransaction } from './utils'; @@ -18,7 +19,7 @@ function errorCallback(): void { const activeTransaction = getActiveTransaction(); if (activeTransaction) { const status: SpanStatusType = 'internal_error'; - isDebugBuild() && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); + IS_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 new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/tracing/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/tracing/src/hubextensions.ts b/packages/tracing/src/hubextensions.ts index 7d2ec809a240..bd38b270cc22 100644 --- a/packages/tracing/src/hubextensions.ts +++ b/packages/tracing/src/hubextensions.ts @@ -7,9 +7,10 @@ import { SamplingContext, TransactionContext, } from '@sentry/types'; -import { dynamicRequire, isDebugBuild, isNaN, isNodeEnv, loadModule, logger } from '@sentry/utils'; +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'; @@ -86,14 +87,14 @@ function sample(transaction: T, options: Options, samplin // 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)) { - isDebugBuild() && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); + IS_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) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.log( `[Tracing] Discarding transaction because ${ typeof options.tracesSampler === 'function' @@ -111,7 +112,7 @@ function sample(transaction: T, options: Options, samplin // if we're not going to keep it, we're done if (!transaction.sampled) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.log( `[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${Number( sampleRate, @@ -120,7 +121,7 @@ function sample(transaction: T, options: Options, samplin return transaction; } - isDebugBuild() && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); + IS_DEBUG_BUILD && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); return transaction; } @@ -131,7 +132,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')) { - isDebugBuild() && + IS_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, @@ -142,7 +143,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) { - isDebugBuild() && + IS_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 5c3ea4fac1d6..0d292eebba65 100644 --- a/packages/tracing/src/idletransaction.ts +++ b/packages/tracing/src/idletransaction.ts @@ -1,8 +1,9 @@ import { Hub } from '@sentry/hub'; import { TransactionContext } from '@sentry/types'; -import { isDebugBuild, logger, timestampWithMs } from '@sentry/utils'; +import { logger, timestampWithMs } from '@sentry/utils'; import { FINISH_REASON_TAG, IDLE_TRANSACTION_FINISH_REASONS } from './constants'; +import { IS_DEBUG_BUILD } from './flags'; import { Span, SpanRecorder } from './span'; import { Transaction } from './transaction'; @@ -92,7 +93,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. - isDebugBuild() && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); + IS_DEBUG_BUILD && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); _idleHub.configureScope(scope => scope.setSpan(this)); } @@ -109,7 +110,7 @@ export class IdleTransaction extends Transaction { this.activities = {}; if (this.spanRecorder) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.log('[Tracing] finishing IdleTransaction', new Date(endTimestamp * 1000).toISOString(), this.op); for (const callback of this._beforeFinishCallbacks) { @@ -126,13 +127,13 @@ export class IdleTransaction extends Transaction { if (!span.endTimestamp) { span.endTimestamp = endTimestamp; span.setStatus('cancelled'); - isDebugBuild() && + IS_DEBUG_BUILD && logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2)); } const keepSpan = span.startTimestamp < endTimestamp; if (!keepSpan) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.log( '[Tracing] discarding Span since it happened after Transaction was finished', JSON.stringify(span, undefined, 2), @@ -141,9 +142,9 @@ export class IdleTransaction extends Transaction { return keepSpan; }); - isDebugBuild() && logger.log('[Tracing] flushing IdleTransaction'); + IS_DEBUG_BUILD && logger.log('[Tracing] flushing IdleTransaction'); } else { - isDebugBuild() && logger.log('[Tracing] No active IdleTransaction'); + IS_DEBUG_BUILD && logger.log('[Tracing] No active IdleTransaction'); } // if `this._onScope` is `true`, the transaction put itself on the scope when it started @@ -186,7 +187,7 @@ export class IdleTransaction extends Transaction { this.spanRecorder = new IdleTransactionSpanRecorder(pushActivity, popActivity, this.spanId, maxlen); // Start heartbeat so that transactions do not run forever. - isDebugBuild() && logger.log('Starting heartbeat'); + IS_DEBUG_BUILD && logger.log('Starting heartbeat'); this._pingHeartbeat(); } this.spanRecorder.add(this); @@ -201,9 +202,9 @@ export class IdleTransaction extends Transaction { clearTimeout(this._initTimeout); this._initTimeout = undefined; } - isDebugBuild() && logger.log(`[Tracing] pushActivity: ${spanId}`); + IS_DEBUG_BUILD && logger.log(`[Tracing] pushActivity: ${spanId}`); this.activities[spanId] = true; - isDebugBuild() && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + IS_DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } /** @@ -212,10 +213,10 @@ export class IdleTransaction extends Transaction { */ private _popActivity(spanId: string): void { if (this.activities[spanId]) { - isDebugBuild() && logger.log(`[Tracing] popActivity ${spanId}`); + IS_DEBUG_BUILD && logger.log(`[Tracing] popActivity ${spanId}`); // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete this.activities[spanId]; - isDebugBuild() && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + IS_DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } if (Object.keys(this.activities).length === 0) { @@ -254,7 +255,7 @@ export class IdleTransaction extends Transaction { this._prevHeartbeatString = heartbeatString; if (this._heartbeatCounter >= 3) { - isDebugBuild() && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); + IS_DEBUG_BUILD && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); this.setStatus('deadline_exceeded'); this.setTag(FINISH_REASON_TAG, IDLE_TRANSACTION_FINISH_REASONS[0]); this.finish(); @@ -267,7 +268,7 @@ export class IdleTransaction extends Transaction { * Pings the heartbeat */ private _pingHeartbeat(): void { - isDebugBuild() && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); + IS_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 35100bb615ab..33a492cc1df6 100644 --- a/packages/tracing/src/integrations/node/express.ts +++ b/packages/tracing/src/integrations/node/express.ts @@ -1,5 +1,7 @@ import { Integration, Transaction } from '@sentry/types'; -import { isDebugBuild, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from '../../flags'; type Method = | 'all' @@ -79,7 +81,7 @@ export class Express implements Integration { */ public setupOnce(): void { if (!this._router) { - isDebugBuild() && logger.error('ExpressIntegration is missing an Express instance'); + IS_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 5a134a877bb7..a3bebce5d7bb 100644 --- a/packages/tracing/src/integrations/node/mongo.ts +++ b/packages/tracing/src/integrations/node/mongo.ts @@ -1,6 +1,8 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration, SpanContext } from '@sentry/types'; -import { fill, isDebugBuild, isThenable, loadModule, logger } from '@sentry/utils'; +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" | ... ) @@ -121,7 +123,7 @@ export class Mongo implements Integration { const pkg = loadModule<{ Collection: MongoCollection }>(moduleName); if (!pkg) { - isDebugBuild() && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); + IS_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 54173fcc7a7b..596b9df80b03 100644 --- a/packages/tracing/src/integrations/node/mysql.ts +++ b/packages/tracing/src/integrations/node/mysql.ts @@ -1,6 +1,8 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration } from '@sentry/types'; -import { fill, isDebugBuild, loadModule, logger } from '@sentry/utils'; +import { fill, loadModule, logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from '../../flags'; interface MysqlConnection { createQuery: () => void; @@ -25,7 +27,7 @@ export class Mysql implements Integration { const pkg = loadModule('mysql/lib/Connection.js'); if (!pkg) { - isDebugBuild() && logger.error('Mysql Integration was unable to require `mysql` package.'); + IS_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 fe751f80ffcd..014fd2266a11 100644 --- a/packages/tracing/src/integrations/node/postgres.ts +++ b/packages/tracing/src/integrations/node/postgres.ts @@ -1,6 +1,8 @@ import { Hub } from '@sentry/hub'; import { EventProcessor, Integration } from '@sentry/types'; -import { fill, isDebugBuild, isThenable, loadModule, logger } from '@sentry/utils'; +import { fill, isThenable, loadModule, logger } from '@sentry/utils'; + +import { IS_DEBUG_BUILD } from '../../flags'; interface PgClient { prototype: { @@ -37,12 +39,12 @@ export class Postgres implements Integration { const pkg = loadModule<{ Client: PgClient; native: { Client: PgClient } }>('pg'); if (!pkg) { - isDebugBuild() && logger.error('Postgres Integration was unable to require `pg` package.'); + IS_DEBUG_BUILD && logger.error('Postgres Integration was unable to require `pg` package.'); return; } if (this._usePgNative && !pkg.native?.Client) { - isDebugBuild() && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); + IS_DEBUG_BUILD && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); return; } diff --git a/packages/tracing/src/transaction.ts b/packages/tracing/src/transaction.ts index e5d469d8d329..6cbda0e04223 100644 --- a/packages/tracing/src/transaction.ts +++ b/packages/tracing/src/transaction.ts @@ -6,8 +6,9 @@ import { TransactionContext, TransactionMetadata, } from '@sentry/types'; -import { dropUndefinedKeys, isDebugBuild, isInstanceOf, logger } from '@sentry/utils'; +import { dropUndefinedKeys, isInstanceOf, logger } from '@sentry/utils'; +import { IS_DEBUG_BUILD } from './flags'; import { Span as SpanClass, SpanRecorder } from './span'; /** JSDoc */ @@ -92,7 +93,7 @@ export class Transaction extends SpanClass implements TransactionInterface { } if (!this.name) { - isDebugBuild() && logger.warn('Transaction has no name, falling back to ``.'); + IS_DEBUG_BUILD && logger.warn('Transaction has no name, falling back to ``.'); this.name = ''; } @@ -101,7 +102,7 @@ export class Transaction extends SpanClass implements TransactionInterface { if (this.sampled !== true) { // At this point if `sampled !== true` we want to discard the transaction. - isDebugBuild() && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); + IS_DEBUG_BUILD && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); const client = this._hub.getClient(); const transport = client && client.getTransport && client.getTransport(); @@ -138,7 +139,7 @@ export class Transaction extends SpanClass implements TransactionInterface { const hasMeasurements = Object.keys(this._measurements).length > 0; if (hasMeasurements) { - isDebugBuild() && + IS_DEBUG_BUILD && logger.log( '[Measurements] Adding measurements to transaction', JSON.stringify(this._measurements, undefined, 2), @@ -146,7 +147,7 @@ export class Transaction extends SpanClass implements TransactionInterface { transaction.measurements = this._measurements; } - isDebugBuild() && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); + IS_DEBUG_BUILD && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); return this._hub.captureEvent(transaction); } diff --git a/packages/utils/src/dsn.ts b/packages/utils/src/dsn.ts index 95db16992def..0b58a7974821 100644 --- a/packages/utils/src/dsn.ts +++ b/packages/utils/src/dsn.ts @@ -1,7 +1,7 @@ import { DsnComponents, DsnLike, DsnProtocol } from '@sentry/types'; -import { isDebugBuild } from './env'; 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 +73,7 @@ function dsnFromComponents(components: DsnComponents): DsnComponents { } function validateDsn(dsn: DsnComponents): boolean | void { - if (!isDebugBuild()) { + if (!IS_DEBUG_BUILD) { return; } diff --git a/packages/utils/src/env.ts b/packages/utils/src/env.ts index a2b6eb56d7f9..101be14e6e2c 100644 --- a/packages/utils/src/env.ts +++ b/packages/utils/src/env.ts @@ -1,24 +1,20 @@ -/** +/* * This module exists for optimizations in the build process through rollup and terser. We define some global * constants, which can be overridden during build. By guarding certain pieces of code with functions that return these * constants, we can control whether or not they appear in the final bundle. (Any code guarded by a false condition will * never run, and will hence be dropped during treeshaking.) The two primary uses for this are stripping out calls to * `logger` and preventing node-related code from appearing in browser bundles. + * + * Attention: + * This file should not be used to define constants/flags that are intended to be used for tree-shaking conducted by + * users. These fags should live in their respective packages, as we identified user tooling (specifically webpack) + * having issues tree-shaking these constants across package boundaries. + * An example for this is the __SENTRY_DEBUG__ constant. It is declared in each package individually because we want + * users to be able to shake away expressions that it guards. */ declare const __SENTRY_BROWSER_BUNDLE__: boolean | undefined; -const __SENTRY_DEBUG__ = true; - -/** - * Figures out if we're building with debug functionality. - * - * @returns true if this is a debug build - */ -export function isDebugBuild(): boolean { - return __SENTRY_DEBUG__; -} - /** * Figures out if we're building a browser bundle. * diff --git a/packages/utils/src/flags.ts b/packages/utils/src/flags.ts new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/utils/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/utils/src/instrument.ts b/packages/utils/src/instrument.ts index 2276a4877999..30fcef290c19 100644 --- a/packages/utils/src/instrument.ts +++ b/packages/utils/src/instrument.ts @@ -3,7 +3,7 @@ /* eslint-disable @typescript-eslint/ban-types */ import { WrappedFunction } from '@sentry/types'; -import { isDebugBuild } from './env'; +import { IS_DEBUG_BUILD } from './flags'; import { getGlobalObject } from './global'; import { isInstanceOf, isString } from './is'; import { CONSOLE_LEVELS, logger } from './logger'; @@ -69,7 +69,7 @@ function instrument(type: InstrumentHandlerType): void { instrumentUnhandledRejection(); break; default: - isDebugBuild() && logger.warn('unknown instrumentation type:', type); + IS_DEBUG_BUILD && logger.warn('unknown instrumentation type:', type); return; } } @@ -95,7 +95,7 @@ function triggerHandlers(type: InstrumentHandlerType, data: any): void { try { handler(data); } catch (e) { - isDebugBuild() && + IS_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 1913916686b5..efb258e5fc38 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import { WrappedFunction } from '@sentry/types'; -import { isDebugBuild } from './env'; +import { IS_DEBUG_BUILD } from './flags'; import { getGlobalObject } from './global'; // TODO: Implement different loggers for different environments @@ -109,7 +109,7 @@ class Logger { const sentryGlobal = global.__SENTRY__ || {}; const logger = (sentryGlobal.logger as Logger) || new Logger(); -if (isDebugBuild()) { +if (IS_DEBUG_BUILD) { // Ensure we only have a single logger instance, even if multiple versions of @sentry/utils are being used sentryGlobal.logger = logger; global.__SENTRY__ = sentryGlobal; diff --git a/packages/utils/src/supports.ts b/packages/utils/src/supports.ts index 59e6bd6804c8..e9109da84ec2 100644 --- a/packages/utils/src/supports.ts +++ b/packages/utils/src/supports.ts @@ -1,4 +1,4 @@ -import { isDebugBuild } from './env'; +import { IS_DEBUG_BUILD } from './flags'; import { getGlobalObject } from './global'; import { logger } from './logger'; @@ -113,7 +113,7 @@ export function supportsNativeFetch(): boolean { } doc.head.removeChild(sandbox); } catch (err) { - isDebugBuild() && + IS_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 44d6e0678210..d5d5d1c11c54 100644 --- a/packages/utils/test/dsn.test.ts +++ b/packages/utils/test/dsn.test.ts @@ -1,7 +1,6 @@ -import { isDebugBuild } from '@sentry/utils'; - 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; @@ -43,7 +42,7 @@ describe('Dsn', () => { expect(dsn.projectId).toBe('123'); }); - testIf(isDebugBuild())('throws for missing components', () => { + testIf(IS_DEBUG_BUILD)('throws for missing components', () => { expect(() => makeDsn({ host: '', @@ -78,7 +77,7 @@ describe('Dsn', () => { ).toThrow(SentryError); }); - testIf(isDebugBuild())('throws for invalid components', () => { + testIf(IS_DEBUG_BUILD)('throws for invalid components', () => { expect(() => makeDsn({ host: 'sentry.io', @@ -144,18 +143,18 @@ describe('Dsn', () => { expect(dsn.projectId).toBe('321'); }); - testIf(isDebugBuild())('throws when provided invalid Dsn', () => { + testIf(IS_DEBUG_BUILD)('throws when provided invalid Dsn', () => { expect(() => makeDsn('some@random.dsn')).toThrow(SentryError); }); - testIf(isDebugBuild())('throws without mandatory fields', () => { + testIf(IS_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(isDebugBuild())('throws for invalid fields', () => { + testIf(IS_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 new file mode 100644 index 000000000000..9d63f65c1bdb --- /dev/null +++ b/packages/vue/src/flags.ts @@ -0,0 +1,9 @@ +/* + * This file defines flags and constants that can be modified during + * compile time in order to facilitate tree shaking for users + */ + +declare const __SENTRY_DEBUG__: boolean; + +/** Flag that is true for debug builds, false otherwise. */ +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; diff --git a/packages/vue/src/sdk.ts b/packages/vue/src/sdk.ts index 0cccfa64fd09..0cd7701ad3db 100644 --- a/packages/vue/src/sdk.ts +++ b/packages/vue/src/sdk.ts @@ -1,8 +1,9 @@ import { init as browserInit, SDK_VERSION } from '@sentry/browser'; -import { getGlobalObject, isDebugBuild, logger } from '@sentry/utils'; +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'; @@ -41,7 +42,7 @@ export function init( browserInit(options); if (!options.Vue && !options.app) { - isDebugBuild() && + IS_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 018d3859378a..304d379a4983 100644 --- a/packages/vue/src/tracing.ts +++ b/packages/vue/src/tracing.ts @@ -1,9 +1,10 @@ import { getCurrentHub } from '@sentry/browser'; import { Span, Transaction } from '@sentry/types'; -import { isDebugBuild, logger, timestampInSeconds } from '@sentry/utils'; +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'; @@ -60,7 +61,7 @@ export const createTracingMixins = (options: TracingOptions): Mixins => { // eg. mount => ['beforeMount', 'mounted'] const internalHooks = HOOKS[operation]; if (!internalHooks) { - isDebugBuild() && logger.warn(`Unknown hook: ${operation}`); + IS_DEBUG_BUILD && logger.warn(`Unknown hook: ${operation}`); continue; } diff --git a/rollup.config.js b/rollup.config.js index 1246365c076b..041f269f1095 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -50,9 +50,8 @@ function makeLicensePlugin(title) { function makeIsDebugBuildPlugin(includeDebugging) { return replace({ - // don't turn `const __SENTRY_DEBUG__ = false` into `const false = false` - preventAssignment: true, - // everywhere else, replace it with the value of `includeDebugging` + // __SENTRY_DEBUG__ should be save to replace in any case, so no checks for assignments necessary + preventAssignment: false, values: { __SENTRY_DEBUG__: includeDebugging, }, From ec46e964f0f4b487d19acda13f9b8a5ba7780c85 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 Apr 2022 11:21:55 +0000 Subject: [PATCH 2/4] Add documentation in CONTRIBUTING.md --- CONTRIBUTING.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index eb9270c48798..07fe9ca2b30c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -60,6 +60,19 @@ If you run into trouble writing tests and need to debug one of them, you can do Pro tip: If any of your breakpoints are in code run by multiple tests, and you run the whole test file, you'll land on those breakpoints over and over again, in the middle of tests you don't care about. To avoid this, replace the test's initial `it` or `test` with `it.only` or `test.only`. That way, when you hit a breakpoint, you'll know you got there are part of the buggy test. +## Debug Build Flags + +Throughout the codebase, you will find debug flags like `IS_DEBUG_BUILD` guarding various code sections. +These flags serve 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. + +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. + ## Linting Similar to building and testing, linting can be done in the project root or in individual packages by calling `yarn lint`. From 529bab7d5d1a4edc0dad42b5c89650f8a964da1b Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 4 Apr 2022 13:53:32 +0000 Subject: [PATCH 3/4] Switch default of IS_DEBUG_BUILD to evaluate to true --- packages/angular/src/flags.ts | 2 +- packages/browser/src/flags.ts | 2 +- packages/core/src/flags.ts | 2 +- packages/hub/src/flags.ts | 2 +- packages/integrations/src/flags.ts | 2 +- packages/nextjs/src/flags.ts | 2 +- packages/node/src/flags.ts | 2 +- packages/react/src/flags.ts | 2 +- packages/serverless/src/flags.ts | 2 +- packages/tracing/src/flags.ts | 2 +- packages/utils/src/flags.ts | 2 +- packages/vue/src/flags.ts | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/angular/src/flags.ts b/packages/angular/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/angular/src/flags.ts +++ b/packages/angular/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/browser/src/flags.ts b/packages/browser/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/browser/src/flags.ts +++ b/packages/browser/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/core/src/flags.ts b/packages/core/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/core/src/flags.ts +++ b/packages/core/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/hub/src/flags.ts b/packages/hub/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/hub/src/flags.ts +++ b/packages/hub/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/integrations/src/flags.ts b/packages/integrations/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/integrations/src/flags.ts +++ b/packages/integrations/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/nextjs/src/flags.ts b/packages/nextjs/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/nextjs/src/flags.ts +++ b/packages/nextjs/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/node/src/flags.ts b/packages/node/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/node/src/flags.ts +++ b/packages/node/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/react/src/flags.ts b/packages/react/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/react/src/flags.ts +++ b/packages/react/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/serverless/src/flags.ts b/packages/serverless/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/serverless/src/flags.ts +++ b/packages/serverless/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/tracing/src/flags.ts b/packages/tracing/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/tracing/src/flags.ts +++ b/packages/tracing/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/utils/src/flags.ts b/packages/utils/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/utils/src/flags.ts +++ b/packages/utils/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; diff --git a/packages/vue/src/flags.ts b/packages/vue/src/flags.ts index 9d63f65c1bdb..28581cc7815d 100644 --- a/packages/vue/src/flags.ts +++ b/packages/vue/src/flags.ts @@ -6,4 +6,4 @@ declare const __SENTRY_DEBUG__: boolean; /** Flag that is true for debug builds, false otherwise. */ -export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ !== 'undefined' && __SENTRY_DEBUG__; +export const IS_DEBUG_BUILD = typeof __SENTRY_DEBUG__ === 'undefined' ? true : __SENTRY_DEBUG__; From 0e1cbc3ccc045cb3b2c4b405148d1ffd3b7214ba Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Tue, 5 Apr 2022 07:02:09 +0000 Subject: [PATCH 4/4] Explain flag files in flag files --- packages/angular/src/flags.ts | 13 +++++++++++-- packages/browser/src/flags.ts | 13 +++++++++++-- packages/core/src/flags.ts | 13 +++++++++++-- packages/hub/src/flags.ts | 13 +++++++++++-- packages/integrations/src/flags.ts | 13 +++++++++++-- packages/nextjs/src/flags.ts | 13 +++++++++++-- packages/node/src/flags.ts | 13 +++++++++++-- packages/react/src/flags.ts | 13 +++++++++++-- packages/serverless/src/flags.ts | 13 +++++++++++-- packages/tracing/src/flags.ts | 13 +++++++++++-- packages/utils/src/flags.ts | 13 +++++++++++-- packages/vue/src/flags.ts | 13 +++++++++++-- 12 files changed, 132 insertions(+), 24 deletions(-) diff --git a/packages/angular/src/flags.ts b/packages/angular/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/angular/src/flags.ts +++ b/packages/angular/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/browser/src/flags.ts b/packages/browser/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/browser/src/flags.ts +++ b/packages/browser/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/core/src/flags.ts b/packages/core/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/core/src/flags.ts +++ b/packages/core/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/hub/src/flags.ts b/packages/hub/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/hub/src/flags.ts +++ b/packages/hub/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/integrations/src/flags.ts b/packages/integrations/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/integrations/src/flags.ts +++ b/packages/integrations/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/nextjs/src/flags.ts b/packages/nextjs/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/nextjs/src/flags.ts +++ b/packages/nextjs/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/node/src/flags.ts b/packages/node/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/node/src/flags.ts +++ b/packages/node/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/react/src/flags.ts b/packages/react/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/react/src/flags.ts +++ b/packages/react/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/serverless/src/flags.ts b/packages/serverless/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/serverless/src/flags.ts +++ b/packages/serverless/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/tracing/src/flags.ts b/packages/tracing/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/tracing/src/flags.ts +++ b/packages/tracing/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/utils/src/flags.ts b/packages/utils/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/utils/src/flags.ts +++ b/packages/utils/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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; diff --git a/packages/vue/src/flags.ts b/packages/vue/src/flags.ts index 28581cc7815d..fb99adbc2aa7 100644 --- a/packages/vue/src/flags.ts +++ b/packages/vue/src/flags.ts @@ -1,6 +1,15 @@ /* - * This file defines flags and constants that can be modified during - * compile time in order to facilitate tree shaking for users + * 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;