diff --git a/apps/login/next-env-vars.d.ts b/apps/login/next-env-vars.d.ts index f57ab6a30..bafdada19 100644 --- a/apps/login/next-env-vars.d.ts +++ b/apps/login/next-env-vars.d.ts @@ -81,5 +81,11 @@ declare namespace NodeJS { * which is safer for environments with enterprise email link scanners. */ NEXT_PUBLIC_AUTO_SUBMIT_CODE?: string; + /** + * Optional: Disable OpenTelemetry instrumentation. + * Set to "true" to bypass OTEL initialization. + * In local development (NODE_ENV=development), it is disabled by default unless explicitly set to "false". + */ + OTEL_SDK_DISABLED?: string; } } diff --git a/apps/login/src/instrumentation.node.ts b/apps/login/src/instrumentation.node.ts new file mode 100644 index 000000000..e205dc327 --- /dev/null +++ b/apps/login/src/instrumentation.node.ts @@ -0,0 +1,53 @@ +import type { LoggerProvider } from "@opentelemetry/api-logs"; + +export async function registerNode(): Promise { + const [ + { NodeSDK }, + { envDetector, processDetector, hostDetector, resourceFromAttributes }, + { containerDetector }, + { gcpDetector }, + { logs }, + { getNodeAutoInstrumentations }, + ] = await Promise.all([ + import("@opentelemetry/sdk-node"), + import("@opentelemetry/resources"), + import("@opentelemetry/resource-detector-container"), + import("@opentelemetry/resource-detector-gcp"), + import("@opentelemetry/api-logs"), + import("@opentelemetry/auto-instrumentations-node"), + ]); + + const sdk = new NodeSDK({ + resource: resourceFromAttributes({ + "deployment.environment.name": process.env.NODE_ENV || "development", + }), + resourceDetectors: [ + envDetector, + processDetector, + hostDetector, + containerDetector, + gcpDetector, + ], + instrumentations: [ + getNodeAutoInstrumentations({ + "@opentelemetry/instrumentation-http": { + ignoreIncomingRequestHook: (req) => + ["/healthy", "/_next/", "/favicon.ico", "/__nextjs", "/metrics"].some((p) => + req.url?.includes(p), + ), + }, + "@opentelemetry/instrumentation-fs": { enabled: false }, + "@opentelemetry/instrumentation-winston": { disableLogSending: false }, + }), + ], + }); + + sdk.start(); + + // Use console during shutdown as the logger may be unavailable + const shutdown = () => sdk.shutdown().catch(console.error); + process.once("SIGTERM", shutdown); + process.once("SIGINT", shutdown); + + return logs.getLoggerProvider(); +} diff --git a/apps/login/src/instrumentation.ts b/apps/login/src/instrumentation.ts index 73ab6ba93..7e1de9792 100644 --- a/apps/login/src/instrumentation.ts +++ b/apps/login/src/instrumentation.ts @@ -29,57 +29,19 @@ import type { LoggerProvider } from "@opentelemetry/api-logs"; let _loggerProvider: LoggerProvider | null = null; export async function register(): Promise { - if (process.env.NEXT_RUNTIME !== "nodejs") return; + // Only run OpenTelemetry in the Node.js environment + if (process.env.NEXT_RUNTIME === "nodejs") { + // Disable by default in local development to avoid unnecessary overhead + if (process.env.NODE_ENV === "development" && process.env.OTEL_SDK_DISABLED !== "false") { + return; + } - const [ - { NodeSDK }, - { envDetector, processDetector, hostDetector, resourceFromAttributes }, - { containerDetector }, - { gcpDetector }, - { logs }, - { getNodeAutoInstrumentations }, - ] = await Promise.all([ - import("@opentelemetry/sdk-node"), - import("@opentelemetry/resources"), - import("@opentelemetry/resource-detector-container"), - import("@opentelemetry/resource-detector-gcp"), - import("@opentelemetry/api-logs"), - import("@opentelemetry/auto-instrumentations-node"), - ]); + // Explicit check for disabled env variable + if (process.env.OTEL_SDK_DISABLED === "true") return; - const sdk = new NodeSDK({ - resource: resourceFromAttributes({ - "deployment.environment.name": process.env.NODE_ENV || "development", - }), - resourceDetectors: [ - envDetector, - processDetector, - hostDetector, - containerDetector, - gcpDetector, - ], - instrumentations: [ - getNodeAutoInstrumentations({ - "@opentelemetry/instrumentation-http": { - ignoreIncomingRequestHook: (req) => - ["/healthy", "/_next/", "/favicon.ico", "/__nextjs", "/metrics"].some((p) => - req.url?.includes(p), - ), - }, - "@opentelemetry/instrumentation-fs": { enabled: false }, - "@opentelemetry/instrumentation-winston": { disableLogSending: false }, - }), - ], - }); - - sdk.start(); - - _loggerProvider = logs.getLoggerProvider(); - - // Use console during shutdown as the logger may be unavailable - const shutdown = () => sdk.shutdown().catch(console.error); - process.once("SIGTERM", shutdown); - process.once("SIGINT", shutdown); + const { registerNode } = await import("./instrumentation.node"); + _loggerProvider = await registerNode(); + } } export function getLoggerProvider(): LoggerProvider | null {