mirror of
https://github.com/andwati/zitadel.git
synced 2026-10-23 16:02:14 +00:00
# Which Problems Are Solved The Login V2 readiness endpoint `/ui/v2/login/ready` performs an authenticated `SettingsService.GetGeneralSettings` call on every invocation. This only affects self-hosted Login V2 deployments that probe the endpoint periodically, for example via the Helm chart's readiness and startup probes, the Docker `HEALTHCHECK`, or a custom HTTP probe. In those setups every login replica continuously issues authenticated API calls that pass through the access-log interceptor and are treated as regular authenticated requests of the instance, although they are only probe traffic. The login hosted by ZITADEL Cloud is not affected, and neither are self-hosted deployments that do not probe `/ready`. Independent of the counting, validating credentials on every probe is unusual: readiness probes are meant to report whether a replica can serve traffic, while configuration errors such as invalid credentials are better caught once at startup. # How the Problems Are Solved The readiness endpoint now only checks that the ZITADEL API is reachable and ready, using the API's unauthenticated `/debug/ready` endpoint. That endpoint is served outside the access-log and quota interceptors, so probe traffic is no longer recorded. `CUSTOM_REQUEST_HEADERS` are applied to the readiness request as they are to gRPC requests. The credential check moves to process startup: `register()` in `instrumentation.ts` calls the new `verifyApiCredentials()` once, using the same auth and transport path as real requests. If the API rejects the credentials (`Unauthenticated`/`PermissionDenied`) or no credentials are configured, the process exits with a clear error so misconfiguration is visible immediately. If the API is not reachable at startup, a warning is logged and the process continues; reachability remains the job of the readiness probe and `ZITADEL_API_AWAITINITIALCONN`. Unit tests cover the readiness route, the credential check result mapping, and the startup behavior of `register()`. No changes to the Helm chart or Dockerfile are required. Self-hosted deployments pick up the fix with the next login image; until then, the probe interval can be increased to reduce the number of calls.
62 lines
2.2 KiB
TypeScript
62 lines
2.2 KiB
TypeScript
import type { LoggerProvider } from "@opentelemetry/api-logs";
|
|
|
|
/**
|
|
* @module instrumentation
|
|
*
|
|
* OpenTelemetry instrumentation for Next.js applications using NodeSDK.
|
|
* Set OTEL_SDK_DISABLED=true to disable instrumentation entirely.
|
|
*
|
|
* Configuration via standard OTEL environment variables:
|
|
*
|
|
* ### Exporters (all default to "otlp")
|
|
* - OTEL_TRACES_EXPORTER: trace exporter (otlp, console, none)
|
|
* - OTEL_METRICS_EXPORTER: metric exporter (otlp, prometheus, console, none)
|
|
* - OTEL_LOGS_EXPORTER: log exporter (otlp, console, none)
|
|
* - OTEL_EXPORTER_OTLP_ENDPOINT: base endpoint for OTLP signals
|
|
* - OTEL_EXPORTER_PROMETHEUS_PORT: Prometheus scrape port (default 9464)
|
|
*
|
|
* ### Batch Processors
|
|
* - OTEL_BSP_SCHEDULE_DELAY: span export delay (default 5000ms)
|
|
* - OTEL_METRIC_EXPORT_INTERVAL: metric push interval (default 60000ms)
|
|
*
|
|
* ### Resource
|
|
* - OTEL_SERVICE_NAME: service.name attribute
|
|
* - OTEL_RESOURCE_ATTRIBUTES: additional attributes (key=value,key=value)
|
|
*
|
|
* @see https://opentelemetry.io/docs/specs/otel/configuration/sdk-environment-variables/
|
|
*/
|
|
|
|
let _loggerProvider: LoggerProvider | null = null;
|
|
|
|
export async function register(): Promise<void> {
|
|
// Only run in the Node.js environment
|
|
if (process.env.NEXT_RUNTIME !== "nodejs") return;
|
|
|
|
if (isOtelEnabled()) {
|
|
const { registerNode } = await import("./instrumentation.node");
|
|
_loggerProvider = await registerNode();
|
|
}
|
|
|
|
// Verify the configured API credentials once at startup (fail fast).
|
|
// Connectivity problems are only logged; reachability is covered by the
|
|
// readiness probe (/ready) and ZITADEL_API_AWAITINITIALCONN.
|
|
const { verifyApiCredentials, FATAL_CREDENTIAL_CHECK_RESULTS } = await import("./lib/verify-credentials");
|
|
const result = await verifyApiCredentials();
|
|
if (FATAL_CREDENTIAL_CHECK_RESULTS.has(result)) {
|
|
process.exit(1);
|
|
}
|
|
}
|
|
|
|
function isOtelEnabled(): boolean {
|
|
// Disable by default in local development to avoid unnecessary overhead
|
|
if (process.env.NODE_ENV === "development" && process.env.OTEL_SDK_DISABLED !== "false") {
|
|
return false;
|
|
}
|
|
// Explicit check for disabled env variable
|
|
return process.env.OTEL_SDK_DISABLED !== "true";
|
|
}
|
|
|
|
export function getLoggerProvider(): LoggerProvider | null {
|
|
return _loggerProvider;
|
|
}
|