Skip to content

Request logging

Besides traces, the core writes plain-text logs to stdout and stderr. There is no log level, no JSON mode and no file output; collect the container's streams with your usual tooling.

Log prefixes

Prefix What it reports
[server] Listening port and environment; shutdown progress.
[db] Connection wait and success; pool closed on shutdown.
[install] Schema installation, migration and their failures. Read these first when /v1/install/status is not installed.
[license] Result of the license check at startup.
[telemetry] Whether the anonymous snapshot was sent.
[observability] Destination enabled or disabled, lost batches (throttled to one line per 5 minutes), shutdown flush.
[req] One line per HTTP request, only with LOG_REQUESTS=true.
[runtime] One line per request forwarded to a provider: [runtime] <surface> <METHOD> <path> <model>, plus warnings such as could not record usage, stream ended early, dlp could not run.
[usage] Token usage returned by the provider on non-streamed calls: [usage] <model> <surface> {…}.
[errorHandler] Unexpected 500s with the real cause. The client only sees INTERNAL_ERROR.
[proxy-runtime] Unexpected errors inside the gateway.

Per-request lines

LOG_REQUESTS=true
[req] POST /v1/proxy-apps/9a1b…/openai/v1/chat/completions 200 843ms
[req] GET /v1/users/me 200 4ms
[req] POST /v1/proxy-apps/9a1b…/openai/v1/responses 200 15210ms (aborted)

(aborted) marks a client that closed the connection before the response was complete. The middleware runs before the body parser, so malformed JSON requests are logged as well. Off by default in production because, at volume, traces are the better record: they carry tokens, cost and identity, and go to a database rather than a log stream.

A typical startup

[license] valid — Acme Corp (enterprise), expires 2027-01-01T00:00:00.000Z
[db] waiting for postgres...
[db] connected
[install] schema version 3 is current
[observability] schema version 1 is current
[observability] enabled (postgres)
[server] listening on port 3000 (production)
[telemetry] anonymous snapshot sent — disable with TELEMETRY_ENABLED=false

A typical shutdown

[server] SIGTERM received, closing
[db] pool closed

Shutdown waits for in-flight requests (long streams delay it) up to 10 s, then logs [server] shutdown timed out, forcing exit and exits with code 1. Give the container at least 15 s of grace.

Shipping logs

Nothing special: docker logs, gcloud run services logs read, a Kubernetes log agent. For Cloud Run, the [req] and [runtime] lines are parsed as text entries in Cloud Logging; filter with textPayload:"[install]".