diff --git a/packages/profiling-node/src/integration.ts b/packages/profiling-node/src/integration.ts index 67ad0c0ed2e3..fb0cdbe6195c 100644 --- a/packages/profiling-node/src/integration.ts +++ b/packages/profiling-node/src/integration.ts @@ -2,12 +2,12 @@ import type { Event, IntegrationFn, Profile, ProfileChunk, ProfilingIntegration, Span } from '@sentry/core'; import { consoleSandbox, + debug, defineIntegration, getCurrentScope, getGlobalScope, getIsolationScope, getRootSpan, - logger, LRUMap, spanToJSON, uuid4, @@ -75,7 +75,7 @@ class ContinuousProfiler { this._legacyProfilerMode = 'profilesSampleRate' in options || 'profilesSampler' in options ? 'span' : 'continuous'; - DEBUG_BUILD && logger.log(`[Profiling] Profiling mode is ${this._legacyProfilerMode}.`); + DEBUG_BUILD && debug.log(`[Profiling] Profiling mode is ${this._legacyProfilerMode}.`); switch (this._legacyProfilerMode) { case 'span': { @@ -88,7 +88,7 @@ class ContinuousProfiler { } default: { DEBUG_BUILD && - logger.warn( + debug.warn( `[Profiling] Unknown profiler mode: ${this._legacyProfilerMode}, profiler was not initialized`, ); break; @@ -100,7 +100,7 @@ class ContinuousProfiler { case 'current': { this._setupSpanChunkInstrumentation(); - DEBUG_BUILD && logger.log(`[Profiling] Profiling mode is ${this._profileLifecycle}.`); + DEBUG_BUILD && debug.log(`[Profiling] Profiling mode is ${this._profileLifecycle}.`); switch (this._profileLifecycle) { case 'trace': { @@ -113,14 +113,14 @@ class ContinuousProfiler { } default: { DEBUG_BUILD && - logger.warn(`[Profiling] Unknown profiler mode: ${this._profileLifecycle}, profiler was not initialized`); + debug.warn(`[Profiling] Unknown profiler mode: ${this._profileLifecycle}, profiler was not initialized`); break; } } break; } default: { - DEBUG_BUILD && logger.warn(`[Profiling] Unknown profiler mode: ${this._mode}, profiler was not initialized`); + DEBUG_BUILD && debug.warn(`[Profiling] Unknown profiler mode: ${this._mode}, profiler was not initialized`); break; } } @@ -142,17 +142,17 @@ class ContinuousProfiler { } if (!this._client) { - DEBUG_BUILD && logger.log('[Profiling] Failed to start, sentry client was never attached to the profiler.'); + DEBUG_BUILD && debug.log('[Profiling] Failed to start, sentry client was never attached to the profiler.'); return; } if (this._mode !== 'legacy') { - DEBUG_BUILD && logger.log('[Profiling] Continuous profiling is not supported in the current mode.'); + DEBUG_BUILD && debug.log('[Profiling] Continuous profiling is not supported in the current mode.'); return; } if (this._legacyProfilerMode === 'span') { - DEBUG_BUILD && logger.log('[Profiling] Calls to profiler.start() are not supported in span profiling mode.'); + DEBUG_BUILD && debug.log('[Profiling] Calls to profiler.start() are not supported in span profiling mode.'); return; } @@ -176,17 +176,17 @@ class ContinuousProfiler { } if (!this._client) { - DEBUG_BUILD && logger.log('[Profiling] Failed to stop, sentry client was never attached to the profiler.'); + DEBUG_BUILD && debug.log('[Profiling] Failed to stop, sentry client was never attached to the profiler.'); return; } if (this._mode !== 'legacy') { - DEBUG_BUILD && logger.log('[Profiling] Continuous profiling is not supported in the current mode.'); + DEBUG_BUILD && debug.log('[Profiling] Continuous profiling is not supported in the current mode.'); return; } if (this._legacyProfilerMode === 'span') { - DEBUG_BUILD && logger.log('[Profiling] Calls to profiler.stop() are not supported in span profiling mode.'); + DEBUG_BUILD && debug.log('[Profiling] Calls to profiler.stop() are not supported in span profiling mode.'); return; } @@ -196,25 +196,25 @@ class ContinuousProfiler { private _startProfiler(): void { if (this._mode !== 'current') { - DEBUG_BUILD && logger.log('[Profiling] Continuous profiling is not supported in the current mode.'); + DEBUG_BUILD && debug.log('[Profiling] Continuous profiling is not supported in the current mode.'); return; } if (this._chunkData !== undefined) { - DEBUG_BUILD && logger.log('[Profiling] Profile session already running, no-op.'); + DEBUG_BUILD && debug.log('[Profiling] Profile session already running, no-op.'); return; } if (this._mode === 'current') { if (!this._sampled) { - DEBUG_BUILD && logger.log('[Profiling] Profile session not sampled, no-op.'); + DEBUG_BUILD && debug.log('[Profiling] Profile session not sampled, no-op.'); return; } } if (this._profileLifecycle === 'trace') { DEBUG_BUILD && - logger.log( + debug.log( '[Profiling] You are using the trace profile lifecycle, manual calls to profiler.startProfiler() and profiler.stopProfiler() will be ignored.', ); return; @@ -225,20 +225,20 @@ class ContinuousProfiler { private _stopProfiler(): void { if (this._mode !== 'current') { - DEBUG_BUILD && logger.log('[Profiling] Continuous profiling is not supported in the current mode.'); + DEBUG_BUILD && debug.log('[Profiling] Continuous profiling is not supported in the current mode.'); return; } if (this._profileLifecycle === 'trace') { DEBUG_BUILD && - logger.log( + debug.log( '[Profiling] You are using the trace profile lifecycle, manual calls to profiler.startProfiler() and profiler.stopProfiler() will be ignored.', ); return; } if (!this._chunkData) { - DEBUG_BUILD && logger.log('[Profiling] No profile session running, no-op.'); + DEBUG_BUILD && debug.log('[Profiling] No profile session running, no-op.'); return; } @@ -251,7 +251,7 @@ class ContinuousProfiler { private _startTraceLifecycleProfiling(): void { if (!this._client) { DEBUG_BUILD && - logger.log( + debug.log( '[Profiling] Failed to start trace lifecycle profiling, sentry client was never attached to the profiler.', ); return; @@ -276,7 +276,7 @@ class ContinuousProfiler { private _setupAutomaticSpanProfiling(): void { if (!this._client) { DEBUG_BUILD && - logger.log( + debug.log( '[Profiling] Failed to setup automatic span profiling, sentry client was never attached to the profiler.', ); return; @@ -307,7 +307,7 @@ class ContinuousProfiler { // Enqueue a timeout to prevent profiles from running over max duration. const timeout = global.setTimeout(() => { DEBUG_BUILD && - logger.log( + debug.log( '[Profiling] max profile duration elapsed, stopping profiling for:', spanToJSON(span).description, ); @@ -371,7 +371,7 @@ class ContinuousProfiler { const cpuProfile = takeFromProfileQueue(profile_id); if (!cpuProfile) { - DEBUG_BUILD && logger.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); + DEBUG_BUILD && debug.log(`[Profiling] Could not retrieve profile for transaction: ${profile_id}`); continue; } @@ -406,13 +406,13 @@ class ContinuousProfiler { // The client is not attached to the profiler if the user has not enabled continuous profiling. // In this case, calling start() and stop() is a noop action.The reason this exists is because // it makes the types easier to work with and avoids users having to do null checks. - DEBUG_BUILD && logger.log('[Profiling] Profiler was never attached to the client.'); + DEBUG_BUILD && debug.log('[Profiling] Profiler was never attached to the client.'); return; } if (this._chunkData) { DEBUG_BUILD && - logger.log( + debug.log( `[Profiling] Chunk with chunk_id ${this._chunkData.id} is still running, current chunk will be stopped a new chunk will be started.`, ); this._stopChunkProfiling(); @@ -426,26 +426,26 @@ class ContinuousProfiler { */ private _stopChunkProfiling(): void { if (!this._chunkData) { - DEBUG_BUILD && logger.log('[Profiling] No chunk data found, no-op.'); + DEBUG_BUILD && debug.log('[Profiling] No chunk data found, no-op.'); return; } if (this._chunkData?.timer) { global.clearTimeout(this._chunkData.timer); this._chunkData.timer = undefined; - DEBUG_BUILD && logger.log(`[Profiling] Stopping profiling chunk: ${this._chunkData.id}`); + DEBUG_BUILD && debug.log(`[Profiling] Stopping profiling chunk: ${this._chunkData.id}`); } if (!this._client) { DEBUG_BUILD && - logger.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.'); + debug.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.'); this._resetChunkData(); return; } if (!this._chunkData?.id) { DEBUG_BUILD && - logger.log(`[Profiling] Failed to collect profile for: ${this._chunkData?.id}, the chunk_id is missing.`); + debug.log(`[Profiling] Failed to collect profile for: ${this._chunkData?.id}, the chunk_id is missing.`); this._resetChunkData(); return; } @@ -453,22 +453,22 @@ class ContinuousProfiler { const profile = CpuProfilerBindings.stopProfiling(this._chunkData.id, ProfileFormat.CHUNK); if (!profile) { - DEBUG_BUILD && logger.log(`[Profiling] Failed to collect profile for: ${this._chunkData.id}`); + DEBUG_BUILD && debug.log(`[Profiling] Failed to collect profile for: ${this._chunkData.id}`); this._resetChunkData(); return; } if (!this._profilerId) { DEBUG_BUILD && - logger.log('[Profiling] Profile chunk does not contain a valid profiler_id, this is a bug in the SDK'); + debug.log('[Profiling] Profile chunk does not contain a valid profiler_id, this is a bug in the SDK'); this._resetChunkData(); return; } if (profile) { - DEBUG_BUILD && logger.log(`[Profiling] Sending profile chunk ${this._chunkData.id}.`); + DEBUG_BUILD && debug.log(`[Profiling] Sending profile chunk ${this._chunkData.id}.`); } - DEBUG_BUILD && logger.log(`[Profiling] Profile chunk ${this._chunkData.id} sent to Sentry.`); + DEBUG_BUILD && debug.log(`[Profiling] Profile chunk ${this._chunkData.id} sent to Sentry.`); const chunk = createProfilingChunkEvent( this._client, this._client.getOptions(), @@ -482,7 +482,7 @@ class ContinuousProfiler { ); if (!chunk) { - DEBUG_BUILD && logger.log(`[Profiling] Failed to create profile chunk for: ${this._chunkData.id}`); + DEBUG_BUILD && debug.log(`[Profiling] Failed to create profile chunk for: ${this._chunkData.id}`); this._resetChunkData(); return; } @@ -502,13 +502,13 @@ class ContinuousProfiler { private _flush(chunk: ProfileChunk): void { if (!this._client) { DEBUG_BUILD && - logger.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.'); + debug.log('[Profiling] Failed to collect profile, sentry client was never attached to the profiler.'); return; } const transport = this._client.getTransport(); if (!transport) { - DEBUG_BUILD && logger.log('[Profiling] No transport available to send profile chunk.'); + DEBUG_BUILD && debug.log('[Profiling] No transport available to send profile chunk.'); return; } @@ -518,7 +518,7 @@ class ContinuousProfiler { const envelope = makeProfileChunkEnvelope('node', chunk, metadata?.sdk, tunnel, dsn); transport.send(envelope).then(null, reason => { - DEBUG_BUILD && logger.error('Error while sending profile chunk envelope:', reason); + DEBUG_BUILD && debug.error('Error while sending profile chunk envelope:', reason); }); } @@ -528,7 +528,7 @@ class ContinuousProfiler { */ private _startChunkProfiling(): void { if (this._chunkData) { - DEBUG_BUILD && logger.log('[Profiling] Chunk is already running, no-op.'); + DEBUG_BUILD && debug.log('[Profiling] Chunk is already running, no-op.'); return; } @@ -537,12 +537,12 @@ class ContinuousProfiler { const chunk = this._initializeChunk(traceId); CpuProfilerBindings.startProfiling(chunk.id); - DEBUG_BUILD && logger.log(`[Profiling] starting profiling chunk: ${chunk.id}`); + DEBUG_BUILD && debug.log(`[Profiling] starting profiling chunk: ${chunk.id}`); chunk.timer = global.setTimeout(() => { - DEBUG_BUILD && logger.log(`[Profiling] Stopping profiling chunk: ${chunk.id}`); + DEBUG_BUILD && debug.log(`[Profiling] Stopping profiling chunk: ${chunk.id}`); this._stopChunkProfiling(); - DEBUG_BUILD && logger.log('[Profiling] Starting new profiling chunk.'); + DEBUG_BUILD && debug.log('[Profiling] Starting new profiling chunk.'); setImmediate(this._restartChunkProfiling.bind(this)); }, CHUNK_INTERVAL_MS); @@ -557,9 +557,7 @@ class ContinuousProfiler { private _setupSpanChunkInstrumentation(): void { if (!this._client) { DEBUG_BUILD && - logger.log( - '[Profiling] Failed to initialize span profiling, sentry client was never attached to the profiler.', - ); + debug.log('[Profiling] Failed to initialize span profiling, sentry client was never attached to the profiler.'); return; } @@ -648,7 +646,7 @@ export const _nodeProfilingIntegration = ((): ProfilingIntegration = name: 'ProfilingIntegration', _profiler: new ContinuousProfiler(), setup(client: NodeClient) { - DEBUG_BUILD && logger.log('[Profiling] Profiling integration setup.'); + DEBUG_BUILD && debug.log('[Profiling] Profiling integration setup.'); this._profiler.initialize(client); return; }, diff --git a/packages/profiling-node/src/spanProfileUtils.ts b/packages/profiling-node/src/spanProfileUtils.ts index 3cde8acde52d..0f3365bbd261 100644 --- a/packages/profiling-node/src/spanProfileUtils.ts +++ b/packages/profiling-node/src/spanProfileUtils.ts @@ -1,6 +1,6 @@ /* eslint-disable deprecation/deprecation */ import type { CustomSamplingContext, Span } from '@sentry/core'; -import { logger, spanIsSampled, spanToJSON, uuid4 } from '@sentry/core'; +import { debug, spanIsSampled, spanToJSON, uuid4 } from '@sentry/core'; import type { NodeClient } from '@sentry/node'; import { type RawThreadCpuProfile, CpuProfilerBindings } from '@sentry-internal/node-cpu-profiler'; import { DEBUG_BUILD } from './debug-build'; @@ -26,13 +26,13 @@ export function maybeProfileSpan( // Client and options are required for profiling if (!client) { - DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no client found.'); + DEBUG_BUILD && debug.log('[Profiling] Profiling disabled, no client found.'); return; } const options = client.getOptions(); if (!options) { - DEBUG_BUILD && logger.log('[Profiling] Profiling disabled, no options found.'); + DEBUG_BUILD && debug.log('[Profiling] Profiling disabled, no options found.'); return; } @@ -56,14 +56,14 @@ export function maybeProfileSpan( // 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 && debug.warn('[Profiling] Discarding profile because of invalid sample rate.'); return; } // 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 && - logger.log( + debug.log( `[Profiling] Discarding profile because ${ typeof profilesSampler === 'function' ? 'profileSampler returned 0 or false' @@ -79,7 +79,7 @@ export function maybeProfileSpan( // Check if we should sample this profile if (!sampled) { DEBUG_BUILD && - logger.log( + debug.log( `[Profiling] Discarding profile because it's not included in the random sample (sampling rate = ${Number( profilesSampleRate, )})`, @@ -89,7 +89,7 @@ export function maybeProfileSpan( const profile_id = uuid4(); CpuProfilerBindings.startProfiling(profile_id); - DEBUG_BUILD && logger.log(`[Profiling] started profiling transaction: ${spanToJSON(span).description}`); + DEBUG_BUILD && debug.log(`[Profiling] started profiling transaction: ${spanToJSON(span).description}`); // set transaction context - do this regardless if profiling fails down the line // so that we can still see the profile_id in the transaction context @@ -109,12 +109,12 @@ export function stopSpanProfile(span: Span, profile_id: string | undefined): Raw } const profile = CpuProfilerBindings.stopProfiling(profile_id, 0); - DEBUG_BUILD && logger.log(`[Profiling] stopped profiling of transaction: ${spanToJSON(span).description}`); + DEBUG_BUILD && debug.log(`[Profiling] stopped profiling of transaction: ${spanToJSON(span).description}`); // In case of an overlapping span, stopProfiling may return null and silently ignore the overlapping profile. if (!profile) { DEBUG_BUILD && - logger.log( + debug.log( `[Profiling] profiler returned null profile for: ${spanToJSON(span).description}`, 'this may indicate an overlapping span or a call to stopProfiling with a profile title that was never started', ); diff --git a/packages/profiling-node/src/utils.ts b/packages/profiling-node/src/utils.ts index e5b5fb9a8f6e..e17642c08148 100644 --- a/packages/profiling-node/src/utils.ts +++ b/packages/profiling-node/src/utils.ts @@ -16,10 +16,10 @@ import type { } from '@sentry/core'; import { createEnvelope, + debug, dsnToString, forEachEnvelopeItem, getDebugImagesForResources, - logger, uuid4, } from '@sentry/core'; import type { RawChunkCpuProfile, RawThreadCpuProfile } from '@sentry-internal/node-cpu-profiler'; @@ -133,7 +133,7 @@ function createProfilePayload( // 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 (trace_id?.length !== 32) { - DEBUG_BUILD && logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`); + DEBUG_BUILD && debug.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`); } const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile); @@ -206,7 +206,7 @@ function createProfileChunkPayload( // 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 (trace_id?.length !== 32) { - DEBUG_BUILD && logger.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`); + DEBUG_BUILD && debug.log(`[Profiling] Invalid traceId: ${trace_id} on profiled event`); } const enrichedThreadProfile = enrichWithThreadInformation(cpuProfile); @@ -265,7 +265,7 @@ 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 && - logger.warn( + debug.warn( `[Profiling] Invalid sample rate. Sample rate must be a boolean or a number between 0 and 1. Got ${JSON.stringify( rate, )} of type ${JSON.stringify(typeof rate)}.`, @@ -280,7 +280,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 && debug.warn(`[Profiling] Invalid sample rate. Sample rate must be between 0 and 1. Got ${rate}.`); return false; } return true; @@ -297,7 +297,7 @@ export function isValidProfile(profile: RawThreadCpuProfile): profile is RawThre // 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. - logger.log('[Profiling] Discarding profile because it contains less than 2 samples'); + debug.log('[Profiling] Discarding profile because it contains less than 2 samples'); return false; } @@ -319,7 +319,7 @@ export function isValidProfileChunk(profile: RawChunkCpuProfile): profile is Raw // 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. - logger.log('[Profiling] Discarding profile chunk because it contains less than 2 samples'); + debug.log('[Profiling] Discarding profile chunk because it contains less than 2 samples'); return false; } diff --git a/packages/profiling-node/test/integration.test.ts b/packages/profiling-node/test/integration.test.ts index 828d08f9fe44..a0ff14d4602e 100644 --- a/packages/profiling-node/test/integration.test.ts +++ b/packages/profiling-node/test/integration.test.ts @@ -1,5 +1,5 @@ import type { ProfileChunk, ProfilingIntegration, Transport } from '@sentry/core'; -import { createEnvelope, getMainCarrier, GLOBAL_OBJ, logger } from '@sentry/core'; +import { createEnvelope, debug, getMainCarrier, GLOBAL_OBJ } from '@sentry/core'; import * as Sentry from '@sentry/node'; import type { NodeClientOptions } from '@sentry/node/build/types/types'; import { CpuProfilerBindings } from '@sentry-internal/node-cpu-profiler'; @@ -127,7 +127,7 @@ describe('ProfilingIntegration', () => { }); it('logger warns user if there are insufficient samples and discards the profile', async () => { - const logSpy = vi.spyOn(logger, 'log'); + const logSpy = vi.spyOn(debug, 'log'); const [client, transport] = makeLegacySpanProfilingClient(); Sentry.setCurrentClient(client); @@ -166,7 +166,7 @@ describe('ProfilingIntegration', () => { }); it('logger warns user if traceId is invalid', async () => { - const logSpy = vi.spyOn(logger, 'log'); + const logSpy = vi.spyOn(debug, 'log'); const [client, transport] = makeLegacySpanProfilingClient(); Sentry.setCurrentClient(client);