diff --git a/packages/node/src/integrations/tracing/connect.ts b/packages/node/src/integrations/tracing/connect.ts index 60bb9d74448a..7d3e5a28137f 100644 --- a/packages/node/src/integrations/tracing/connect.ts +++ b/packages/node/src/integrations/tracing/connect.ts @@ -1,4 +1,3 @@ -import { isWrapped } from '@opentelemetry/core'; import { ConnectInstrumentation } from '@opentelemetry/instrumentation-connect'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, @@ -6,12 +5,11 @@ import { captureException, defineIntegration, getClient, - isEnabled, spanToJSON, } from '@sentry/core'; import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; import type { IntegrationFn, Span } from '@sentry/types'; -import { consoleSandbox } from '@sentry/utils'; +import { ensureIsWrapped } from '../../utils/ensureIsWrapped'; type ConnectApp = { // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -48,14 +46,7 @@ export const setupConnectErrorHandler = (app: ConnectApp): void => { }); } - if (!isWrapped(app.use) && isEnabled()) { - consoleSandbox(() => { - // eslint-disable-next-line no-console - console.warn( - '[Sentry] Connect is not instrumented. This is likely because you required/imported connect before calling `Sentry.init()`.', - ); - }); - } + ensureIsWrapped(app.use, 'connect'); }; function addConnectSpanAttributes(span: Span): void { diff --git a/packages/node/src/integrations/tracing/express.ts b/packages/node/src/integrations/tracing/express.ts index 58164f97d5ea..cddb9bb7e0e5 100644 --- a/packages/node/src/integrations/tracing/express.ts +++ b/packages/node/src/integrations/tracing/express.ts @@ -1,21 +1,14 @@ import type * as http from 'node:http'; import { ExpressInstrumentation } from '@opentelemetry/instrumentation-express'; -import { - SEMANTIC_ATTRIBUTE_SENTRY_OP, - defineIntegration, - getDefaultIsolationScope, - isEnabled, - spanToJSON, -} from '@sentry/core'; +import { SEMANTIC_ATTRIBUTE_SENTRY_OP, defineIntegration, getDefaultIsolationScope, spanToJSON } from '@sentry/core'; import { captureException, getClient, getIsolationScope } from '@sentry/core'; import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; import type { IntegrationFn } from '@sentry/types'; - -import { isWrapped } from '@opentelemetry/core'; -import { consoleSandbox, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../../debug-build'; import type { NodeClient } from '../../sdk/client'; import { addOriginToSpan } from '../../utils/addOriginToSpan'; +import { ensureIsWrapped } from '../../utils/ensureIsWrapped'; const _expressIntegration = (() => { return { @@ -138,15 +131,7 @@ export function expressErrorHandler(options?: { */ export function setupExpressErrorHandler(app: { use: (middleware: ExpressMiddleware) => unknown }): void { app.use(expressErrorHandler()); - - if (!isWrapped(app.use) && isEnabled()) { - consoleSandbox(() => { - // eslint-disable-next-line no-console - console.warn( - '[Sentry] Express is not instrumented. This is likely because you required/imported express before calling `Sentry.init()`.', - ); - }); - } + ensureIsWrapped(app.use, 'express'); } function getStatusCodeFromResponse(error: MiddlewareError): number { diff --git a/packages/node/src/integrations/tracing/fastify.ts b/packages/node/src/integrations/tracing/fastify.ts index 33f2af3084bd..6286bd8a0f97 100644 --- a/packages/node/src/integrations/tracing/fastify.ts +++ b/packages/node/src/integrations/tracing/fastify.ts @@ -1,4 +1,3 @@ -import { isWrapped } from '@opentelemetry/core'; import { FastifyInstrumentation } from '@opentelemetry/instrumentation-fastify'; import { SEMANTIC_ATTRIBUTE_SENTRY_OP, @@ -7,12 +6,11 @@ import { defineIntegration, getClient, getIsolationScope, - isEnabled, spanToJSON, } from '@sentry/core'; import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; import type { IntegrationFn, Span } from '@sentry/types'; -import { consoleSandbox } from '@sentry/utils'; +import { ensureIsWrapped } from '../../utils/ensureIsWrapped'; // We inline the types we care about here interface Fastify { @@ -101,14 +99,7 @@ export function setupFastifyErrorHandler(fastify: Fastify): void { }); } - if (!isWrapped(fastify.addHook) && isEnabled()) { - consoleSandbox(() => { - // eslint-disable-next-line no-console - console.warn( - '[Sentry] Fastify is not instrumented. This is likely because you required/imported fastify before calling `Sentry.init()`.', - ); - }); - } + ensureIsWrapped(fastify.addHook, 'fastify'); } function addFastifySpanAttributes(span: Span): void { diff --git a/packages/node/src/integrations/tracing/hapi/index.ts b/packages/node/src/integrations/tracing/hapi/index.ts index 42da7423ca5b..ee03cfc34ac6 100644 --- a/packages/node/src/integrations/tracing/hapi/index.ts +++ b/packages/node/src/integrations/tracing/hapi/index.ts @@ -1,4 +1,3 @@ -import { isWrapped } from '@opentelemetry/core'; import { HapiInstrumentation } from '@opentelemetry/instrumentation-hapi'; import { SDK_VERSION, @@ -12,13 +11,13 @@ import { getDefaultIsolationScope, getIsolationScope, getRootSpan, - isEnabled, spanToJSON, } from '@sentry/core'; import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; import type { IntegrationFn, Span } from '@sentry/types'; -import { consoleSandbox, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../../../debug-build'; +import { ensureIsWrapped } from '../../../utils/ensureIsWrapped'; import type { Boom, RequestEvent, ResponseObject, Server } from './types'; const _hapiIntegration = (() => { @@ -110,14 +109,7 @@ export async function setupHapiErrorHandler(server: Server): Promise { } // eslint-disable-next-line @typescript-eslint/unbound-method - if (!isWrapped(server.register) && isEnabled()) { - consoleSandbox(() => { - // eslint-disable-next-line no-console - console.warn( - '[Sentry] Hapi is not instrumented. This is likely because you required/imported hapi before calling `Sentry.init()`.', - ); - }); - } + ensureIsWrapped(server.register, 'hapi'); } function addHapiSpanAttributes(span: Span): void { diff --git a/packages/node/src/integrations/tracing/koa.ts b/packages/node/src/integrations/tracing/koa.ts index d6be349e60de..7d68afb19efe 100644 --- a/packages/node/src/integrations/tracing/koa.ts +++ b/packages/node/src/integrations/tracing/koa.ts @@ -1,4 +1,3 @@ -import { isWrapped } from '@opentelemetry/core'; import { KoaInstrumentation } from '@opentelemetry/instrumentation-koa'; import { SEMATTRS_HTTP_ROUTE } from '@opentelemetry/semantic-conventions'; import { @@ -8,13 +7,13 @@ import { defineIntegration, getDefaultIsolationScope, getIsolationScope, - isEnabled, spanToJSON, } from '@sentry/core'; import { addOpenTelemetryInstrumentation } from '@sentry/opentelemetry'; import type { IntegrationFn, Span } from '@sentry/types'; -import { consoleSandbox, logger } from '@sentry/utils'; +import { logger } from '@sentry/utils'; import { DEBUG_BUILD } from '../../debug-build'; +import { ensureIsWrapped } from '../../utils/ensureIsWrapped'; function addKoaSpanAttributes(span: Span): void { span.setAttribute(SEMANTIC_ATTRIBUTE_SENTRY_ORIGIN, 'auto.http.otel.koa'); @@ -76,12 +75,5 @@ export const setupKoaErrorHandler = (app: { use: (arg0: (ctx: any, next: any) => } }); - if (!isWrapped(app.use) && isEnabled()) { - consoleSandbox(() => { - // eslint-disable-next-line no-console - console.warn( - '[Sentry] Koa is not instrumented. This is likely because you required/imported koa before calling `Sentry.init()`.', - ); - }); - } + ensureIsWrapped(app.use, 'koa'); }; diff --git a/packages/node/src/sdk/init.ts b/packages/node/src/sdk/init.ts index 469c9e9e12f7..be78aa54efa3 100644 --- a/packages/node/src/sdk/init.ts +++ b/packages/node/src/sdk/init.ts @@ -41,7 +41,8 @@ import { defaultStackParser, getSentryRelease } from './api'; import { NodeClient } from './client'; import { initOpenTelemetry } from './initOtel'; -function isCjs(): boolean { +/** Detect CommonJS. */ +export function isCjs(): boolean { return typeof require !== 'undefined'; } diff --git a/packages/node/src/utils/ensureIsWrapped.ts b/packages/node/src/utils/ensureIsWrapped.ts new file mode 100644 index 000000000000..41003e3b7ec3 --- /dev/null +++ b/packages/node/src/utils/ensureIsWrapped.ts @@ -0,0 +1,28 @@ +import { isWrapped } from '@opentelemetry/core'; +import { hasTracingEnabled, isEnabled } from '@sentry/core'; +import { consoleSandbox } from '@sentry/utils'; +import { isCjs } from '../sdk/init'; + +/** + * Checks and warns if a framework isn't wrapped by opentelemetry. + */ +export function ensureIsWrapped( + maybeWrappedModule: unknown, + name: 'express' | 'connect' | 'fastify' | 'hapi' | 'koa', +): void { + if (!isWrapped(maybeWrappedModule) && isEnabled() && hasTracingEnabled()) { + consoleSandbox(() => { + if (isCjs()) { + // eslint-disable-next-line no-console + console.warn( + `[Sentry] ${name} is not instrumented. This is likely because you required/imported ${name} before calling \`Sentry.init()\`.`, + ); + } else { + // eslint-disable-next-line no-console + console.warn( + `[Sentry] ${name} is not instrumented. Please make sure to initialize Sentry in a separate file that you \`--import\` when running node, see: https://docs.sentry.io/platforms/javascript/guides/${name}/install/esm/.`, + ); + } + }); + } +}