From 44d3df74595c0030ac1b85c58d0f830656b84765 Mon Sep 17 00:00:00 2001 From: Luca Forstner Date: Mon, 27 Nov 2023 12:38:28 +0000 Subject: [PATCH] I lost so many brain cells for this commit --- CONTRIBUTING.md | 2 +- packages/browser/src/client.ts | 9 +++--- packages/browser/src/debug-build.ts | 8 ++++++ .../browser/src/integrations/breadcrumbs.ts | 3 +- packages/browser/src/integrations/dedupe.ts | 4 ++- .../src/integrations/globalhandlers.ts | 3 +- .../browser/src/profiling/hubextensions.ts | 15 +++++----- packages/browser/src/profiling/integration.ts | 9 +++--- packages/browser/src/profiling/utils.ts | 28 +++++++++---------- packages/browser/src/sdk.ts | 10 +++---- packages/browser/src/transports/utils.ts | 4 +-- packages/core/src/baseclient.ts | 19 +++++++------ packages/core/src/debug-build.ts | 8 ++++++ packages/core/src/eventProcessors.ts | 7 ++--- packages/core/src/exports.ts | 9 +++--- packages/core/src/hub.ts | 7 +++-- packages/core/src/integration.ts | 5 ++-- .../core/src/integrations/inboundfilters.ts | 16 ++++++----- packages/core/src/sdk.ts | 3 +- packages/core/src/server-runtime-client.ts | 9 +++--- packages/core/src/tracing/errors.ts | 3 +- packages/core/src/tracing/hubextensions.ts | 3 +- packages/core/src/tracing/idletransaction.ts | 27 +++++++++--------- packages/core/src/tracing/sampling.ts | 13 +++++---- packages/core/src/tracing/span.ts | 6 ++-- packages/core/src/tracing/trace.ts | 3 +- packages/core/src/tracing/transaction.ts | 9 +++--- packages/core/src/transports/base.ts | 6 ++-- packages/core/src/transports/offline.ts | 4 ++- packages/feedback/src/debug-build.ts | 8 ++++++ packages/feedback/src/integration.ts | 11 ++++---- .../feedback/src/util/handleFeedbackSubmit.ts | 3 +- packages/integrations/src/debug-build.ts | 8 ++++++ packages/integrations/src/dedupe.ts | 4 ++- packages/integrations/src/extraerrordata.ts | 4 ++- packages/integrations/src/httpclient.ts | 10 ++++--- packages/integrations/src/offline.ts | 16 ++++++----- .../pagesRouterRoutingInstrumentation.ts | 4 ++- packages/nextjs/src/client/tunnelRoute.ts | 6 ++-- packages/nextjs/src/common/debug-build.ts | 8 ++++++ .../src/common/utils/edgeWrapperUtils.ts | 3 +- .../nextjs/src/common/utils/responseEnd.ts | 7 +++-- .../common/withServerActionInstrumentation.ts | 3 +- .../src/common/wrapApiHandlerWithSentry.ts | 3 +- packages/nextjs/src/config/webpack.ts | 5 ++-- packages/nextjs/src/server/index.ts | 9 +++--- packages/node-experimental/src/debug-build.ts | 8 ++++++ .../node-experimental/src/sdk/initOtel.ts | 3 +- packages/node/src/debug-build.ts | 8 ++++++ packages/node/src/handlers.ts | 3 +- packages/node/src/integrations/http.ts | 7 +++-- .../src/integrations/onuncaughtexception.ts | 3 +- .../src/integrations/utils/errorhandling.ts | 7 +++-- .../opentelemetry-node/src/debug-build.ts | 8 ++++++ .../opentelemetry-node/src/spanprocessor.ts | 4 +-- packages/opentelemetry/src/custom/scope.ts | 6 ++-- packages/opentelemetry/src/debug-build.ts | 8 ++++++ packages/opentelemetry/src/sampler.ts | 16 +++++------ packages/opentelemetry/src/spanExporter.ts | 5 ++-- packages/opentelemetry/src/spanProcessor.ts | 5 ++-- .../opentelemetry/test/helpers/initOtel.ts | 3 +- packages/react/src/debug-build.ts | 8 ++++++ packages/react/src/errorboundary.tsx | 4 ++- packages/react/src/reactrouterv6.tsx | 5 ++-- packages/remix/src/client/performance.tsx | 3 +- packages/remix/src/index.server.ts | 3 +- packages/remix/src/utils/debug-build.ts | 8 ++++++ packages/remix/src/utils/instrumentServer.ts | 13 ++++----- .../remix/src/utils/serverAdapters/express.ts | 9 +++--- packages/remix/src/utils/web-fetch.ts | 3 +- .../src/coreHandlers/handleGlobalEvent.ts | 3 +- .../coreHandlers/handleNetworkBreadcrumbs.ts | 3 +- .../src/coreHandlers/util/fetchUtils.ts | 9 +++--- .../src/coreHandlers/util/networkUtils.ts | 5 ++-- .../replay/src/coreHandlers/util/xhrUtils.ts | 5 ++-- packages/replay/src/debug-build.ts | 8 ++++++ .../src/eventBuffer/EventBufferProxy.ts | 3 +- .../replay/src/eventBuffer/WorkerHandler.ts | 3 +- packages/replay/src/replay.ts | 11 ++++---- packages/replay/src/util/addEvent.ts | 5 ++-- .../replay/src/util/handleRecordingEmit.ts | 3 +- packages/replay/src/util/log.ts | 6 ++-- packages/replay/src/util/sendReplay.ts | 3 +- .../replay/src/util/shouldFilterRequest.ts | 3 +- packages/serverless/src/awslambda.ts | 11 ++++---- packages/serverless/src/debug-build.ts | 8 ++++++ .../src/gcpfunction/cloud_events.ts | 3 +- packages/serverless/src/gcpfunction/events.ts | 3 +- packages/serverless/src/gcpfunction/http.ts | 3 +- packages/sveltekit/src/common/debug-build.ts | 8 ++++++ packages/sveltekit/src/server/utils.ts | 7 +++-- .../src/browser/backgroundtab.ts | 6 ++-- .../src/browser/browsertracing.ts | 19 ++++++------- .../src/browser/instrument.ts | 3 +- .../src/browser/metrics/index.ts | 22 +++++++-------- .../tracing-internal/src/browser/router.ts | 5 ++-- .../src/common/debug-build.ts | 8 ++++++ .../src/node/integrations/apollo.ts | 9 +++--- .../src/node/integrations/express.ts | 9 +++--- .../src/node/integrations/graphql.ts | 5 ++-- .../src/node/integrations/mongo.ts | 5 ++-- .../src/node/integrations/mysql.ts | 7 +++-- .../src/node/integrations/postgres.ts | 7 +++-- .../src/node/integrations/prisma.ts | 3 +- packages/types/src/globals.ts | 18 ------------ packages/types/src/index.ts | 4 --- packages/utils/src/baggage.ts | 3 +- packages/utils/src/debug-build.ts | 8 ++++++ packages/utils/src/dsn.ts | 3 +- packages/utils/src/instrument/_handlers.ts | 3 +- packages/utils/src/instrument/index.ts | 3 +- packages/utils/src/logger.ts | 3 +- packages/utils/src/object.ts | 3 +- packages/utils/src/requestdata.ts | 3 +- packages/utils/src/supports.ts | 3 +- packages/utils/test/dsn.test.ts | 11 ++++---- packages/vercel-edge/src/async.ts | 4 ++- packages/vercel-edge/src/debug-build.ts | 8 ++++++ packages/vue/src/debug-build.ts | 8 ++++++ packages/vue/src/tracing.ts | 3 +- 120 files changed, 521 insertions(+), 302 deletions(-) create mode 100644 packages/browser/src/debug-build.ts create mode 100644 packages/core/src/debug-build.ts create mode 100644 packages/feedback/src/debug-build.ts create mode 100644 packages/integrations/src/debug-build.ts create mode 100644 packages/nextjs/src/common/debug-build.ts create mode 100644 packages/node-experimental/src/debug-build.ts create mode 100644 packages/node/src/debug-build.ts create mode 100644 packages/opentelemetry-node/src/debug-build.ts create mode 100644 packages/opentelemetry/src/debug-build.ts create mode 100644 packages/react/src/debug-build.ts create mode 100644 packages/remix/src/utils/debug-build.ts create mode 100644 packages/replay/src/debug-build.ts create mode 100644 packages/serverless/src/debug-build.ts create mode 100644 packages/sveltekit/src/common/debug-build.ts create mode 100644 packages/tracing-internal/src/common/debug-build.ts delete mode 100644 packages/types/src/globals.ts create mode 100644 packages/utils/src/debug-build.ts create mode 100644 packages/vercel-edge/src/debug-build.ts create mode 100644 packages/vue/src/debug-build.ts diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9af7a880a407..717e548c5a9a 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -69,7 +69,7 @@ Pro tip: If any of your breakpoints are in code run by multiple tests, and you r ## Debug Build Flags -Throughout the codebase, you will find the `__DEBUG_BUILD__` flag guarding various code sections. This flag serves two purposes: +Throughout the codebase, you will find a `__DEBUG_BUILD__` constant. This flag serves two purposes: 1. It enables us to remove debug code from our minified CDN bundles during build, by replacing the flag with `false` before tree-shaking occurs. 2. It enables users to remove Sentry debug code from their production bundles during their own build. When we build our npm packages, we replace the flag with `(typeof __SENTRY_DEBUG__ === 'undefined' || __SENTRY_DEBUG__)`. If the user does nothing, this evaluates to `true` and logging is included. But if the user runs their own replacement during build (again replacing the flag with `false`), the build will tree-shake the logging away, just as our bundle builds do. diff --git a/packages/browser/src/client.ts b/packages/browser/src/client.ts index 4c0ace57547b..4e46314f6711 100644 --- a/packages/browser/src/client.ts +++ b/packages/browser/src/client.ts @@ -13,6 +13,7 @@ import type { } from '@sentry/types'; import { createClientReportEnvelope, dsnToString, getSDKSource, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { eventFromException, eventFromMessage } from './eventbuilder'; import { WINDOW } from './helpers'; import type { BrowserTransportOptions } from './transports/types'; @@ -96,7 +97,7 @@ export class BrowserClient extends BaseClient { */ public captureUserFeedback(feedback: UserFeedback): void { if (!this._isEnabled()) { - __DEBUG_BUILD__ && logger.warn('SDK not enabled, will not capture user feedback.'); + DEBUG_BUILD && logger.warn('SDK not enabled, will not capture user feedback.'); return; } @@ -123,17 +124,17 @@ export class BrowserClient extends BaseClient { const outcomes = this._clearOutcomes(); if (outcomes.length === 0) { - __DEBUG_BUILD__ && logger.log('No outcomes to send'); + DEBUG_BUILD && logger.log('No outcomes to send'); return; } // This is really the only place where we want to check for a DSN and only send outcomes then if (!this._dsn) { - __DEBUG_BUILD__ && logger.log('No dsn provided, will not send outcomes'); + DEBUG_BUILD && logger.log('No dsn provided, will not send outcomes'); return; } - __DEBUG_BUILD__ && logger.log('Sending outcomes:', outcomes); + DEBUG_BUILD && logger.log('Sending outcomes:', outcomes); const envelope = createClientReportEnvelope(outcomes, this._options.tunnel && dsnToString(this._dsn)); void this._sendEnvelope(envelope); diff --git a/packages/browser/src/debug-build.ts b/packages/browser/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/browser/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/browser/src/integrations/breadcrumbs.ts b/packages/browser/src/integrations/breadcrumbs.ts index 83db8af4fc63..2679cabed5f5 100644 --- a/packages/browser/src/integrations/breadcrumbs.ts +++ b/packages/browser/src/integrations/breadcrumbs.ts @@ -30,6 +30,7 @@ import { severityLevelFromString, } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { getClient } from '../exports'; import { WINDOW } from '../helpers'; @@ -148,7 +149,7 @@ function _domBreadcrumb(dom: BreadcrumbsOptions['dom']): (handlerData: HandlerDa let maxStringLength = typeof dom === 'object' && typeof dom.maxStringLength === 'number' ? dom.maxStringLength : undefined; if (maxStringLength && maxStringLength > MAX_ALLOWED_STRING_LENGTH) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `\`dom.maxStringLength\` cannot exceed ${MAX_ALLOWED_STRING_LENGTH}, but a value of ${maxStringLength} was configured. Sentry will use ${MAX_ALLOWED_STRING_LENGTH} instead.`, ); diff --git a/packages/browser/src/integrations/dedupe.ts b/packages/browser/src/integrations/dedupe.ts index c7a5cb5470b3..74d22d5a462c 100644 --- a/packages/browser/src/integrations/dedupe.ts +++ b/packages/browser/src/integrations/dedupe.ts @@ -1,6 +1,8 @@ import type { Event, Exception, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + /** Deduplication filter */ export class Dedupe implements Integration { /** @@ -40,7 +42,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, this._previousEvent)) { - __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + DEBUG_BUILD && logger.warn('Event dropped due to being a duplicate of previously captured event.'); return null; } } catch (_oO) {} // eslint-disable-line no-empty diff --git a/packages/browser/src/integrations/globalhandlers.ts b/packages/browser/src/integrations/globalhandlers.ts index 47acd2a75140..0c3f3be60e2d 100644 --- a/packages/browser/src/integrations/globalhandlers.ts +++ b/packages/browser/src/integrations/globalhandlers.ts @@ -12,6 +12,7 @@ import { } from '@sentry/utils'; import type { BrowserClient } from '../client'; +import { DEBUG_BUILD } from '../debug-build'; import { eventFromUnknownInput } from '../eventbuilder'; import { shouldIgnoreOnError } from '../helpers'; @@ -254,7 +255,7 @@ function _enhanceEventWithInitialFrame(event: Event, url: any, line: any, column } function globalHandlerLog(type: string): void { - __DEBUG_BUILD__ && logger.log(`Global Handler attached: ${type}`); + DEBUG_BUILD && logger.log(`Global Handler attached: ${type}`); } function getHubAndOptions(): [Hub, StackParser, boolean | undefined] { diff --git a/packages/browser/src/profiling/hubextensions.ts b/packages/browser/src/profiling/hubextensions.ts index 0c23b5e5f128..82492081b924 100644 --- a/packages/browser/src/profiling/hubextensions.ts +++ b/packages/browser/src/profiling/hubextensions.ts @@ -2,6 +2,7 @@ import type { Transaction } from '@sentry/types'; import { logger, timestampInSeconds, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { WINDOW } from '../helpers'; import type { JSSelfProfile } from './jsSelfProfiling'; import { @@ -21,7 +22,7 @@ import { */ export function onProfilingStartRouteTransaction(transaction: Transaction | undefined): Transaction | undefined { if (!transaction) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Transaction is undefined, skipping profiling'); } return transaction; @@ -54,7 +55,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio return transaction; } - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log(`[Profiling] started profiling transaction: ${transaction.name || transaction.description}`); } @@ -85,7 +86,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio return null; } if (processedProfile) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( '[Profiling] profile for:', transaction.name || transaction.description, @@ -103,13 +104,13 @@ export function startProfileForTransaction(transaction: Transaction): Transactio maxDurationTimeoutID = undefined; } - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log(`[Profiling] stopped profiling of transaction: ${transaction.name || transaction.description}`); } // In case of an overlapping transaction, stopProfiling may return null and silently ignore the overlapping profile. if (!profile) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( `[Profiling] profiler returned null profile for: ${transaction.name || transaction.description}`, 'this may indicate an overlapping transaction or a call to stopProfiling with a profile title that was never started', @@ -122,7 +123,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio return null; }) .catch(error => { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] error while stopping profiler:', error); } return null; @@ -131,7 +132,7 @@ export function startProfileForTransaction(transaction: Transaction): Transactio // Enqueue a timeout to prevent profiles from running over max duration. let maxDurationTimeoutID: number | undefined = WINDOW.setTimeout(() => { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( '[Profiling] max profile duration elapsed, stopping profiling for:', transaction.name || transaction.description, diff --git a/packages/browser/src/profiling/integration.ts b/packages/browser/src/profiling/integration.ts index 1ccfd63cf798..3f5251c4583f 100644 --- a/packages/browser/src/profiling/integration.ts +++ b/packages/browser/src/profiling/integration.ts @@ -2,6 +2,7 @@ import type { EventProcessor, Hub, Integration, Transaction } from '@sentry/type import type { Profile } from '@sentry/types/src/profiling'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { startProfileForTransaction } from './hubextensions'; import type { ProfiledEvent } from './utils'; import { @@ -78,14 +79,12 @@ export class BrowserProfilingIntegration implements Integration { const start_timestamp = context && context['profile'] && context['profile']['start_timestamp']; if (typeof profile_id !== 'string') { - __DEBUG_BUILD__ && - logger.log('[Profiling] cannot find profile for a transaction without a profile context'); + DEBUG_BUILD && logger.log('[Profiling] cannot find profile for a transaction without a profile context'); continue; } if (!profile_id) { - __DEBUG_BUILD__ && - logger.log('[Profiling] cannot find profile for a transaction without a profile context'); + DEBUG_BUILD && logger.log('[Profiling] cannot find profile for a transaction without a profile context'); continue; } @@ -96,7 +95,7 @@ export class BrowserProfilingIntegration implements Integration { const profile = takeProfileFromGlobalCache(profile_id); if (!profile) { - __DEBUG_BUILD__ && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); + DEBUG_BUILD && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); continue; } diff --git a/packages/browser/src/profiling/utils.ts b/packages/browser/src/profiling/utils.ts index 4c8a74adf247..ddf966d86deb 100644 --- a/packages/browser/src/profiling/utils.ts +++ b/packages/browser/src/profiling/utils.ts @@ -5,6 +5,7 @@ import type { DebugImage, Envelope, Event, StackFrame, StackParser, Transaction import type { Profile, ThreadCpuProfile } from '@sentry/types/src/profiling'; import { browserPerformanceTimeOrigin, forEachEnvelopeItem, GLOBAL_OBJ, logger, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { getClient } from '../exports'; import { WINDOW } from '../helpers'; import type { JSSelfProfile, JSSelfProfiler, JSSelfProfilerConstructor, JSSelfProfileStack } from './jsSelfProfiling'; @@ -96,7 +97,7 @@ function getTraceId(event: Event): string { // All profiles and transactions are rejected if this is the case and we want to // warn users that this is happening if they enable debug flag if (typeof traceId === 'string' && traceId.length !== 32) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log(`[Profiling] Invalid traceId: ${traceId} on profiled event`); } } @@ -418,7 +419,7 @@ export function applyDebugMetadata(resource_paths: ReadonlyArray): Debug export 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 if ((typeof rate !== 'number' && typeof rate !== 'boolean') || (typeof rate === 'number' && isNaN(rate))) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -434,8 +435,7 @@ export 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) { - __DEBUG_BUILD__ && - logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`); + DEBUG_BUILD && logger.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } return true; @@ -443,7 +443,7 @@ export function isValidSampleRate(rate: unknown): boolean { function isValidProfile(profile: JSSelfProfile): profile is JSSelfProfile & { profile_id: string } { if (profile.samples.length < 2) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { // Log a warning if the profile has less than 2 samples so users can know why // they are not seeing any profiling data and we cant avoid the back and forth // of asking them to provide us with a dump of the profile data. @@ -453,7 +453,7 @@ function isValidProfile(profile: JSSelfProfile): profile is JSSelfProfile & { pr } if (!profile.frames.length) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Discarding profile because it contains no frames'); } return false; @@ -483,7 +483,7 @@ export function startJSSelfProfile(): JSSelfProfiler | undefined { const JSProfilerConstructor = WINDOW.Profiler; if (!isJSProfilerSupported(JSProfilerConstructor)) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( '[Profiling] Profiling is not supported by this browser, Profiler interface missing on window object.', ); @@ -502,7 +502,7 @@ export function startJSSelfProfile(): JSSelfProfiler | undefined { try { return new JSProfilerConstructor({ sampleInterval: samplingIntervalMS, maxBufferSize: maxSamples }); } catch (e) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log( "[Profiling] Failed to initialize the Profiling constructor, this is likely due to a missing 'Document-Policy': 'js-profiling' header.", ); @@ -520,14 +520,14 @@ export function startJSSelfProfile(): JSSelfProfiler | undefined { export function shouldProfileTransaction(transaction: Transaction): boolean { // If constructor failed once, it will always fail, so we can early return. if (PROFILING_CONSTRUCTOR_FAILED) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Profiling has been disabled for the duration of the current user session.'); } return false; } if (!transaction.sampled) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.log('[Profiling] Discarding profile because transaction was not sampled.'); } return false; @@ -536,7 +536,7 @@ export function shouldProfileTransaction(transaction: Transaction): boolean { const client = getClient(); const options = client && client.getOptions(); if (!options) { - __DEBUG_BUILD__ && logger.log('[Profiling] Profiling disabled, no options found.'); + DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no options found.'); return false; } @@ -546,13 +546,13 @@ export function shouldProfileTransaction(transaction: Transaction): boolean { // 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(profilesSampleRate)) { - __DEBUG_BUILD__ && logger.warn('[Profiling] Discarding profile because of invalid sample rate.'); + DEBUG_BUILD && logger.warn('[Profiling] Discarding profile because of invalid sample rate.'); return false; } // if the function returned 0 (or false), or if `profileSampleRate` is 0, it's a sign the profile should be dropped if (!profilesSampleRate) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( '[Profiling] Discarding profile because a negative sampling decision was inherited or profileSampleRate is set to 0', ); @@ -564,7 +564,7 @@ export function shouldProfileTransaction(transaction: Transaction): boolean { const sampled = profilesSampleRate === true ? true : Math.random() < profilesSampleRate; // Check if we should sample this profile if (!sampled) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number( profilesSampleRate, diff --git a/packages/browser/src/sdk.ts b/packages/browser/src/sdk.ts index 0244af0ba98e..2bee5912e15e 100644 --- a/packages/browser/src/sdk.ts +++ b/packages/browser/src/sdk.ts @@ -17,6 +17,7 @@ import { import type { BrowserClientOptions, BrowserOptions } from './client'; import { BrowserClient } from './client'; +import { DEBUG_BUILD } from './debug-build'; import type { ReportDialogOptions } from './helpers'; import { WINDOW, wrap as internalWrap } from './helpers'; import { Breadcrumbs, Dedupe, GlobalHandlers, HttpContext, LinkedErrors, TryCatch } from './integrations'; @@ -140,14 +141,14 @@ export function init(options: BrowserOptions = {}): void { export function showReportDialog(options: ReportDialogOptions = {}, hub: Hub = getCurrentHub()): void { // doesn't work without a document (React Native) if (!WINDOW.document) { - __DEBUG_BUILD__ && logger.error('Global document not defined in showReportDialog call'); + DEBUG_BUILD && logger.error('Global document not defined in showReportDialog call'); return; } const { client, scope } = hub.getStackTop(); const dsn = options.dsn || (client && client.getDsn()); if (!dsn) { - __DEBUG_BUILD__ && logger.error('DSN not configured for showReportDialog call'); + DEBUG_BUILD && logger.error('DSN not configured for showReportDialog call'); return; } @@ -189,7 +190,7 @@ export function showReportDialog(options: ReportDialogOptions = {}, hub: Hub = g if (injectionPoint) { injectionPoint.appendChild(script); } else { - __DEBUG_BUILD__ && logger.error('Not injecting report dialog. No injection point found in HTML'); + DEBUG_BUILD && logger.error('Not injecting report dialog. No injection point found in HTML'); } } @@ -236,8 +237,7 @@ function startSessionOnHub(hub: Hub): void { */ function startSessionTracking(): void { if (typeof WINDOW.document === 'undefined') { - __DEBUG_BUILD__ && - logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); + DEBUG_BUILD && logger.warn('Session tracking in non-browser environment with @sentry/browser is not supported.'); return; } diff --git a/packages/browser/src/transports/utils.ts b/packages/browser/src/transports/utils.ts index 9852d754ec7b..6b42ae77b480 100644 --- a/packages/browser/src/transports/utils.ts +++ b/packages/browser/src/transports/utils.ts @@ -1,5 +1,6 @@ import { isNativeFetch, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { WINDOW } from '../helpers'; let cachedFetchImpl: FetchImpl | undefined = undefined; @@ -70,8 +71,7 @@ export function getNativeFetchImplementation(): FetchImpl { } document.head.removeChild(sandbox); } catch (e) { - __DEBUG_BUILD__ && - logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); + DEBUG_BUILD && logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', e); } } diff --git a/packages/core/src/baseclient.ts b/packages/core/src/baseclient.ts index 915bafffa9bc..df3444126e8d 100644 --- a/packages/core/src/baseclient.ts +++ b/packages/core/src/baseclient.ts @@ -44,6 +44,7 @@ import { } from '@sentry/utils'; import { getEnvelopeEndpointWithUrlEncodedAuth } from './api'; +import { DEBUG_BUILD } from './debug-build'; import { createEventEnvelope, createSessionEnvelope } from './envelope'; import type { IntegrationIndex } from './integration'; import { setupIntegration, setupIntegrations } from './integration'; @@ -128,7 +129,7 @@ export abstract class BaseClient implements Client { if (options.dsn) { this._dsn = makeDsn(options.dsn); } else { - __DEBUG_BUILD__ && logger.warn('No DSN provided, client will not send events.'); + DEBUG_BUILD && logger.warn('No DSN provided, client will not send events.'); } if (this._dsn) { @@ -148,7 +149,7 @@ export abstract class BaseClient implements Client { public captureException(exception: any, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (checkOrSetAlreadyCaught(exception)) { - __DEBUG_BUILD__ && logger.log(ALREADY_SEEN_ERROR); + DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); return; } @@ -198,7 +199,7 @@ export abstract class BaseClient implements Client { public captureEvent(event: Event, hint?: EventHint, scope?: Scope): string | undefined { // ensure we haven't captured this very object before if (hint && hint.originalException && checkOrSetAlreadyCaught(hint.originalException)) { - __DEBUG_BUILD__ && logger.log(ALREADY_SEEN_ERROR); + DEBUG_BUILD && logger.log(ALREADY_SEEN_ERROR); return; } @@ -218,7 +219,7 @@ export abstract class BaseClient implements Client { */ public captureSession(session: Session): void { if (!(typeof session.release === 'string')) { - __DEBUG_BUILD__ && logger.warn('Discarded session because of missing or non-string release'); + DEBUG_BUILD && logger.warn('Discarded session because of missing or non-string release'); } else { this.sendSession(session); // After sending, we set init false to indicate it's not the first occurrence @@ -316,7 +317,7 @@ export abstract class BaseClient implements Client { try { return (this._integrations[integration.id] as T) || null; } catch (_oO) { - __DEBUG_BUILD__ && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); + DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Client`); return null; } } @@ -374,7 +375,7 @@ export abstract class BaseClient implements Client { // would be `Partial>>>` // With typescript 4.1 we could even use template literal types const key = `${reason}:${category}`; - __DEBUG_BUILD__ && logger.log(`Adding outcome: "${key}"`); + DEBUG_BUILD && logger.log(`Adding outcome: "${key}"`); // The following works because undefined + 1 === NaN and NaN is falsy this._outcomes[key] = this._outcomes[key] + 1 || 1; @@ -604,7 +605,7 @@ export abstract class BaseClient implements Client { return finalEvent.event_id; }, reason => { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { // If something's gone wrong, log the error as a warning. If it's just us having used a `SentryError` for // control flow, log just the message (no stack) as a log-level log. const sentryError = reason as SentryError; @@ -739,10 +740,10 @@ export abstract class BaseClient implements Client { if (this._isEnabled() && this._transport) { return this._transport.send(envelope).then(null, reason => { - __DEBUG_BUILD__ && logger.error('Error while sending event:', reason); + DEBUG_BUILD && logger.error('Error while sending event:', reason); }); } else { - __DEBUG_BUILD__ && logger.error('Transport disabled'); + DEBUG_BUILD && logger.error('Transport disabled'); } } diff --git a/packages/core/src/debug-build.ts b/packages/core/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/core/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/core/src/eventProcessors.ts b/packages/core/src/eventProcessors.ts index 4596788b9dcb..cc4a39cc84ea 100644 --- a/packages/core/src/eventProcessors.ts +++ b/packages/core/src/eventProcessors.ts @@ -1,6 +1,8 @@ import type { Event, EventHint, EventProcessor } from '@sentry/types'; import { getGlobalSingleton, isThenable, logger, SyncPromise } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + /** * Returns the global event processors. */ @@ -32,10 +34,7 @@ export function notifyEventProcessors( } else { const result = processor({ ...event }, hint) as Event | null; - __DEBUG_BUILD__ && - processor.id && - result === null && - logger.log(`Event processor "${processor.id}" dropped event`); + DEBUG_BUILD && processor.id && result === null && logger.log(`Event processor "${processor.id}" dropped event`); if (isThenable(result)) { void result diff --git a/packages/core/src/exports.ts b/packages/core/src/exports.ts index 6d1d52e60863..6d1e80600a75 100644 --- a/packages/core/src/exports.ts +++ b/packages/core/src/exports.ts @@ -18,6 +18,7 @@ import type { } from '@sentry/types'; import { isThenable, logger, timestampInSeconds, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import type { Hub } from './hub'; import { getCurrentHub } from './hub'; import type { Scope } from './scope'; @@ -205,9 +206,9 @@ export function captureCheckIn(checkIn: CheckIn, upsertMonitorConfig?: MonitorCo const scope = hub.getScope(); const client = hub.getClient(); if (!client) { - __DEBUG_BUILD__ && logger.warn('Cannot capture check-in. No client defined.'); + DEBUG_BUILD && logger.warn('Cannot capture check-in. No client defined.'); } else if (!client.captureCheckIn) { - __DEBUG_BUILD__ && logger.warn('Cannot capture check-in. Client does not support sending check-ins.'); + DEBUG_BUILD && logger.warn('Cannot capture check-in. Client does not support sending check-ins.'); } else { return client.captureCheckIn(checkIn, upsertMonitorConfig, scope); } @@ -271,7 +272,7 @@ export async function flush(timeout?: number): Promise { if (client) { return client.flush(timeout); } - __DEBUG_BUILD__ && logger.warn('Cannot flush events. No client defined.'); + DEBUG_BUILD && logger.warn('Cannot flush events. No client defined.'); return Promise.resolve(false); } @@ -288,7 +289,7 @@ export async function close(timeout?: number): Promise { if (client) { return client.close(timeout); } - __DEBUG_BUILD__ && logger.warn('Cannot flush events and disable SDK. No client defined.'); + DEBUG_BUILD && logger.warn('Cannot flush events and disable SDK. No client defined.'); return Promise.resolve(false); } diff --git a/packages/core/src/hub.ts b/packages/core/src/hub.ts index c25f9fe00f67..892ecf7b3b52 100644 --- a/packages/core/src/hub.ts +++ b/packages/core/src/hub.ts @@ -23,6 +23,7 @@ import type { import { consoleSandbox, dateTimestampInSeconds, getGlobalSingleton, GLOBAL_OBJ, logger, uuid4 } from '@sentry/utils'; import { DEFAULT_ENVIRONMENT } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import { Scope } from './scope'; import { closeSession, makeSession, updateSession } from './session'; @@ -362,7 +363,7 @@ export class Hub implements HubInterface { try { return client.getIntegration(integration); } catch (_oO) { - __DEBUG_BUILD__ && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); + DEBUG_BUILD && logger.warn(`Cannot retrieve integration ${integration.id} from the current Hub`); return null; } } @@ -373,7 +374,7 @@ export class Hub implements HubInterface { public startTransaction(context: TransactionContext, customSamplingContext?: CustomSamplingContext): Transaction { const result = this._callExtensionMethod('startTransaction', context, customSamplingContext); - if (__DEBUG_BUILD__ && !result) { + if (DEBUG_BUILD && !result) { const client = this.getClient(); if (!client) { // eslint-disable-next-line no-console @@ -505,7 +506,7 @@ Sentry.init({...}); if (sentry && sentry.extensions && typeof sentry.extensions[method] === 'function') { return sentry.extensions[method].apply(this, args); } - __DEBUG_BUILD__ && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); + DEBUG_BUILD && logger.warn(`Extension method ${method} couldn't be found, doing nothing.`); } } diff --git a/packages/core/src/integration.ts b/packages/core/src/integration.ts index 8b05139af74b..2f21339a0842 100644 --- a/packages/core/src/integration.ts +++ b/packages/core/src/integration.ts @@ -1,6 +1,7 @@ import type { Client, Event, EventHint, Integration, Options } from '@sentry/types'; import { arrayify, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { addGlobalEventProcessor } from './eventProcessors'; import { getClient } from './exports'; import { getCurrentHub } from './hub'; @@ -128,7 +129,7 @@ export function setupIntegration(client: Client, integration: Integration, integ client.addEventProcessor(processor); } - __DEBUG_BUILD__ && logger.log(`Integration installed: ${integration.name}`); + DEBUG_BUILD && logger.log(`Integration installed: ${integration.name}`); } /** Add an integration to the current hub's client. */ @@ -136,7 +137,7 @@ export function addIntegration(integration: Integration): void { const client = getClient(); if (!client || !client.addIntegration) { - __DEBUG_BUILD__ && logger.warn(`Cannot add integration "${integration.name}" because no SDK Client is available.`); + DEBUG_BUILD && logger.warn(`Cannot add integration "${integration.name}" because no SDK Client is available.`); return; } diff --git a/packages/core/src/integrations/inboundfilters.ts b/packages/core/src/integrations/inboundfilters.ts index 20721d9dbcec..c1fcadb1076b 100644 --- a/packages/core/src/integrations/inboundfilters.ts +++ b/packages/core/src/integrations/inboundfilters.ts @@ -1,6 +1,8 @@ import type { Client, Event, EventHint, Integration, StackFrame } from '@sentry/types'; import { getEventDescription, logger, stringMatchesSomePattern } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + // "Script error." is hard coded into browsers for errors that it can't read. // this is the result of a script being pulled in from an external domain and CORS. const DEFAULT_IGNORE_ERRORS = [/^Script error\.?$/, /^Javascript error: Script error\.? on line 0$/]; @@ -85,26 +87,26 @@ export function _mergeOptions( /** JSDoc */ export function _shouldDropEvent(event: Event, options: Partial): boolean { if (options.ignoreInternal && _isSentryError(event)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`Event dropped due to being internal Sentry Error.\nEvent: ${getEventDescription(event)}`); return true; } if (_isIgnoredError(event, options.ignoreErrors)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`ignoreErrors\` option.\nEvent: ${getEventDescription(event)}`, ); return true; } if (_isIgnoredTransaction(event, options.ignoreTransactions)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`ignoreTransactions\` option.\nEvent: ${getEventDescription(event)}`, ); return true; } if (_isDeniedUrl(event, options.denyUrls)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Event dropped due to being matched by \`denyUrls\` option.\nEvent: ${getEventDescription( event, @@ -113,7 +115,7 @@ export function _shouldDropEvent(event: Event, options: Partial( options: O, ): void { if (options.debug === true) { - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { logger.enable(); } else { // use `console.warn` rather than `logger.warn` since by non-debug bundles have all `logger.x` statements stripped diff --git a/packages/core/src/server-runtime-client.ts b/packages/core/src/server-runtime-client.ts index 67d7055a1623..398a4224ef6d 100644 --- a/packages/core/src/server-runtime-client.ts +++ b/packages/core/src/server-runtime-client.ts @@ -15,6 +15,7 @@ import { eventFromMessage, eventFromUnknownInput, logger, resolvedSyncPromise, u import { BaseClient } from './baseclient'; import { createCheckInEnvelope } from './checkin'; +import { DEBUG_BUILD } from './debug-build'; import { getCurrentHub } from './hub'; import type { Scope } from './scope'; import { SessionFlusher } from './sessionflusher'; @@ -129,7 +130,7 @@ export class ServerRuntimeClient< public initSessionFlusher(): void { const { release, environment } = this._options; if (!release) { - __DEBUG_BUILD__ && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); + DEBUG_BUILD && logger.warn('Cannot initialise an instance of SessionFlusher if no release is provided!'); } else { this._sessionFlusher = new SessionFlusher(this, { release, @@ -148,7 +149,7 @@ export class ServerRuntimeClient< public captureCheckIn(checkIn: CheckIn, monitorConfig?: MonitorConfig, scope?: Scope): string { const id = checkIn.status !== 'in_progress' && checkIn.checkInId ? checkIn.checkInId : uuid4(); if (!this._isEnabled()) { - __DEBUG_BUILD__ && logger.warn('SDK not enabled, will not capture checkin.'); + DEBUG_BUILD && logger.warn('SDK not enabled, will not capture checkin.'); return id; } @@ -191,7 +192,7 @@ export class ServerRuntimeClient< this.getDsn(), ); - __DEBUG_BUILD__ && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status); + DEBUG_BUILD && logger.info('Sending checkin:', checkIn.monitorSlug, checkIn.status); void this._sendEnvelope(envelope); return id; } @@ -202,7 +203,7 @@ export class ServerRuntimeClient< */ protected _captureRequestSession(): void { if (!this._sessionFlusher) { - __DEBUG_BUILD__ && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); + DEBUG_BUILD && logger.warn('Discarded request mode session because autoSessionTracking option was disabled'); } else { this._sessionFlusher.incrementSessionStatusCount(); } diff --git a/packages/core/src/tracing/errors.ts b/packages/core/src/tracing/errors.ts index 477629cb7f9e..9030f02efadc 100644 --- a/packages/core/src/tracing/errors.ts +++ b/packages/core/src/tracing/errors.ts @@ -4,6 +4,7 @@ import { logger, } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { SpanStatusType } from './span'; import { getActiveTransaction } from './utils'; @@ -29,7 +30,7 @@ function errorCallback(): void { const activeTransaction = getActiveTransaction(); if (activeTransaction) { const status: SpanStatusType = 'internal_error'; - __DEBUG_BUILD__ && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); + DEBUG_BUILD && logger.log(`[Tracing] Transaction: ${status} -> Global error occured`); activeTransaction.setStatus(status); } } diff --git a/packages/core/src/tracing/hubextensions.ts b/packages/core/src/tracing/hubextensions.ts index 007612d8fb34..7cd8286860b2 100644 --- a/packages/core/src/tracing/hubextensions.ts +++ b/packages/core/src/tracing/hubextensions.ts @@ -1,6 +1,7 @@ import type { ClientOptions, CustomSamplingContext, TransactionContext } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import { getMainCarrier } from '../hub'; import { registerErrorInstrumentation } from './errors'; @@ -47,7 +48,7 @@ function _startTransaction( const transactionInstrumenter = transactionContext.instrumenter || 'sentry'; if (configInstrumenter !== transactionInstrumenter) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error( `A transaction was started with instrumenter=\`${transactionInstrumenter}\`, but the SDK is configured with the \`${configInstrumenter}\` instrumenter. The transaction will not be sampled. Please use the ${configInstrumenter} instrumentation to start transactions.`, diff --git a/packages/core/src/tracing/idletransaction.ts b/packages/core/src/tracing/idletransaction.ts index 1c4086ceecb7..b49b1d15e9b1 100644 --- a/packages/core/src/tracing/idletransaction.ts +++ b/packages/core/src/tracing/idletransaction.ts @@ -2,6 +2,7 @@ import type { TransactionContext } from '@sentry/types'; import { logger, timestampInSeconds } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import type { Span } from './span'; import { SpanRecorder } from './span'; @@ -119,7 +120,7 @@ export class IdleTransaction extends Transaction { if (_onScope) { // We set the transaction here on the scope so error events pick up the trace // context and attach it to the error. - __DEBUG_BUILD__ && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); + DEBUG_BUILD && logger.log(`Setting idle transaction on scope. Span ID: ${this.spanId}`); _idleHub.configureScope(scope => scope.setSpan(this)); } @@ -143,7 +144,7 @@ export class IdleTransaction extends Transaction { } if (this.spanRecorder) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log('[Tracing] finishing IdleTransaction', new Date(endTimestamp * 1000).toISOString(), this.op); for (const callback of this._beforeFinishCallbacks) { @@ -160,7 +161,7 @@ export class IdleTransaction extends Transaction { if (!span.endTimestamp) { span.endTimestamp = endTimestamp; span.setStatus('cancelled'); - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log('[Tracing] cancelling span since transaction ended early', JSON.stringify(span, undefined, 2)); } @@ -170,7 +171,7 @@ export class IdleTransaction extends Transaction { const timeoutWithMarginOfError = (this._finalTimeout + this._idleTimeout) / 1000; const spanEndedBeforeFinalTimeout = span.endTimestamp - this.startTimestamp < timeoutWithMarginOfError; - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { const stringifiedSpan = JSON.stringify(span, undefined, 2); if (!spanStartedBeforeTransactionFinish) { logger.log('[Tracing] discarding Span since it happened after Transaction was finished', stringifiedSpan); @@ -182,9 +183,9 @@ export class IdleTransaction extends Transaction { return spanStartedBeforeTransactionFinish && spanEndedBeforeFinalTimeout; }); - __DEBUG_BUILD__ && logger.log('[Tracing] flushing IdleTransaction'); + DEBUG_BUILD && logger.log('[Tracing] flushing IdleTransaction'); } else { - __DEBUG_BUILD__ && logger.log('[Tracing] No active IdleTransaction'); + DEBUG_BUILD && logger.log('[Tracing] No active IdleTransaction'); } // if `this._onScope` is `true`, the transaction put itself on the scope when it started @@ -230,7 +231,7 @@ export class IdleTransaction extends Transaction { this.spanRecorder = new IdleTransactionSpanRecorder(pushActivity, popActivity, this.spanId, maxlen); // Start heartbeat so that transactions do not run forever. - __DEBUG_BUILD__ && logger.log('Starting heartbeat'); + DEBUG_BUILD && logger.log('Starting heartbeat'); this._pingHeartbeat(); } this.spanRecorder.add(this); @@ -296,9 +297,9 @@ export class IdleTransaction extends Transaction { */ private _pushActivity(spanId: string): void { this.cancelIdleTimeout(undefined, { restartOnChildSpanChange: !this._idleTimeoutCanceledPermanently }); - __DEBUG_BUILD__ && logger.log(`[Tracing] pushActivity: ${spanId}`); + DEBUG_BUILD && logger.log(`[Tracing] pushActivity: ${spanId}`); this.activities[spanId] = true; - __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } /** @@ -307,10 +308,10 @@ export class IdleTransaction extends Transaction { */ private _popActivity(spanId: string): void { if (this.activities[spanId]) { - __DEBUG_BUILD__ && logger.log(`[Tracing] popActivity ${spanId}`); + DEBUG_BUILD && logger.log(`[Tracing] popActivity ${spanId}`); // eslint-disable-next-line @typescript-eslint/no-dynamic-delete delete this.activities[spanId]; - __DEBUG_BUILD__ && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); + DEBUG_BUILD && logger.log('[Tracing] new activities count', Object.keys(this.activities).length); } if (Object.keys(this.activities).length === 0) { @@ -347,7 +348,7 @@ export class IdleTransaction extends Transaction { this._prevHeartbeatString = heartbeatString; if (this._heartbeatCounter >= 3) { - __DEBUG_BUILD__ && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); + DEBUG_BUILD && logger.log('[Tracing] Transaction finished because of no change for 3 heart beats'); this.setStatus('deadline_exceeded'); this._finishReason = IDLE_TRANSACTION_FINISH_REASONS[0]; this.finish(); @@ -360,7 +361,7 @@ export class IdleTransaction extends Transaction { * Pings the heartbeat */ private _pingHeartbeat(): void { - __DEBUG_BUILD__ && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); + DEBUG_BUILD && logger.log(`pinging Heartbeat -> current counter: ${this._heartbeatCounter}`); setTimeout(() => { this._beat(); }, this._heartbeatInterval); diff --git a/packages/core/src/tracing/sampling.ts b/packages/core/src/tracing/sampling.ts index 4b357b7bf1be..6c6ab19bf7c9 100644 --- a/packages/core/src/tracing/sampling.ts +++ b/packages/core/src/tracing/sampling.ts @@ -1,6 +1,7 @@ import type { Options, SamplingContext } from '@sentry/types'; import { isNaN, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { hasTracingEnabled } from '../utils/hasTracingEnabled'; import type { Transaction } from './transaction'; @@ -58,14 +59,14 @@ export function sampleTransaction( // 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)) { - __DEBUG_BUILD__ && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); + DEBUG_BUILD && logger.warn('[Tracing] Discarding transaction because of invalid sample rate.'); transaction.sampled = false; return transaction; } // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped if (!sampleRate) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding transaction because ${ typeof options.tracesSampler === 'function' @@ -83,7 +84,7 @@ export function sampleTransaction( // if we're not going to keep it, we're done if (!transaction.sampled) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding transaction because it's not included in the random sample (sampling rate = ${Number( sampleRate, @@ -92,7 +93,7 @@ export function sampleTransaction( return transaction; } - __DEBUG_BUILD__ && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); + DEBUG_BUILD && logger.log(`[Tracing] starting ${transaction.op} transaction - ${transaction.name}`); return transaction; } @@ -103,7 +104,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')) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -114,7 +115,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) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } diff --git a/packages/core/src/tracing/span.ts b/packages/core/src/tracing/span.ts index be4e420fc8bc..4b341a71e2c2 100644 --- a/packages/core/src/tracing/span.ts +++ b/packages/core/src/tracing/span.ts @@ -10,6 +10,8 @@ import type { } from '@sentry/types'; import { dropUndefinedKeys, generateSentryTraceHeader, logger, timestampInSeconds, uuid4 } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + /** * Keeps track of finished spans for a given transaction * @internal @@ -190,7 +192,7 @@ export class Span implements SpanInterface { childSpan.transaction = this.transaction; - if (__DEBUG_BUILD__ && childSpan.transaction) { + if (DEBUG_BUILD && childSpan.transaction) { const opStr = (spanContext && spanContext.op) || '< unknown op >'; const nameStr = childSpan.transaction.name || '< unknown name >'; const idStr = childSpan.transaction.spanId; @@ -260,7 +262,7 @@ export class Span implements SpanInterface { */ public finish(endTimestamp?: number): void { if ( - __DEBUG_BUILD__ && + DEBUG_BUILD && // Don't call this for transactions this.transaction && this.transaction.spanId !== this.spanId diff --git a/packages/core/src/tracing/trace.ts b/packages/core/src/tracing/trace.ts index 33e19ec7ecb4..99d706f0585e 100644 --- a/packages/core/src/tracing/trace.ts +++ b/packages/core/src/tracing/trace.ts @@ -1,6 +1,7 @@ import type { TransactionContext } from '@sentry/types'; import { dropUndefinedKeys, isThenable, logger, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import { getCurrentHub } from '../hub'; import { hasTracingEnabled } from '../utils/hasTracingEnabled'; @@ -248,7 +249,7 @@ export function continueTrace( currentScope.setPropagationContext(propagationContext); - if (__DEBUG_BUILD__ && traceparentData) { + if (DEBUG_BUILD && traceparentData) { logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`); } diff --git a/packages/core/src/tracing/transaction.ts b/packages/core/src/tracing/transaction.ts index 73bfb16996bb..da2ccb32d30b 100644 --- a/packages/core/src/tracing/transaction.ts +++ b/packages/core/src/tracing/transaction.ts @@ -11,6 +11,7 @@ import type { } from '@sentry/types'; import { dropUndefinedKeys, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { Hub } from '../hub'; import { getCurrentHub } from '../hub'; import { getDynamicSamplingContextFromClient } from './dynamicSamplingContext'; @@ -226,7 +227,7 @@ export class Transaction extends SpanClass implements TransactionInterface { } if (!this.name) { - __DEBUG_BUILD__ && logger.warn('Transaction has no name, falling back to ``.'); + DEBUG_BUILD && logger.warn('Transaction has no name, falling back to ``.'); this.name = ''; } @@ -240,7 +241,7 @@ export class Transaction extends SpanClass implements TransactionInterface { if (this.sampled !== true) { // At this point if `sampled !== true` we want to discard the transaction. - __DEBUG_BUILD__ && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); + DEBUG_BUILD && logger.log('[Tracing] Discarding transaction because its trace was not chosen to be sampled.'); if (client) { client.recordDroppedEvent('sample_rate', 'transaction'); @@ -288,7 +289,7 @@ export class Transaction extends SpanClass implements TransactionInterface { const hasMeasurements = Object.keys(this._measurements).length > 0; if (hasMeasurements) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( '[Measurements] Adding measurements to transaction', JSON.stringify(this._measurements, undefined, 2), @@ -296,7 +297,7 @@ export class Transaction extends SpanClass implements TransactionInterface { transaction.measurements = this._measurements; } - __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); + DEBUG_BUILD && logger.log(`[Tracing] Finishing ${this.op} transaction: ${this.name}.`); return transaction; } diff --git a/packages/core/src/transports/base.ts b/packages/core/src/transports/base.ts index 3111f5f15fca..199cad6c545b 100644 --- a/packages/core/src/transports/base.ts +++ b/packages/core/src/transports/base.ts @@ -24,6 +24,8 @@ import { updateRateLimits, } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + export const DEFAULT_TRANSPORT_BUFFER_SIZE = 30; /** @@ -77,7 +79,7 @@ export function createTransport( response => { // We don't want to throw on NOK responses, but we want to at least log them if (response.statusCode !== undefined && (response.statusCode < 200 || response.statusCode >= 300)) { - __DEBUG_BUILD__ && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`); + DEBUG_BUILD && logger.warn(`Sentry responded with status code ${response.statusCode} to sent event.`); } rateLimits = updateRateLimits(rateLimits, response); @@ -93,7 +95,7 @@ export function createTransport( result => result, error => { if (error instanceof SentryError) { - __DEBUG_BUILD__ && logger.error('Skipped sending event because buffer is full.'); + DEBUG_BUILD && logger.error('Skipped sending event because buffer is full.'); recordEnvelopeLoss('queue_overflow'); return resolvedSyncPromise(); } else { diff --git a/packages/core/src/transports/offline.ts b/packages/core/src/transports/offline.ts index c3864ead7ec5..c628e538a071 100644 --- a/packages/core/src/transports/offline.ts +++ b/packages/core/src/transports/offline.ts @@ -1,12 +1,14 @@ import type { Envelope, InternalBaseTransportOptions, Transport, TransportMakeRequestResponse } from '@sentry/types'; import { envelopeContainsItemType, logger, parseRetryAfterHeader } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + export const MIN_DELAY = 100; // 100 ms export const START_DELAY = 5_000; // 5 seconds const MAX_DELAY = 3.6e6; // 1 hour function log(msg: string, error?: Error): void { - __DEBUG_BUILD__ && logger.info(`[Offline]: ${msg}`, error); + DEBUG_BUILD && logger.info(`[Offline]: ${msg}`, error); } export interface OfflineStore { diff --git a/packages/feedback/src/debug-build.ts b/packages/feedback/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/feedback/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/feedback/src/integration.ts b/packages/feedback/src/integration.ts index 13f155d1ced5..6b1e0fb1b2c4 100644 --- a/packages/feedback/src/integration.ts +++ b/packages/feedback/src/integration.ts @@ -16,6 +16,7 @@ import { SUCCESS_MESSAGE_TEXT, WINDOW, } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import type { FeedbackInternalOptions, FeedbackWidget, OptionalFeedbackConfiguration } from './types'; import { mergeOptions } from './util/mergeOptions'; import { createActorStyles } from './widget/Actor.css'; @@ -173,7 +174,7 @@ export class Feedback implements Integration { this._createWidget(this.options); } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); } } @@ -218,7 +219,7 @@ export class Feedback implements Integration { typeof el === 'string' ? doc.querySelector(el) : typeof el.addEventListener === 'function' ? el : null; if (!targetEl) { - __DEBUG_BUILD__ && logger.error('[Feedback] Unable to attach to target element'); + DEBUG_BUILD && logger.error('[Feedback] Unable to attach to target element'); return null; } @@ -232,7 +233,7 @@ export class Feedback implements Integration { return widget; }); } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); return null; } } @@ -246,7 +247,7 @@ export class Feedback implements Integration { try { return this._createWidget(mergeOptions(this.options, optionOverrides || {})); } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); return null; } } @@ -273,7 +274,7 @@ export class Feedback implements Integration { return true; } } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); } return false; diff --git a/packages/feedback/src/util/handleFeedbackSubmit.ts b/packages/feedback/src/util/handleFeedbackSubmit.ts index eef28c8a2f29..abb3aeb1368d 100644 --- a/packages/feedback/src/util/handleFeedbackSubmit.ts +++ b/packages/feedback/src/util/handleFeedbackSubmit.ts @@ -2,6 +2,7 @@ import type { TransportMakeRequestResponse } from '@sentry/types'; import { logger } from '@sentry/utils'; import { FEEDBACK_WIDGET_SOURCE } from '../constants'; +import { DEBUG_BUILD } from '../debug-build'; import { sendFeedback } from '../sendFeedback'; import type { FeedbackFormData, SendFeedbackOptions } from '../types'; import type { DialogComponent } from '../widget/Dialog'; @@ -35,7 +36,7 @@ export async function handleFeedbackSubmit( // Success! return resp; } catch (err) { - __DEBUG_BUILD__ && logger.error(err); + DEBUG_BUILD && logger.error(err); showFetchError(); } } diff --git a/packages/integrations/src/debug-build.ts b/packages/integrations/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/integrations/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/integrations/src/dedupe.ts b/packages/integrations/src/dedupe.ts index 49865de3cd79..06ff147a76cb 100644 --- a/packages/integrations/src/dedupe.ts +++ b/packages/integrations/src/dedupe.ts @@ -1,6 +1,8 @@ import type { Event, Exception, Integration, StackFrame } from '@sentry/types'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + /** Deduplication filter */ export class Dedupe implements Integration { /** @@ -40,7 +42,7 @@ export class Dedupe implements Integration { // Juuust in case something goes wrong try { if (_shouldDropEvent(currentEvent, this._previousEvent)) { - __DEBUG_BUILD__ && logger.warn('Event dropped due to being a duplicate of previously captured event.'); + DEBUG_BUILD && logger.warn('Event dropped due to being a duplicate of previously captured event.'); return null; } } catch (_oO) { diff --git a/packages/integrations/src/extraerrordata.ts b/packages/integrations/src/extraerrordata.ts index 0ac2729e3baf..a5222fb84833 100644 --- a/packages/integrations/src/extraerrordata.ts +++ b/packages/integrations/src/extraerrordata.ts @@ -1,6 +1,8 @@ import type { Contexts, Event, EventHint, ExtendedError, Integration } from '@sentry/types'; import { addNonEnumerableProperty, isError, isPlainObject, logger, normalize } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + /** JSDoc */ interface ExtraErrorDataOptions { depth: number; @@ -127,7 +129,7 @@ function _extractErrorData(error: ExtendedError): Record | null return extraErrorInfo; } catch (oO) { - __DEBUG_BUILD__ && logger.error('Unable to extract extra data from the Error object:', oO); + DEBUG_BUILD && logger.error('Unable to extract extra data from the Error object:', oO); } return null; diff --git a/packages/integrations/src/httpclient.ts b/packages/integrations/src/httpclient.ts index 623b216e22fa..02918151817b 100644 --- a/packages/integrations/src/httpclient.ts +++ b/packages/integrations/src/httpclient.ts @@ -16,6 +16,8 @@ import { supportsNativeFetch, } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + export type HttpStatusCodeRange = [number, number] | number; export type HttpRequestTarget = string | RegExp; interface HttpClientOptions { @@ -113,7 +115,7 @@ export class HttpClient implements Integration { cookies = this._parseCookieString(cookieString); } } catch (e) { - __DEBUG_BUILD__ && logger.log(`Could not extract cookies from header ${cookieHeader}`); + DEBUG_BUILD && logger.log(`Could not extract cookies from header ${cookieHeader}`); } return { @@ -157,13 +159,13 @@ export class HttpClient implements Integration { responseCookies = this._parseCookieString(cookieString); } } catch (e) { - __DEBUG_BUILD__ && logger.log('Could not extract cookies from response headers'); + DEBUG_BUILD && logger.log('Could not extract cookies from response headers'); } try { responseHeaders = this._getXHRResponseHeaders(xhr); } catch (e) { - __DEBUG_BUILD__ && logger.log('Could not extract headers from response'); + DEBUG_BUILD && logger.log('Could not extract headers from response'); } requestHeaders = headers; @@ -333,7 +335,7 @@ export class HttpClient implements Integration { try { this._xhrResponseHandler(xhr, method, headers); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Error while extracting response event form XHR response', e); + DEBUG_BUILD && logger.warn('Error while extracting response event form XHR response', e); } }); } diff --git a/packages/integrations/src/offline.ts b/packages/integrations/src/offline.ts index bdb3d8324333..9708ffbdc050 100644 --- a/packages/integrations/src/offline.ts +++ b/packages/integrations/src/offline.ts @@ -5,6 +5,8 @@ import type { Event, EventProcessor, Hub, Integration } from '@sentry/types'; import { GLOBAL_OBJ, logger, normalize, uuid4 } from '@sentry/utils'; import localForage from 'localforage'; +import { DEBUG_BUILD } from './debug-build'; + const WINDOW = GLOBAL_OBJ as typeof GLOBAL_OBJ & Window; type LocalForage = { @@ -73,7 +75,7 @@ export class Offline implements Integration { if ('addEventListener' in WINDOW) { WINDOW.addEventListener('online', () => { void this._sendEvents().catch(() => { - __DEBUG_BUILD__ && logger.warn('could not send cached events'); + DEBUG_BUILD && logger.warn('could not send cached events'); }); }); } @@ -82,12 +84,12 @@ export class Offline implements Integration { if (this.hub && this.hub.getIntegration(Offline)) { // cache if we are positively offline if ('navigator' in WINDOW && 'onLine' in WINDOW.navigator && !WINDOW.navigator.onLine) { - __DEBUG_BUILD__ && logger.log('Event dropped due to being a offline - caching instead'); + DEBUG_BUILD && logger.log('Event dropped due to being a offline - caching instead'); void this._cacheEvent(event) .then((_event: Event): Promise => this._enforceMaxEvents()) .catch((_error): void => { - __DEBUG_BUILD__ && logger.warn('could not cache event while offline'); + DEBUG_BUILD && logger.warn('could not cache event while offline'); }); // return null on success or failure, because being offline will still result in an error @@ -104,7 +106,7 @@ export class Offline implements Integration { // if online now, send any events stored in a previous offline session if ('navigator' in WINDOW && 'onLine' in WINDOW.navigator && WINDOW.navigator.onLine) { void this._sendEvents().catch(() => { - __DEBUG_BUILD__ && logger.warn('could not send cached events'); + DEBUG_BUILD && logger.warn('could not send cached events'); }); } } @@ -140,7 +142,7 @@ export class Offline implements Integration { ), ) .catch((_error): void => { - __DEBUG_BUILD__ && logger.warn('could not enforce max events'); + DEBUG_BUILD && logger.warn('could not enforce max events'); }); } @@ -168,10 +170,10 @@ export class Offline implements Integration { this.hub.captureEvent(event); void this._purgeEvent(cacheKey).catch((_error): void => { - __DEBUG_BUILD__ && logger.warn('could not purge event from cache'); + DEBUG_BUILD && logger.warn('could not purge event from cache'); }); } else { - __DEBUG_BUILD__ && logger.warn('no hub found - could not send cached event'); + DEBUG_BUILD && logger.warn('no hub found - could not send cached event'); } }); } diff --git a/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts b/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts index c1f8bdc5ccfe..2f5995b8354b 100644 --- a/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts +++ b/packages/nextjs/src/client/routing/pagesRouterRoutingInstrumentation.ts @@ -11,6 +11,8 @@ import type { NEXT_DATA as NextData } from 'next/dist/next-server/lib/utils'; import { default as Router } from 'next/router'; import type { ParsedUrlQuery } from 'querystring'; +import { DEBUG_BUILD } from '../../common/debug-build'; + const globalObject = WINDOW as typeof WINDOW & { __BUILD_MANIFEST?: { sortedPages?: string[]; @@ -62,7 +64,7 @@ function extractNextDataTagInformation(): NextDataTagInfo { try { nextData = JSON.parse(nextDataTag.innerHTML); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Could not extract __NEXT_DATA__'); + DEBUG_BUILD && logger.warn('Could not extract __NEXT_DATA__'); } } diff --git a/packages/nextjs/src/client/tunnelRoute.ts b/packages/nextjs/src/client/tunnelRoute.ts index 6f10b190727a..6ac5fb50a640 100644 --- a/packages/nextjs/src/client/tunnelRoute.ts +++ b/packages/nextjs/src/client/tunnelRoute.ts @@ -1,6 +1,8 @@ import type { BrowserOptions } from '@sentry/react'; import { dsnFromString, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; + const globalWithInjectedValues = global as typeof global & { __sentryRewritesTunnelPath__?: string; }; @@ -20,9 +22,9 @@ export function applyTunnelRouteOption(options: BrowserOptions): void { const orgId = sentrySaasDsnMatch[1]; const tunnelPath = `${tunnelRouteOption}?o=${orgId}&p=${dsnComponents.projectId}`; options.tunnel = tunnelPath; - __DEBUG_BUILD__ && logger.info(`Tunneling events to "${tunnelPath}"`); + DEBUG_BUILD && logger.info(`Tunneling events to "${tunnelPath}"`); } else { - __DEBUG_BUILD__ && logger.warn('Provided DSN is not a Sentry SaaS DSN. Will not tunnel events.'); + DEBUG_BUILD && logger.warn('Provided DSN is not a Sentry SaaS DSN. Will not tunnel events.'); } } } diff --git a/packages/nextjs/src/common/debug-build.ts b/packages/nextjs/src/common/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/nextjs/src/common/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/nextjs/src/common/utils/edgeWrapperUtils.ts b/packages/nextjs/src/common/utils/edgeWrapperUtils.ts index bdf7b389fa00..72dc2f142365 100644 --- a/packages/nextjs/src/common/utils/edgeWrapperUtils.ts +++ b/packages/nextjs/src/common/utils/edgeWrapperUtils.ts @@ -9,6 +9,7 @@ import { } from '@sentry/utils'; import type { EdgeRouteHandler } from '../../edge/types'; +import { DEBUG_BUILD } from '../debug-build'; /** * Wraps a function on the edge runtime with error and performance monitoring. @@ -41,7 +42,7 @@ export function withEdgeWrapping( ); currentScope.setPropagationContext(propagationContext); if (traceparentData) { - __DEBUG_BUILD__ && logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`); + DEBUG_BUILD && logger.log(`[Tracing] Continuing trace ${traceparentData.traceId}.`); } span = startTransaction({ diff --git a/packages/nextjs/src/common/utils/responseEnd.ts b/packages/nextjs/src/common/utils/responseEnd.ts index 4cc31de89fb5..35f227261089 100644 --- a/packages/nextjs/src/common/utils/responseEnd.ts +++ b/packages/nextjs/src/common/utils/responseEnd.ts @@ -3,6 +3,7 @@ import type { Transaction } from '@sentry/types'; import { fill, logger } from '@sentry/utils'; import type { ServerResponse } from 'http'; +import { DEBUG_BUILD } from '../debug-build'; import type { ResponseEndMethod, WrappedResponseEndMethod } from '../types'; /** @@ -48,10 +49,10 @@ export async function finishTransaction(transaction: Transaction | undefined, re /** Flush the event queue to ensure that events get sent to Sentry before the response is finished and the lambda ends */ export async function flushQueue(): Promise { try { - __DEBUG_BUILD__ && logger.log('Flushing events...'); + DEBUG_BUILD && logger.log('Flushing events...'); await flush(2000); - __DEBUG_BUILD__ && logger.log('Done flushing events'); + DEBUG_BUILD && logger.log('Done flushing events'); } catch (e) { - __DEBUG_BUILD__ && logger.log('Error while flushing events:\n', e); + DEBUG_BUILD && logger.log('Error while flushing events:\n', e); } } diff --git a/packages/nextjs/src/common/withServerActionInstrumentation.ts b/packages/nextjs/src/common/withServerActionInstrumentation.ts index 8f458fc728a6..dcc1c7d29382 100644 --- a/packages/nextjs/src/common/withServerActionInstrumentation.ts +++ b/packages/nextjs/src/common/withServerActionInstrumentation.ts @@ -1,6 +1,7 @@ import { addTracingExtensions, captureException, flush, getCurrentHub, runWithAsyncContext, trace } from '@sentry/core'; import { logger, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { platformSupportsStreaming } from './utils/platformSupportsStreaming'; interface Options { @@ -60,7 +61,7 @@ async function withServerActionInstrumentationImplementation key in userOptions); if (sentryWebpackPluginOptionOverrides.length > 0) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( '[Sentry] You are overriding the following automatically-set SentryWebpackPlugin config options:\n' + `\t${sentryWebpackPluginOptionOverrides.toString()},\n` + diff --git a/packages/nextjs/src/server/index.ts b/packages/nextjs/src/server/index.ts index 822f2619d127..a672d814bc78 100644 --- a/packages/nextjs/src/server/index.ts +++ b/packages/nextjs/src/server/index.ts @@ -7,6 +7,7 @@ import type { IntegrationWithExclusionOption } from '@sentry/utils'; import { addOrUpdateIntegration, escapeStringForRegex, logger } from '@sentry/utils'; import * as path from 'path'; +import { DEBUG_BUILD } from '../common/debug-build'; import { devErrorSymbolicationEventProcessor } from '../common/devErrorSymbolicationEventProcessor'; import { getVercelEnv } from '../common/getVercelEnv'; import { buildMetadata } from '../common/metadata'; @@ -77,14 +78,14 @@ export function init(options: NodeOptions): void { autoSessionTracking: false, }; - if (__DEBUG_BUILD__ && opts.debug) { + if (DEBUG_BUILD && opts.debug) { logger.enable(); } - __DEBUG_BUILD__ && logger.log('Initializing SDK...'); + DEBUG_BUILD && logger.log('Initializing SDK...'); if (sdkAlreadyInitialized()) { - __DEBUG_BUILD__ && logger.log('SDK already initialized'); + DEBUG_BUILD && logger.log('SDK already initialized'); return; } @@ -113,7 +114,7 @@ export function init(options: NodeOptions): void { } }); - __DEBUG_BUILD__ && logger.log('SDK successfully initialized'); + DEBUG_BUILD && logger.log('SDK successfully initialized'); } function sdkAlreadyInitialized(): boolean { diff --git a/packages/node-experimental/src/debug-build.ts b/packages/node-experimental/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/node-experimental/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/node-experimental/src/sdk/initOtel.ts b/packages/node-experimental/src/sdk/initOtel.ts index 7b33df8431f1..285938b92c90 100644 --- a/packages/node-experimental/src/sdk/initOtel.ts +++ b/packages/node-experimental/src/sdk/initOtel.ts @@ -13,6 +13,7 @@ import { } from '@sentry/opentelemetry'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import type { NodeExperimentalClient } from '../types'; import { NodeExperimentalSentrySpanProcessor } from './spanProcessor'; @@ -23,7 +24,7 @@ export function initOtel(): void { const client = getClient(); if (!client) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'No client available, skipping OpenTelemetry setup. This probably means that `Sentry.init()` was not called before `initOtel()`.', ); diff --git a/packages/node/src/debug-build.ts b/packages/node/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/node/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/node/src/handlers.ts b/packages/node/src/handlers.ts index 1a75a76a20ab..339c9553bf26 100644 --- a/packages/node/src/handlers.ts +++ b/packages/node/src/handlers.ts @@ -25,6 +25,7 @@ import { import type * as http from 'http'; import type { NodeClient } from './client'; +import { DEBUG_BUILD } from './debug-build'; // TODO (v8 / XXX) Remove this import import type { ParseRequestOptions } from './requestDataDeprecated'; import { isAutoSessionTrackingEnabled } from './sdk'; @@ -178,7 +179,7 @@ export function requestHandler( _end.call(this, chunk, encoding, cb); }) .then(null, e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); _end.call(this, chunk, encoding, cb); }); }; diff --git a/packages/node/src/integrations/http.ts b/packages/node/src/integrations/http.ts index 4fd2e702bb44..be5f061e62e5 100644 --- a/packages/node/src/integrations/http.ts +++ b/packages/node/src/integrations/http.ts @@ -19,6 +19,7 @@ import type * as http from 'http'; import type * as https from 'https'; import type { NodeClient } from '../client'; +import { DEBUG_BUILD } from '../debug-build'; import { NODE_VERSION } from '../nodeVersion'; import type { RequestMethod, RequestMethodArgs, RequestOptions } from './utils/http'; import { cleanSpanDescription, extractRawUrl, extractUrl, normalizeRequestArgs } from './utils/http'; @@ -106,7 +107,7 @@ export class Http implements Integration { // Do not auto-instrument for other instrumenter if (clientOptions && clientOptions.instrumenter !== 'sentry') { - __DEBUG_BUILD__ && logger.log('HTTP Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('HTTP Integration is skipped because of instrumenter configuration.'); return; } @@ -271,7 +272,7 @@ function _createWrappedRequestMethodFactory( addHeadersToRequestOptions(requestOptions, requestUrl, sentryTraceHeader, dynamicSamplingContext); } } else { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Not adding sentry-trace header to outgoing request (${requestUrl}) due to mismatching tracePropagationTargets option.`, ); @@ -323,7 +324,7 @@ function addHeadersToRequestOptions( return; } - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log(`[Tracing] Adding sentry-trace header ${sentryTraceHeader} to outgoing request to "${requestUrl}": `); const sentryBaggage = dynamicSamplingContextToSentryBaggageHeader(dynamicSamplingContext); const sentryBaggageHeader = diff --git a/packages/node/src/integrations/onuncaughtexception.ts b/packages/node/src/integrations/onuncaughtexception.ts index b1699f464960..9fcd2fe5fa26 100644 --- a/packages/node/src/integrations/onuncaughtexception.ts +++ b/packages/node/src/integrations/onuncaughtexception.ts @@ -4,6 +4,7 @@ import type { Integration } from '@sentry/types'; import { logger } from '@sentry/utils'; import type { NodeClient } from '../client'; +import { DEBUG_BUILD } from '../debug-build'; import { logAndExitProcess } from './utils/errorhandling'; type OnFatalErrorHandler = (firstError: Error, secondError?: Error) => void; @@ -148,7 +149,7 @@ export class OnUncaughtException implements Integration { if (shouldApplyFatalHandlingLogic) { if (calledFatalError) { // we hit an error *after* calling onFatalError - pretty boned at this point, just shut it down - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'uncaught exception after calling fatal error shutdown callback - this is bad! forcing shutdown', ); diff --git a/packages/node/src/integrations/utils/errorhandling.ts b/packages/node/src/integrations/utils/errorhandling.ts index e3f03f064421..86d55c2c8086 100644 --- a/packages/node/src/integrations/utils/errorhandling.ts +++ b/packages/node/src/integrations/utils/errorhandling.ts @@ -2,6 +2,7 @@ import { getClient } from '@sentry/core'; import { logger } from '@sentry/utils'; import type { NodeClient } from '../../client'; +import { DEBUG_BUILD } from '../../debug-build'; const DEFAULT_SHUTDOWN_TIMEOUT = 2000; @@ -15,7 +16,7 @@ export function logAndExitProcess(error: Error): void { const client = getClient(); if (client === undefined) { - __DEBUG_BUILD__ && logger.warn('No NodeClient was defined, we are exiting the process now.'); + DEBUG_BUILD && logger.warn('No NodeClient was defined, we are exiting the process now.'); global.process.exit(1); } @@ -26,12 +27,12 @@ export function logAndExitProcess(error: Error): void { client.close(timeout).then( (result: boolean) => { if (!result) { - __DEBUG_BUILD__ && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); + DEBUG_BUILD && logger.warn('We reached the timeout for emptying the request buffer, still exiting now!'); } global.process.exit(1); }, error => { - __DEBUG_BUILD__ && logger.error(error); + DEBUG_BUILD && logger.error(error); }, ); } diff --git a/packages/opentelemetry-node/src/debug-build.ts b/packages/opentelemetry-node/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/opentelemetry-node/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/opentelemetry-node/src/spanprocessor.ts b/packages/opentelemetry-node/src/spanprocessor.ts index 98ab46c405cb..571871e1e3f0 100644 --- a/packages/opentelemetry-node/src/spanprocessor.ts +++ b/packages/opentelemetry-node/src/spanprocessor.ts @@ -7,6 +7,7 @@ import type { DynamicSamplingContext, Span as SentrySpan, TraceparentData, Trans import { logger } from '@sentry/utils'; import { SENTRY_DYNAMIC_SAMPLING_CONTEXT_KEY, SENTRY_TRACE_PARENT_CONTEXT_KEY } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import { maybeCaptureExceptionForTimedEvent } from './utils/captureExceptionForTimedEvent'; import { isSentryRequestSpan } from './utils/isSentryRequest'; import { mapOtelStatus } from './utils/mapOtelStatus'; @@ -85,8 +86,7 @@ export class SentrySpanProcessor implements OtelSpanProcessor { const sentrySpan = getSentrySpan(otelSpanId); if (!sentrySpan) { - __DEBUG_BUILD__ && - logger.error(`SentrySpanProcessor could not find span with OTEL-spanId ${otelSpanId} to finish.`); + DEBUG_BUILD && logger.error(`SentrySpanProcessor could not find span with OTEL-spanId ${otelSpanId} to finish.`); clearSpan(otelSpanId); return; } diff --git a/packages/opentelemetry/src/custom/scope.ts b/packages/opentelemetry/src/custom/scope.ts index 9c544b018134..b65aa437b14f 100644 --- a/packages/opentelemetry/src/custom/scope.ts +++ b/packages/opentelemetry/src/custom/scope.ts @@ -4,6 +4,7 @@ import { Scope } from '@sentry/core'; import type { Breadcrumb, SeverityLevel, Span as SentrySpan } from '@sentry/types'; import { dateTimestampInSeconds, dropUndefinedKeys, logger, normalize } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { InternalSentrySemanticAttributes } from '../semanticAttributes'; import { convertOtelTimeToSeconds } from '../utils/convertOtelTimeToSeconds'; import { getActiveSpan, getRootSpan } from '../utils/getActiveSpan'; @@ -48,8 +49,7 @@ export class OpenTelemetryScope extends Scope { * Instead, use the global `getActiveSpan()`. */ public getSpan(): undefined { - __DEBUG_BUILD__ && - logger.warn('Calling getSpan() is a noop in @sentry/opentelemetry. Use `getActiveSpan()` instead.'); + DEBUG_BUILD && logger.warn('Calling getSpan() is a noop in @sentry/opentelemetry. Use `getActiveSpan()` instead.'); return undefined; } @@ -59,7 +59,7 @@ export class OpenTelemetryScope extends Scope { * Instead, use the global `startSpan()` to define the active span. */ public setSpan(_span: SentrySpan): this { - __DEBUG_BUILD__ && logger.warn('Calling setSpan() is a noop in @sentry/opentelemetry. Use `startSpan()` instead.'); + DEBUG_BUILD && logger.warn('Calling setSpan() is a noop in @sentry/opentelemetry. Use `startSpan()` instead.'); return this; } diff --git a/packages/opentelemetry/src/debug-build.ts b/packages/opentelemetry/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/opentelemetry/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/opentelemetry/src/sampler.ts b/packages/opentelemetry/src/sampler.ts index 03f82f100a87..f07dc4f8f1e4 100644 --- a/packages/opentelemetry/src/sampler.ts +++ b/packages/opentelemetry/src/sampler.ts @@ -7,6 +7,7 @@ import { hasTracingEnabled } from '@sentry/core'; import type { Client, ClientOptions, SamplingContext } from '@sentry/types'; import { isNaN, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { InternalSentrySemanticAttributes } from './semanticAttributes'; import { getPropagationContextFromContext } from './utils/contextData'; @@ -44,12 +45,11 @@ export class SentrySampler implements Sampler { if (parentContext && isSpanContextValid(parentContext) && parentContext.traceId === traceId) { if (parentContext.isRemote) { parentSampled = getParentRemoteSampled(parentContext, context); - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log(`[Tracing] Inheriting remote parent's sampled decision for ${spanName}: ${parentSampled}`); } else { parentSampled = Boolean(parentContext.traceFlags & TraceFlags.SAMPLED); - __DEBUG_BUILD__ && - logger.log(`[Tracing] Inheriting parent's sampled decision for ${spanName}: ${parentSampled}`); + DEBUG_BUILD && logger.log(`[Tracing] Inheriting parent's sampled decision for ${spanName}: ${parentSampled}`); } } @@ -72,7 +72,7 @@ export class SentrySampler implements Sampler { // 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)) { - __DEBUG_BUILD__ && logger.warn('[Tracing] Discarding span because of invalid sample rate.'); + DEBUG_BUILD && logger.warn('[Tracing] Discarding span because of invalid sample rate.'); return { decision: SamplingDecision.NOT_RECORD, @@ -82,7 +82,7 @@ export class SentrySampler implements Sampler { // if the function returned 0 (or false), or if `tracesSampleRate` is 0, it's a sign the transaction should be dropped if (!sampleRate) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding span because ${ typeof options.tracesSampler === 'function' @@ -103,7 +103,7 @@ export class SentrySampler implements Sampler { // if we're not going to keep it, we're done if (!isSampled) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Discarding span because it's not included in the random sample (sampling rate = ${Number( sampleRate, @@ -159,7 +159,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')) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Tracing] Given sample rate is invalid. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, @@ -170,7 +170,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) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`[Tracing] Given sample rate is invalid. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } diff --git a/packages/opentelemetry/src/spanExporter.ts b/packages/opentelemetry/src/spanExporter.ts index f2094d132733..d3c3b5b3da90 100644 --- a/packages/opentelemetry/src/spanExporter.ts +++ b/packages/opentelemetry/src/spanExporter.ts @@ -12,6 +12,7 @@ import { getCurrentHub } from './custom/hub'; import { OpenTelemetryScope } from './custom/scope'; import type { OpenTelemetryTransaction } from './custom/transaction'; import { startTransaction } from './custom/transaction'; +import { DEBUG_BUILD } from './debug-build'; import { InternalSentrySemanticAttributes } from './semanticAttributes'; import { convertOtelTimeToSeconds } from './utils/convertOtelTimeToSeconds'; import { getRequestSpanData } from './utils/getRequestSpanData'; @@ -54,12 +55,12 @@ export class SentrySpanExporter implements SpanExporter { const remainingOpenSpanCount = remainingSpans.length; const sentSpanCount = openSpanCount + newSpanCount - remainingOpenSpanCount; - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log(`SpanExporter exported ${sentSpanCount} spans, ${remainingOpenSpanCount} unsent spans remaining`); this._finishedSpans = remainingSpans.filter(span => { const shouldDrop = shouldCleanupSpan(span, 5 * 60); - __DEBUG_BUILD__ && + DEBUG_BUILD && shouldDrop && logger.log( `SpanExporter dropping span ${span.name} (${ diff --git a/packages/opentelemetry/src/spanProcessor.ts b/packages/opentelemetry/src/spanProcessor.ts index dc8bf53cf83f..a2d7de69fb00 100644 --- a/packages/opentelemetry/src/spanProcessor.ts +++ b/packages/opentelemetry/src/spanProcessor.ts @@ -5,6 +5,7 @@ import { BatchSpanProcessor } from '@opentelemetry/sdk-trace-base'; import { logger } from '@sentry/utils'; import { getCurrentHub } from './custom/hub'; +import { DEBUG_BUILD } from './debug-build'; import { SentrySpanExporter } from './spanExporter'; import { maybeCaptureExceptionForTimedEvent } from './utils/captureExceptionForTimedEvent'; import { getHubFromContext } from './utils/contextData'; @@ -57,14 +58,14 @@ export class SentrySpanProcessor extends BatchSpanProcessor implements SpanProce public onStart(span: Span, parentContext: Context): void { onSpanStart(span, parentContext); - __DEBUG_BUILD__ && logger.log(`[Tracing] Starting span "${span.name}" (${span.spanContext().spanId})`); + DEBUG_BUILD && logger.log(`[Tracing] Starting span "${span.name}" (${span.spanContext().spanId})`); return super.onStart(span, parentContext); } /** @inheritDoc */ public onEnd(span: Span): void { - __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing span "${span.name}" (${span.spanContext().spanId})`); + DEBUG_BUILD && logger.log(`[Tracing] Finishing span "${span.name}" (${span.spanContext().spanId})`); if (!this._shouldSendSpanToSentry(span)) { // Prevent this being called to super.onEnd(), which would pass this to the span exporter diff --git a/packages/opentelemetry/test/helpers/initOtel.ts b/packages/opentelemetry/test/helpers/initOtel.ts index 91be948b2f9d..e69420242a09 100644 --- a/packages/opentelemetry/test/helpers/initOtel.ts +++ b/packages/opentelemetry/test/helpers/initOtel.ts @@ -8,6 +8,7 @@ import { logger } from '@sentry/utils'; import { wrapContextManagerClass } from '../../src/contextManager'; import { getCurrentHub } from '../../src/custom/hub'; +import { DEBUG_BUILD } from '../../src/debug-build'; import { SentryPropagator } from '../../src/propagator'; import { SentrySampler } from '../../src/sampler'; import { setupEventContextTrace } from '../../src/setupEventContextTrace'; @@ -21,7 +22,7 @@ export function initOtel(): void { const client = getCurrentHub().getClient(); if (!client) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'No client available, skipping OpenTelemetry setup. This probably means that `Sentry.init()` was not called before `initOtel()`.', ); diff --git a/packages/react/src/debug-build.ts b/packages/react/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/react/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/react/src/errorboundary.tsx b/packages/react/src/errorboundary.tsx index 61dd976050f6..dacc30b5d85a 100644 --- a/packages/react/src/errorboundary.tsx +++ b/packages/react/src/errorboundary.tsx @@ -4,6 +4,8 @@ import { isError, logger } from '@sentry/utils'; import hoistNonReactStatics from 'hoist-non-react-statics'; import * as React from 'react'; +import { DEBUG_BUILD } from './debug-build'; + export function isAtLeastReact17(version: string): boolean { const major = version.match(/^([^.]+)/); return major !== null && parseInt(major[0]) >= 17; @@ -208,7 +210,7 @@ class ErrorBoundary extends React.Component, R !_matchRoutes || !_customStartTransaction ) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`reactRouterV6Instrumentation was unable to wrap Routes because of one or more missing parameters. useEffect: ${_useEffect}. useLocation: ${_useLocation}. useNavigationType: ${_useNavigationType}. createRoutesFromChildren: ${_createRoutesFromChildren}. matchRoutes: ${_matchRoutes}. customStartTransaction: ${_customStartTransaction}.`); @@ -218,7 +219,7 @@ export function withSentryReactRouterV6Routing

, R export function wrapUseRoutes(origUseRoutes: UseRoutes): UseRoutes { if (!_useEffect || !_useLocation || !_useNavigationType || !_matchRoutes || !_customStartTransaction) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( 'reactRouterV6Instrumentation was unable to wrap `useRoutes` because of one or more missing parameters.', ); diff --git a/packages/remix/src/client/performance.tsx b/packages/remix/src/client/performance.tsx index 97c455a80a94..2e597d10fa2b 100644 --- a/packages/remix/src/client/performance.tsx +++ b/packages/remix/src/client/performance.tsx @@ -4,6 +4,7 @@ import type { Transaction, TransactionContext } from '@sentry/types'; import { isNodeEnv, logger } from '@sentry/utils'; import * as React from 'react'; +import { DEBUG_BUILD } from '../utils/debug-build'; import { getFutureFlagsBrowser, readRemixVersionFromLoader } from '../utils/futureFlags'; const DEFAULT_TAGS = { @@ -108,7 +109,7 @@ export function withSentry

, R extends React.Co const SentryRoot: React.FC

= (props: P) => { // Early return when any of the required functions is not available. if (!_useEffect || !_useLocation || !_useMatches || !_customStartTransaction) { - __DEBUG_BUILD__ && + DEBUG_BUILD && !isNodeEnv() && logger.warn('Remix SDK was unable to wrap your root because of one or more missing parameters.'); diff --git a/packages/remix/src/index.server.ts b/packages/remix/src/index.server.ts index 80c6602e4938..747634603bc0 100644 --- a/packages/remix/src/index.server.ts +++ b/packages/remix/src/index.server.ts @@ -3,6 +3,7 @@ import type { NodeOptions } from '@sentry/node'; import { configureScope, getCurrentHub, init as nodeInit } from '@sentry/node'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './utils/debug-build'; import { instrumentServer } from './utils/instrumentServer'; import { buildMetadata } from './utils/metadata'; import type { RemixOptions } from './utils/remixOptions'; @@ -75,7 +76,7 @@ export function init(options: RemixOptions): void { buildMetadata(options, ['remix', 'node']); if (sdkAlreadyInitialized()) { - __DEBUG_BUILD__ && logger.log('SDK already initialized'); + DEBUG_BUILD && logger.log('SDK already initialized'); return; } diff --git a/packages/remix/src/utils/debug-build.ts b/packages/remix/src/utils/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/remix/src/utils/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/remix/src/utils/instrumentServer.ts b/packages/remix/src/utils/instrumentServer.ts index 935e24124b49..b6eff804156c 100644 --- a/packages/remix/src/utils/instrumentServer.ts +++ b/packages/remix/src/utils/instrumentServer.ts @@ -13,6 +13,7 @@ import { tracingContextFromHeaders, } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; import { getFutureFlagsServer, getRemixVersionFromBuild } from './futureFlags'; import { extractData, @@ -96,7 +97,7 @@ export async function captureRemixServerException(err: unknown, name: string, re // eslint-disable-next-line @typescript-eslint/no-explicit-any normalizedRequest = normalizeRemixRequest(request as unknown as any); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Failed to normalize Remix request'); + DEBUG_BUILD && logger.warn('Failed to normalize Remix request'); } captureException(isResponse(err) ? await extractResponseError(err) : err, scope => { @@ -271,8 +272,7 @@ function makeWrappedRootLoader(remixVersion: number) { // We skip injection of trace and baggage in those cases. // For `redirect`, a valid internal redirection target will have the trace and baggage injected. if (isRedirectResponse(res) || isCatchResponse(res)) { - __DEBUG_BUILD__ && - logger.warn('Skipping injection of trace and baggage as the response does not have a body'); + DEBUG_BUILD && logger.warn('Skipping injection of trace and baggage as the response does not have a body'); return res; } else { const data = await extractData(res); @@ -283,8 +283,7 @@ function makeWrappedRootLoader(remixVersion: number) { { headers: res.headers, statusText: res.statusText, status: res.status }, ); } else { - __DEBUG_BUILD__ && - logger.warn('Skipping injection of trace and baggage as the response body is not an object'); + DEBUG_BUILD && logger.warn('Skipping injection of trace and baggage as the response body is not an object'); return res; } } @@ -381,7 +380,7 @@ function wrapRequestHandler(origRequestHandler: RequestHandler, build: ServerBui try { normalizedRequest = normalizeRemixRequest(request); } catch (e) { - __DEBUG_BUILD__ && logger.warn('Failed to normalize Remix request'); + DEBUG_BUILD && logger.warn('Failed to normalize Remix request'); } const url = new URL(request.url); @@ -495,7 +494,7 @@ export function instrumentServer(): void { const pkg = loadModule<{ createRequestHandler: CreateRequestHandlerFunction }>('@remix-run/server-runtime'); if (!pkg) { - __DEBUG_BUILD__ && logger.warn('Remix SDK was unable to require `@remix-run/server-runtime` package.'); + DEBUG_BUILD && logger.warn('Remix SDK was unable to require `@remix-run/server-runtime` package.'); return; } diff --git a/packages/remix/src/utils/serverAdapters/express.ts b/packages/remix/src/utils/serverAdapters/express.ts index 78affeaaa9ac..ab638866ffd4 100644 --- a/packages/remix/src/utils/serverAdapters/express.ts +++ b/packages/remix/src/utils/serverAdapters/express.ts @@ -4,6 +4,7 @@ import type { Transaction } from '@sentry/types'; import { extractRequestData, isString, logger } from '@sentry/utils'; import { cwd } from 'process'; +import { DEBUG_BUILD } from '../debug-build'; import { createRoutes, getTransactionName, @@ -48,7 +49,7 @@ function wrapExpressRequestHandler( pkg = await import(`${cwd()}/node_modules/react-router-dom`); } finally { if (!pkg) { - __DEBUG_BUILD__ && logger.error('Could not find `react-router-dom` package.'); + DEBUG_BUILD && logger.error('Could not find `react-router-dom` package.'); } } } @@ -151,10 +152,10 @@ async function finishSentryProcessing(res: AugmentedExpressResponse): Promise { // If this is false, it means session is expired, create and a new session and wait for checkout if (!replay.checkAndHandleExpiredSession()) { - __DEBUG_BUILD__ && logger.warn('[Replay] Received replay event after session expired.'); + DEBUG_BUILD && logger.warn('[Replay] Received replay event after session expired.'); return; } diff --git a/packages/replay/src/util/log.ts b/packages/replay/src/util/log.ts index 9aa650a81264..96b6e76dc498 100644 --- a/packages/replay/src/util/log.ts +++ b/packages/replay/src/util/log.ts @@ -1,11 +1,13 @@ import { getCurrentHub } from '@sentry/core'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; + /** * Log a message in debug mode, and add a breadcrumb when _experiment.traceInternals is enabled. */ export function logInfo(message: string, shouldAddBreadcrumb?: boolean): void { - if (!__DEBUG_BUILD__) { + if (!DEBUG_BUILD) { return; } @@ -21,7 +23,7 @@ export function logInfo(message: string, shouldAddBreadcrumb?: boolean): void { * This is necessary when the breadcrumb may be added before the replay is initialized. */ export function logInfoNextTick(message: string, shouldAddBreadcrumb?: boolean): void { - if (!__DEBUG_BUILD__) { + if (!DEBUG_BUILD) { return; } diff --git a/packages/replay/src/util/sendReplay.ts b/packages/replay/src/util/sendReplay.ts index 645a6573e727..9aea14be4a16 100644 --- a/packages/replay/src/util/sendReplay.ts +++ b/packages/replay/src/util/sendReplay.ts @@ -1,6 +1,7 @@ import { captureException, setContext } from '@sentry/core'; import { RETRY_BASE_INTERVAL, RETRY_MAX_COUNT, UNABLE_TO_SEND_REPLAY } from '../constants'; +import { DEBUG_BUILD } from '../debug-build'; import type { SendReplayData } from '../types'; import { RateLimitError, sendReplayRequest, TransportStatusCodeError } from './sendReplayRequest'; @@ -34,7 +35,7 @@ export async function sendReplay( _retryCount: retryConfig.count, }); - if (__DEBUG_BUILD__ && options._experiments && options._experiments.captureExceptions) { + if (DEBUG_BUILD && options._experiments && options._experiments.captureExceptions) { captureException(err); } diff --git a/packages/replay/src/util/shouldFilterRequest.ts b/packages/replay/src/util/shouldFilterRequest.ts index fcfd75b1b048..274ad4ee488a 100644 --- a/packages/replay/src/util/shouldFilterRequest.ts +++ b/packages/replay/src/util/shouldFilterRequest.ts @@ -1,5 +1,6 @@ import { getCurrentHub, isSentryRequestUrl } from '@sentry/core'; +import { DEBUG_BUILD } from '../debug-build'; import type { ReplayContainer } from '../types'; /** @@ -8,7 +9,7 @@ import type { ReplayContainer } from '../types'; */ export function shouldFilterRequest(replay: ReplayContainer, url: string): boolean { // If we enabled the `traceInternals` experiment, we want to trace everything - if (__DEBUG_BUILD__ && replay.getOptions()._experiments.traceInternals) { + if (DEBUG_BUILD && replay.getOptions()._experiments.traceInternals) { return false; } diff --git a/packages/serverless/src/awslambda.ts b/packages/serverless/src/awslambda.ts index 78578083ee72..97dec35a6113 100644 --- a/packages/serverless/src/awslambda.ts +++ b/packages/serverless/src/awslambda.ts @@ -14,6 +14,7 @@ import { performance } from 'perf_hooks'; import { types } from 'util'; import { AWSServices } from './awsservices'; +import { DEBUG_BUILD } from './debug-build'; import { markEventUnhandled } from './utils'; export * from '@sentry/node'; @@ -131,7 +132,7 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { const handlerDesc = basename(handlerPath); const match = handlerDesc.match(/^([^.]*)\.(.*)$/); if (!match) { - __DEBUG_BUILD__ && logger.error(`Bad handler ${handlerDesc}`); + DEBUG_BUILD && logger.error(`Bad handler ${handlerDesc}`); return; } @@ -142,7 +143,7 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { const handlerDir = handlerPath.substring(0, handlerPath.indexOf(handlerDesc)); obj = tryRequire(taskRoot, handlerDir, handlerMod); } catch (e) { - __DEBUG_BUILD__ && logger.error(`Cannot require ${handlerPath} in ${taskRoot}`, e); + DEBUG_BUILD && logger.error(`Cannot require ${handlerPath} in ${taskRoot}`, e); return; } @@ -154,11 +155,11 @@ export function tryPatchHandler(taskRoot: string, handlerPath: string): void { functionName = name; }); if (!obj) { - __DEBUG_BUILD__ && logger.error(`${handlerPath} is undefined or not exported`); + DEBUG_BUILD && logger.error(`${handlerPath} is undefined or not exported`); return; } if (typeof obj !== 'function') { - __DEBUG_BUILD__ && logger.error(`${handlerPath} is not a function`); + DEBUG_BUILD && logger.error(`${handlerPath} is not a function`); return; } @@ -345,7 +346,7 @@ export function wrapHandler( transaction?.finish(); hub.popScope(); await flush(options.flushTimeout).catch(e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }); } return rv; diff --git a/packages/serverless/src/debug-build.ts b/packages/serverless/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/serverless/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/serverless/src/gcpfunction/cloud_events.ts b/packages/serverless/src/gcpfunction/cloud_events.ts index a0d843e71abe..05595867c191 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 } from '@sentry/node'; import { isThenable, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { domainify, markEventUnhandled, proxyFunction } from '../utils'; import type { CloudEventFunction, CloudEventFunctionWithCallback, WrapperOptions } from './general'; @@ -56,7 +57,7 @@ function _wrapCloudEventFunction( void flush(options.flushTimeout) .then(null, e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }) .then(() => { callback(...args); diff --git a/packages/serverless/src/gcpfunction/events.ts b/packages/serverless/src/gcpfunction/events.ts index 9c98fcb8c485..c3be42c6a6c2 100644 --- a/packages/serverless/src/gcpfunction/events.ts +++ b/packages/serverless/src/gcpfunction/events.ts @@ -1,6 +1,7 @@ import { captureException, flush, getCurrentHub } from '@sentry/node'; import { isThenable, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { domainify, markEventUnhandled, proxyFunction } from '../utils'; import type { EventFunction, EventFunctionWithCallback, WrapperOptions } from './general'; @@ -58,7 +59,7 @@ function _wrapEventFunction void flush(options.flushTimeout) .then(null, e => { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }) .then(() => { if (typeof callback === 'function') { diff --git a/packages/serverless/src/gcpfunction/http.ts b/packages/serverless/src/gcpfunction/http.ts index eea492bb8dab..8f4a77099696 100644 --- a/packages/serverless/src/gcpfunction/http.ts +++ b/packages/serverless/src/gcpfunction/http.ts @@ -2,6 +2,7 @@ import type { AddRequestDataToEventOptions } from '@sentry/node'; import { captureException, flush, getCurrentHub } from '@sentry/node'; import { isString, isThenable, logger, stripUrlQueryAndFragment, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from '../debug-build'; import { domainify, markEventUnhandled, proxyFunction } from './../utils'; import type { HttpFunction, WrapperOptions } from './general'; @@ -111,7 +112,7 @@ function _wrapHttpFunction(fn: HttpFunction, wrapOptions: Partial { - __DEBUG_BUILD__ && logger.error(e); + DEBUG_BUILD && logger.error(e); }) .then(() => { _end.call(this, chunk, encoding, cb); diff --git a/packages/sveltekit/src/common/debug-build.ts b/packages/sveltekit/src/common/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/sveltekit/src/common/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/sveltekit/src/server/utils.ts b/packages/sveltekit/src/server/utils.ts index cf591568486b..719771d50c57 100644 --- a/packages/sveltekit/src/server/utils.ts +++ b/packages/sveltekit/src/server/utils.ts @@ -3,6 +3,7 @@ import type { StackFrame } from '@sentry/types'; import { basename, escapeStringForRegex, GLOBAL_OBJ, join, logger, tracingContextFromHeaders } from '@sentry/utils'; import type { RequestEvent } from '@sveltejs/kit'; +import { DEBUG_BUILD } from '../common/debug-build'; import { WRAPPED_MODULE_SUFFIX } from '../vite/autoInstrument'; import type { GlobalWithSentryValues } from '../vite/injectGlobalValues'; @@ -76,11 +77,11 @@ export async function flushIfServerless(): Promise { if (!platformSupportsStreaming) { try { - __DEBUG_BUILD__ && logger.log('Flushing events...'); + DEBUG_BUILD && logger.log('Flushing events...'); await flush(2000); - __DEBUG_BUILD__ && logger.log('Done flushing events'); + DEBUG_BUILD && logger.log('Done flushing events'); } catch (e) { - __DEBUG_BUILD__ && logger.log('Error while flushing events:\n', e); + DEBUG_BUILD && logger.log('Error while flushing events:\n', e); } } } diff --git a/packages/tracing-internal/src/browser/backgroundtab.ts b/packages/tracing-internal/src/browser/backgroundtab.ts index e061f39925a1..7d65941c8d43 100644 --- a/packages/tracing-internal/src/browser/backgroundtab.ts +++ b/packages/tracing-internal/src/browser/backgroundtab.ts @@ -2,6 +2,7 @@ import type { IdleTransaction, SpanStatusType } from '@sentry/core'; import { getActiveTransaction } from '@sentry/core'; import { logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { WINDOW } from './types'; /** @@ -15,7 +16,7 @@ export function registerBackgroundTabDetection(): void { if (WINDOW.document.hidden && activeTransaction) { const statusType: SpanStatusType = 'cancelled'; - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.log( `[Tracing] Transaction: ${statusType} -> since tab moved to the background, op: ${activeTransaction.op}`, ); @@ -29,7 +30,6 @@ export function registerBackgroundTabDetection(): void { } }); } else { - __DEBUG_BUILD__ && - logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); + DEBUG_BUILD && logger.warn('[Tracing] Could not set up background tab detection due to lack of global document'); } } diff --git a/packages/tracing-internal/src/browser/browsertracing.ts b/packages/tracing-internal/src/browser/browsertracing.ts index a11ea7ff2cf2..f1ee79c39679 100644 --- a/packages/tracing-internal/src/browser/browsertracing.ts +++ b/packages/tracing-internal/src/browser/browsertracing.ts @@ -4,6 +4,7 @@ import { addTracingExtensions, getActiveTransaction, startIdleTransaction, TRACI import type { EventProcessor, Integration, Transaction, TransactionContext, TransactionSource } from '@sentry/types'; import { getDomElement, logger, tracingContextFromHeaders } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { registerBackgroundTabDetection } from './backgroundtab'; import { addPerformanceEntries, @@ -179,7 +180,7 @@ export class BrowserTracing implements Integration { addTracingExtensions(); - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { this._hasSetTracePropagationTargets = !!( _options && // eslint-disable-next-line deprecation/deprecation @@ -250,7 +251,7 @@ export class BrowserTracing implements Integration { // If both 1 and either one of 2 or 3 are set (from above), we log out a warning. // eslint-disable-next-line deprecation/deprecation const tracePropagationTargets = clientOptionsTracePropagationTargets || this.options.tracePropagationTargets; - if (__DEBUG_BUILD__ && this._hasSetTracePropagationTargets && clientOptionsTracePropagationTargets) { + if (DEBUG_BUILD && this._hasSetTracePropagationTargets && clientOptionsTracePropagationTargets) { logger.warn( '[Tracing] The `tracePropagationTargets` option was set in the BrowserTracing integration and top level `Sentry.init`. The top level `Sentry.init` value is being used.', ); @@ -289,7 +290,7 @@ export class BrowserTracing implements Integration { /** Create routing idle transaction. */ private _createRouteTransaction(context: TransactionContext): Transaction | undefined { if (!this._getCurrentHub) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${context.op} transaction because _getCurrentHub is invalid.`); return undefined; } @@ -333,11 +334,10 @@ export class BrowserTracing implements Integration { this._latestRouteSource = finalContext.metadata && finalContext.metadata.source; if (finalContext.sampled === false) { - __DEBUG_BUILD__ && - logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); + DEBUG_BUILD && logger.log(`[Tracing] Will not send ${finalContext.op} transaction because of beforeNavigate.`); } - __DEBUG_BUILD__ && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); + DEBUG_BUILD && logger.log(`[Tracing] Starting ${finalContext.op} transaction on scope`); const { location } = WINDOW; @@ -385,7 +385,7 @@ export class BrowserTracing implements Integration { const currentTransaction = getActiveTransaction(); if (currentTransaction && currentTransaction.op && ['navigation', 'pageload'].includes(currentTransaction.op)) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `[Tracing] Did not create ${op} transaction because a pageload or navigation transaction is in progress.`, ); @@ -399,13 +399,12 @@ export class BrowserTracing implements Integration { } if (!this._getCurrentHub) { - __DEBUG_BUILD__ && logger.warn(`[Tracing] Did not create ${op} transaction because _getCurrentHub is invalid.`); + DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _getCurrentHub is invalid.`); return undefined; } if (!this._latestRouteName) { - __DEBUG_BUILD__ && - logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`); + DEBUG_BUILD && logger.warn(`[Tracing] Did not create ${op} transaction because _latestRouteName is missing.`); return undefined; } diff --git a/packages/tracing-internal/src/browser/instrument.ts b/packages/tracing-internal/src/browser/instrument.ts index 85c2aeccb43e..ae4532259f94 100644 --- a/packages/tracing-internal/src/browser/instrument.ts +++ b/packages/tracing-internal/src/browser/instrument.ts @@ -1,5 +1,6 @@ import { getFunctionName, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { onCLS } from './web-vitals/getCLS'; import { onFID } from './web-vitals/getFID'; import { onLCP } from './web-vitals/getLCP'; @@ -148,7 +149,7 @@ function triggerHandlers(type: InstrumentHandlerType, data: unknown): void { try { handler(data); } catch (e) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error( `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`, e, diff --git a/packages/tracing-internal/src/browser/metrics/index.ts b/packages/tracing-internal/src/browser/metrics/index.ts index 4d28f6102cde..c7a37a210d80 100644 --- a/packages/tracing-internal/src/browser/metrics/index.ts +++ b/packages/tracing-internal/src/browser/metrics/index.ts @@ -4,6 +4,7 @@ import { getActiveTransaction } from '@sentry/core'; import type { Measurements } from '@sentry/types'; import { browserPerformanceTimeOrigin, htmlTreeAsString, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import { addClsInstrumentationHandler, addFidInstrumentationHandler, @@ -121,7 +122,7 @@ function _trackCLS(): () => void { return; } - __DEBUG_BUILD__ && logger.log('[Measurements] Adding CLS'); + DEBUG_BUILD && logger.log('[Measurements] Adding CLS'); _measurements['cls'] = { value: metric.value, unit: '' }; _clsEntry = entry as LayoutShift; }); @@ -135,7 +136,7 @@ function _trackLCP(): () => void { return; } - __DEBUG_BUILD__ && logger.log('[Measurements] Adding LCP'); + DEBUG_BUILD && logger.log('[Measurements] Adding LCP'); _measurements['lcp'] = { value: metric.value, unit: 'millisecond' }; _lcpEntry = entry as LargestContentfulPaint; }); @@ -151,7 +152,7 @@ function _trackFID(): () => void { const timeOrigin = msToSec(browserPerformanceTimeOrigin as number); const startTime = msToSec(entry.startTime); - __DEBUG_BUILD__ && logger.log('[Measurements] Adding FID'); + DEBUG_BUILD && logger.log('[Measurements] Adding FID'); _measurements['fid'] = { value: metric.value, unit: 'millisecond' }; _measurements['mark.fid'] = { value: timeOrigin + startTime, unit: 'second' }; }); @@ -165,7 +166,7 @@ export function addPerformanceEntries(transaction: Transaction): void { return; } - __DEBUG_BUILD__ && logger.log('[Tracing] Adding & adjusting spans using Performance API'); + DEBUG_BUILD && logger.log('[Tracing] Adding & adjusting spans using Performance API'); const timeOrigin = msToSec(browserPerformanceTimeOrigin); const performanceEntries = performance.getEntries(); @@ -200,11 +201,11 @@ export function addPerformanceEntries(transaction: Transaction): void { const shouldRecord = entry.startTime < firstHidden.firstHiddenTime; if (entry.name === 'first-paint' && shouldRecord) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding FP'); + DEBUG_BUILD && logger.log('[Measurements] Adding FP'); _measurements['fp'] = { value: entry.startTime, unit: 'millisecond' }; } if (entry.name === 'first-contentful-paint' && shouldRecord) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding FCP'); + DEBUG_BUILD && logger.log('[Measurements] Adding FCP'); _measurements['fcp'] = { value: entry.startTime, unit: 'millisecond' }; } break; @@ -228,7 +229,7 @@ export function addPerformanceEntries(transaction: Transaction): void { // Generate TTFB (Time to First Byte), which measured as the time between the beginning of the transaction and the // start of the response in milliseconds if (typeof responseStartTimestamp === 'number') { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding TTFB'); + DEBUG_BUILD && logger.log('[Measurements] Adding TTFB'); _measurements['ttfb'] = { value: (responseStartTimestamp - transaction.startTimestamp) * 1000, unit: 'millisecond', @@ -258,8 +259,7 @@ export function addPerformanceEntries(transaction: Transaction): void { const normalizedValue = Math.abs((measurementTimestamp - transaction.startTimestamp) * 1000); const delta = normalizedValue - oldValue; - __DEBUG_BUILD__ && - logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); + DEBUG_BUILD && logger.log(`[Measurements] Normalized ${name} from ${oldValue} to ${normalizedValue} (${delta})`); _measurements[name].value = normalizedValue; }); @@ -461,7 +461,7 @@ function _trackNavigator(transaction: Transaction): void { /** Add LCP / CLS data to transaction to allow debugging */ function _tagMetricInfo(transaction: Transaction): void { if (_lcpEntry) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding LCP Data'); + DEBUG_BUILD && logger.log('[Measurements] Adding LCP Data'); // Capture Properties of the LCP element that contributes to the LCP. @@ -483,7 +483,7 @@ function _tagMetricInfo(transaction: Transaction): void { // See: https://developer.mozilla.org/en-US/docs/Web/API/LayoutShift if (_clsEntry && _clsEntry.sources) { - __DEBUG_BUILD__ && logger.log('[Measurements] Adding CLS Data'); + DEBUG_BUILD && logger.log('[Measurements] Adding CLS Data'); _clsEntry.sources.forEach((source, index) => transaction.setTag(`cls.source.${index + 1}`, htmlTreeAsString(source.node)), ); diff --git a/packages/tracing-internal/src/browser/router.ts b/packages/tracing-internal/src/browser/router.ts index 98656d4d3f2a..472c2e9fec05 100644 --- a/packages/tracing-internal/src/browser/router.ts +++ b/packages/tracing-internal/src/browser/router.ts @@ -1,6 +1,7 @@ import type { Transaction, TransactionContext } from '@sentry/types'; import { addHistoryInstrumentationHandler, browserPerformanceTimeOrigin, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../common/debug-build'; import { WINDOW } from './types'; /** @@ -12,7 +13,7 @@ export function instrumentRoutingWithDefaults( startTransactionOnLocationChange: boolean = true, ): void { if (!WINDOW || !WINDOW.location) { - __DEBUG_BUILD__ && logger.warn('Could not initialize routing instrumentation due to invalid location'); + DEBUG_BUILD && logger.warn('Could not initialize routing instrumentation due to invalid location'); return; } @@ -49,7 +50,7 @@ export function instrumentRoutingWithDefaults( if (from !== to) { startingUrl = undefined; if (activeTransaction) { - __DEBUG_BUILD__ && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); + DEBUG_BUILD && logger.log(`[Tracing] Finishing current transaction with op: ${activeTransaction.op}`); // If there's an open transaction on the scope, we need to finish it before creating an new one. activeTransaction.finish(); } diff --git a/packages/tracing-internal/src/common/debug-build.ts b/packages/tracing-internal/src/common/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/tracing-internal/src/common/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/tracing-internal/src/node/integrations/apollo.ts b/packages/tracing-internal/src/node/integrations/apollo.ts index e4c64a299925..033e0648d624 100644 --- a/packages/tracing-internal/src/node/integrations/apollo.ts +++ b/packages/tracing-internal/src/node/integrations/apollo.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor } from '@sentry/types'; import { arrayify, fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -77,7 +78,7 @@ export class Apollo implements LazyLoadedIntegration void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Apollo Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Apollo Integration is skipped because of instrumenter configuration.'); return; } @@ -85,7 +86,7 @@ export class Apollo implements LazyLoadedIntegration Hub): void { if (!this._router) { - __DEBUG_BUILD__ && logger.error('ExpressIntegration is missing an Express instance'); + DEBUG_BUILD && logger.error('ExpressIntegration is missing an Express instance'); return; } if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Express Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Express Integration is skipped because of instrumenter configuration.'); return; } @@ -293,8 +294,8 @@ function instrumentRouter(appOrRouter: ExpressRouter): void { TODO: Proper Express 5 support */ - __DEBUG_BUILD__ && logger.debug('Cannot instrument router for URL Parameterization (did not find a valid router).'); - __DEBUG_BUILD__ && logger.debug('Routing instrumentation is currently only supported in Express 4.'); + DEBUG_BUILD && logger.debug('Cannot instrument router for URL Parameterization (did not find a valid router).'); + DEBUG_BUILD && logger.debug('Routing instrumentation is currently only supported in Express 4.'); return; } diff --git a/packages/tracing-internal/src/node/integrations/graphql.ts b/packages/tracing-internal/src/node/integrations/graphql.ts index 3fdf6e8ede4c..1fafae134ad7 100644 --- a/packages/tracing-internal/src/node/integrations/graphql.ts +++ b/packages/tracing-internal/src/node/integrations/graphql.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -37,14 +38,14 @@ export class GraphQL implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('GraphQL Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('GraphQL Integration is skipped because of instrumenter configuration.'); return; } const pkg = this.loadDependency(); if (!pkg) { - __DEBUG_BUILD__ && logger.error('GraphQL Integration was unable to require graphql/execution package.'); + DEBUG_BUILD && logger.error('GraphQL Integration was unable to require graphql/execution package.'); return; } diff --git a/packages/tracing-internal/src/node/integrations/mongo.ts b/packages/tracing-internal/src/node/integrations/mongo.ts index a3bc810be7a3..fe6bc971d72e 100644 --- a/packages/tracing-internal/src/node/integrations/mongo.ts +++ b/packages/tracing-internal/src/node/integrations/mongo.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor, SpanContext } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -140,7 +141,7 @@ export class Mongo implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Mongo Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Mongo Integration is skipped because of instrumenter configuration.'); return; } @@ -148,7 +149,7 @@ export class Mongo implements LazyLoadedIntegration { if (!pkg) { const moduleName = this._useMongoose ? 'mongoose' : 'mongodb'; - __DEBUG_BUILD__ && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); + DEBUG_BUILD && logger.error(`Mongo Integration was unable to require \`${moduleName}\` package.`); return; } diff --git a/packages/tracing-internal/src/node/integrations/mysql.ts b/packages/tracing-internal/src/node/integrations/mysql.ts index d176730f5847..18038982c03d 100644 --- a/packages/tracing-internal/src/node/integrations/mysql.ts +++ b/packages/tracing-internal/src/node/integrations/mysql.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor, Span } from '@sentry/types'; import { fill, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -46,14 +47,14 @@ export class Mysql implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Mysql Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Mysql Integration is skipped because of instrumenter configuration.'); return; } const pkg = this.loadDependency(); if (!pkg) { - __DEBUG_BUILD__ && logger.error('Mysql Integration was unable to require `mysql` package.'); + DEBUG_BUILD && logger.error('Mysql Integration was unable to require `mysql` package.'); return; } @@ -69,7 +70,7 @@ export class Mysql implements LazyLoadedIntegration { }, }); } catch (e) { - __DEBUG_BUILD__ && logger.error('Mysql Integration was unable to instrument `mysql` config.'); + DEBUG_BUILD && logger.error('Mysql Integration was unable to instrument `mysql` config.'); } function spanDataFromConfig(): Record { diff --git a/packages/tracing-internal/src/node/integrations/postgres.ts b/packages/tracing-internal/src/node/integrations/postgres.ts index a3d94653477f..918f20664b92 100644 --- a/packages/tracing-internal/src/node/integrations/postgres.ts +++ b/packages/tracing-internal/src/node/integrations/postgres.ts @@ -2,6 +2,7 @@ import type { Hub } from '@sentry/core'; import type { EventProcessor } from '@sentry/types'; import { fill, isThenable, loadModule, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import type { LazyLoadedIntegration } from './lazy'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; @@ -76,21 +77,21 @@ export class Postgres implements LazyLoadedIntegration { */ public setupOnce(_: (callback: EventProcessor) => void, getCurrentHub: () => Hub): void { if (shouldDisableAutoInstrumentation(getCurrentHub)) { - __DEBUG_BUILD__ && logger.log('Postgres Integration is skipped because of instrumenter configuration.'); + DEBUG_BUILD && logger.log('Postgres Integration is skipped because of instrumenter configuration.'); return; } const pkg = this.loadDependency(); if (!pkg) { - __DEBUG_BUILD__ && logger.error('Postgres Integration was unable to require `pg` package.'); + DEBUG_BUILD && logger.error('Postgres Integration was unable to require `pg` package.'); return; } const Client = this._usePgNative ? pkg.native?.Client : pkg.Client; if (!Client) { - __DEBUG_BUILD__ && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); + DEBUG_BUILD && logger.error("Postgres Integration was unable to access 'pg-native' bindings."); return; } diff --git a/packages/tracing-internal/src/node/integrations/prisma.ts b/packages/tracing-internal/src/node/integrations/prisma.ts index df43ec441391..b13fa2af7f53 100644 --- a/packages/tracing-internal/src/node/integrations/prisma.ts +++ b/packages/tracing-internal/src/node/integrations/prisma.ts @@ -2,6 +2,7 @@ import { getCurrentHub, trace } from '@sentry/core'; import type { Integration } from '@sentry/types'; import { addNonEnumerableProperty, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from '../../common/debug-build'; import { shouldDisableAutoInstrumentation } from './utils/node-utils'; type PrismaAction = @@ -109,7 +110,7 @@ export class Prisma implements Integration { ); }); } else { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn('Unsupported Prisma client provided to PrismaIntegration. Provided client:', options.client); } } diff --git a/packages/types/src/globals.ts b/packages/types/src/globals.ts deleted file mode 100644 index 4a3e239f8a2f..000000000000 --- a/packages/types/src/globals.ts +++ /dev/null @@ -1,18 +0,0 @@ -/* - * This file adds variables to the global namespace when it's loaded. We do this in order to be able to use flags and - * constants to facilitate tree shaking for users without having to import them, since the imports can confuse some - * tree-shaking algorithms. - * - * "Magic strings" like `__DEBUG_BUILD__` are declared here, but only replaced with actual values during our build - * process. - * - * See https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html and - * the Debug Build Flags section in CONTRIBUTING.md. - */ - -declare global { - const __DEBUG_BUILD__: boolean; -} - -// We need this empty export because of --isolatedModules -export type {}; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index cf7d801dee8b..627879493365 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -48,10 +48,6 @@ export type { Event, EventHint, EventType, ErrorEvent, TransactionEvent } from ' export type { EventProcessor } from './eventprocessor'; export type { Exception } from './exception'; export type { Extra, Extras } from './extra'; -// This is a dummy export, purely for the purpose of loading `globals.ts`, in order to take advantage of its side effect -// of putting variables into the global namespace. See -// https://www.typescriptlang.org/docs/handbook/declaration-files/templates/global-modifying-module-d-ts.html. -export type {} from './globals'; export type { Hub } from './hub'; export type { Integration, IntegrationClass } from './integration'; export type { Mechanism } from './mechanism'; diff --git a/packages/utils/src/baggage.ts b/packages/utils/src/baggage.ts index 674e7f60f7ef..0202f0ec00f5 100644 --- a/packages/utils/src/baggage.ts +++ b/packages/utils/src/baggage.ts @@ -1,5 +1,6 @@ import type { DynamicSamplingContext } from '@sentry/types'; +import { DEBUG_BUILD } from './debug-build'; import { isString } from './is'; import { logger } from './logger'; @@ -136,7 +137,7 @@ function objectToBaggageHeader(object: Record): string | undefin const baggageEntry = `${encodeURIComponent(objectKey)}=${encodeURIComponent(objectValue)}`; const newBaggageHeader = currentIndex === 0 ? baggageEntry : `${baggageHeader},${baggageEntry}`; if (newBaggageHeader.length > MAX_BAGGAGE_STRING_LENGTH) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( `Not adding key: ${objectKey} with val: ${objectValue} to baggage header due to exceeding baggage size limits.`, ); diff --git a/packages/utils/src/debug-build.ts b/packages/utils/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/utils/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/utils/src/dsn.ts b/packages/utils/src/dsn.ts index f149b67a9386..574e9c78b4eb 100644 --- a/packages/utils/src/dsn.ts +++ b/packages/utils/src/dsn.ts @@ -1,5 +1,6 @@ import type { DsnComponents, DsnLike, DsnProtocol } from '@sentry/types'; +import { DEBUG_BUILD } from './debug-build'; import { logger } from './logger'; /** Regular expression used to parse a Dsn. */ @@ -75,7 +76,7 @@ function dsnFromComponents(components: DsnComponents): DsnComponents { } function validateDsn(dsn: DsnComponents): boolean { - if (!__DEBUG_BUILD__) { + if (!DEBUG_BUILD) { return true; } diff --git a/packages/utils/src/instrument/_handlers.ts b/packages/utils/src/instrument/_handlers.ts index e86ab677ed39..520d258ae1ac 100644 --- a/packages/utils/src/instrument/_handlers.ts +++ b/packages/utils/src/instrument/_handlers.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from '../debug-build'; import { logger } from '../logger'; import { getFunctionName } from '../stacktrace'; @@ -44,7 +45,7 @@ export function triggerHandlers(type: InstrumentHandlerType, data: unknown): voi try { handler(data); } catch (e) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.error( `Error while triggering instrumentation handler.\nType: ${type}\nName: ${getFunctionName(handler)}\nError:`, e, diff --git a/packages/utils/src/instrument/index.ts b/packages/utils/src/instrument/index.ts index 800f2ec6540d..e74f6788f6e2 100644 --- a/packages/utils/src/instrument/index.ts +++ b/packages/utils/src/instrument/index.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from '../debug-build'; import type { InstrumentHandlerCallback as _InstrumentHandlerCallback, InstrumentHandlerType as _InstrumentHandlerType, @@ -35,7 +36,7 @@ export function addInstrumentationHandler(type: _InstrumentHandlerType, callback case 'unhandledrejection': return addGlobalUnhandledRejectionInstrumentationHandler(callback); default: - __DEBUG_BUILD__ && logger.warn('unknown instrumentation type:', type); + DEBUG_BUILD && logger.warn('unknown instrumentation type:', type); } } diff --git a/packages/utils/src/logger.ts b/packages/utils/src/logger.ts index 1784aa179bb1..e996d87202b2 100644 --- a/packages/utils/src/logger.ts +++ b/packages/utils/src/logger.ts @@ -1,5 +1,6 @@ import type { ConsoleLevel } from '@sentry/types'; +import { DEBUG_BUILD } from './debug-build'; import { GLOBAL_OBJ } from './worldwide'; /** Prefix for logging strings */ @@ -76,7 +77,7 @@ function makeLogger(): Logger { isEnabled: () => enabled, }; - if (__DEBUG_BUILD__) { + if (DEBUG_BUILD) { CONSOLE_LEVELS.forEach(name => { // eslint-disable-next-line @typescript-eslint/no-explicit-any logger[name] = (...args: any[]) => { diff --git a/packages/utils/src/object.ts b/packages/utils/src/object.ts index e4e866bf2763..f6dd9a1a7166 100644 --- a/packages/utils/src/object.ts +++ b/packages/utils/src/object.ts @@ -3,6 +3,7 @@ import type { WrappedFunction } from '@sentry/types'; import { htmlTreeAsString } from './browser'; +import { DEBUG_BUILD } from './debug-build'; import { isElement, isError, isEvent, isInstanceOf, isPlainObject, isPrimitive } from './is'; import { logger } from './logger'; import { truncate } from './string'; @@ -51,7 +52,7 @@ export function addNonEnumerableProperty(obj: object, name: string, value: unkno configurable: true, }); } catch (o_O) { - __DEBUG_BUILD__ && logger.log(`Failed to add non-enumerable property "${name}" to object`, obj); + DEBUG_BUILD && logger.log(`Failed to add non-enumerable property "${name}" to object`, obj); } } diff --git a/packages/utils/src/requestdata.ts b/packages/utils/src/requestdata.ts index a138ecf3141b..7106a42a5a60 100644 --- a/packages/utils/src/requestdata.ts +++ b/packages/utils/src/requestdata.ts @@ -9,6 +9,7 @@ import type { } from '@sentry/types'; import { parseCookie } from './cookie'; +import { DEBUG_BUILD } from './debug-build'; import { isPlainObject, isString } from './is'; import { logger } from './logger'; import { normalize } from './normalize'; @@ -379,7 +380,7 @@ export function winterCGHeadersToDict(winterCGHeaders: WebFetchHeaders): Record< } }); } catch (e) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn('Sentry failed extracting headers from a request object. If you see this, please file an issue.'); } diff --git a/packages/utils/src/supports.ts b/packages/utils/src/supports.ts index 2e555ee2efb5..01d4627d2892 100644 --- a/packages/utils/src/supports.ts +++ b/packages/utils/src/supports.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from './debug-build'; import { logger } from './logger'; import { getGlobalObject } from './worldwide'; @@ -121,7 +122,7 @@ export function supportsNativeFetch(): boolean { } doc.head.removeChild(sandbox); } catch (err) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn('Could not create sandbox iframe for pure fetch check, bailing to window.fetch: ', err); } } diff --git a/packages/utils/test/dsn.test.ts b/packages/utils/test/dsn.test.ts index 3de435bf5fcf..e1aadb893e8e 100644 --- a/packages/utils/test/dsn.test.ts +++ b/packages/utils/test/dsn.test.ts @@ -1,3 +1,4 @@ +import { DEBUG_BUILD } from '../src/debug-build'; import { dsnToString, makeDsn } from '../src/dsn'; import { logger } from '../src/logger'; @@ -48,7 +49,7 @@ describe('Dsn', () => { expect(dsn?.projectId).toBe('123'); }); - testIf(__DEBUG_BUILD__)('returns `undefined` for missing components', () => { + testIf(DEBUG_BUILD)('returns `undefined` for missing components', () => { expect( makeDsn({ host: '', @@ -85,7 +86,7 @@ describe('Dsn', () => { expect(loggerErrorSpy).toHaveBeenCalledTimes(4); }); - testIf(__DEBUG_BUILD__)('returns `undefined` if components are invalid', () => { + testIf(DEBUG_BUILD)('returns `undefined` if components are invalid', () => { expect( makeDsn({ host: 'sentry.io', @@ -164,12 +165,12 @@ describe('Dsn', () => { expect(dsn?.projectId).toBe('321'); }); - testIf(__DEBUG_BUILD__)('returns undefined when provided invalid Dsn', () => { + testIf(DEBUG_BUILD)('returns undefined when provided invalid Dsn', () => { expect(makeDsn('some@random.dsn')).toBeUndefined(); expect(consoleErrorSpy).toHaveBeenCalledTimes(1); }); - testIf(__DEBUG_BUILD__)('returns undefined if mandatory fields are missing', () => { + testIf(DEBUG_BUILD)('returns undefined if mandatory fields are missing', () => { expect(makeDsn('://abc@sentry.io/123')).toBeUndefined(); expect(makeDsn('https://@sentry.io/123')).toBeUndefined(); expect(makeDsn('https://abc@123')).toBeUndefined(); @@ -177,7 +178,7 @@ describe('Dsn', () => { expect(consoleErrorSpy).toHaveBeenCalledTimes(4); }); - testIf(__DEBUG_BUILD__)('returns undefined if fields are invalid', () => { + testIf(DEBUG_BUILD)('returns undefined if fields are invalid', () => { expect(makeDsn('httpx://abc@sentry.io/123')).toBeUndefined(); expect(makeDsn('httpx://abc@sentry.io:xxx/123')).toBeUndefined(); expect(makeDsn('http://abc@sentry.io/abc')).toBeUndefined(); diff --git a/packages/vercel-edge/src/async.ts b/packages/vercel-edge/src/async.ts index 36c6317248b4..336494dfbf3e 100644 --- a/packages/vercel-edge/src/async.ts +++ b/packages/vercel-edge/src/async.ts @@ -2,6 +2,8 @@ import type { Carrier, Hub, RunWithAsyncContextOptions } from '@sentry/core'; import { ensureHubOnCarrier, getHubFromCarrier, setAsyncContextStrategy } from '@sentry/core'; import { GLOBAL_OBJ, logger } from '@sentry/utils'; +import { DEBUG_BUILD } from './debug-build'; + interface AsyncLocalStorage { getStore(): T | undefined; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -18,7 +20,7 @@ let asyncStorage: AsyncLocalStorage; */ export function setAsyncLocalStorageAsyncContextStrategy(): void { if (!MaybeGlobalAsyncLocalStorage) { - __DEBUG_BUILD__ && + DEBUG_BUILD && logger.warn( "Tried to register AsyncLocalStorage async context strategy in a runtime that doesn't support AsyncLocalStorage.", ); diff --git a/packages/vercel-edge/src/debug-build.ts b/packages/vercel-edge/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/vercel-edge/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/vue/src/debug-build.ts b/packages/vue/src/debug-build.ts new file mode 100644 index 000000000000..60aa50940582 --- /dev/null +++ b/packages/vue/src/debug-build.ts @@ -0,0 +1,8 @@ +declare const __DEBUG_BUILD__: boolean; + +/** + * This serves as a build time flag that will be true by default, but false in non-debug builds or if users replace `__SENTRY_DEBUG__` in their generated code. + * + * ATTENTION: This constant must never cross package boundaries (i.e. be exported) to guarantee that it can be used for tree shaking. + */ +export const DEBUG_BUILD = __DEBUG_BUILD__; diff --git a/packages/vue/src/tracing.ts b/packages/vue/src/tracing.ts index 312ee076ba25..82000b9799a4 100644 --- a/packages/vue/src/tracing.ts +++ b/packages/vue/src/tracing.ts @@ -3,6 +3,7 @@ import type { Span, Transaction } from '@sentry/types'; import { logger, timestampInSeconds } from '@sentry/utils'; import { DEFAULT_HOOKS } from './constants'; +import { DEBUG_BUILD } from './debug-build'; import type { Hook, Operation, TracingOptions, ViewModel, Vue } from './types'; import { formatComponentName } from './vendor/components'; @@ -63,7 +64,7 @@ export const createTracingMixins = (options: TracingOptions): Mixins => { // eg. mount => ['beforeMount', 'mounted'] const internalHooks = HOOKS[operation]; if (!internalHooks) { - __DEBUG_BUILD__ && logger.warn(`Unknown hook: ${operation}`); + DEBUG_BUILD && logger.warn(`Unknown hook: ${operation}`); continue; }