Skip to main content

Where each signal lands

Every request through /v1 produces three things you can read. The one exception is on the trace span: a successful chat or messages call that returns no output, no cost and no completion tokens is dropped before export. The gateway starts one span per dispatched request and exports it to the project the virtual key names. The span is named gen_ai.<operation>, for example gen_ai.chat.

Trace attributes

The table lists every attribute the gateway sets. An attribute whose value the gateway does not have is left off the span.
A successful chat or messages call that returns no output, no cost and no completion tokens is dropped before export. These are the empty probe calls coding agents send, and they would otherwise fill the trace list with rows that carry no data.

Response headers

Debugging a single request

Read X-LangWatch-Gateway-Request-Id off the response or the client’s error, then search that value in Trace Explorer. That span shows the model, the provider, the token counts, the cost and the upstream status.

Trace ID propagation

Send a Traceparent request header and the span written to your project becomes a child of your trace, under your trace id. Send no header and the span starts a trace of its own. The Traceparent response header names that span. Forward it to the next hop in your system and everything stitches into one trace in Trace Explorer. X-LangWatch-Trace-Id and X-LangWatch-Span-Id name the gateway’s own operational span, which stays separate from your trace. They are present only on a deployment that exports the gateway’s own spans; LangWatch Cloud responses carry Traceparent and X-LangWatch-Gateway-Request-Id only. Use them when you report a problem to LangWatch support.

Metrics (Prometheus)

GET /metrics needs no authentication and runs on the same port as the API. Scrape it with a ServiceMonitor or a plain scrape config. See Self-hosting: Helm.

Traffic and lifecycle

Provider dispatch and fallback

outcome is one of success, fallback_success, retryable_5xx, not_found, rate_limit, timeout, network, circuit_open, non_retryable, chain_exhausted, context_done.

Authentication cache

tier always reads l1. The cache is an in-process LRU, private to each pod.

Governance

gateway_client_rejects_total counts only what the gateway refused. Three cases stay off it on purpose, because each would make a per-key alert fire for a key doing its job:
  • Authentication failures, which have no key to attribute yet. Watch gateway_http_requests_total{status="401"}.
  • Provider rejections, such as an upstream 429. Watch gateway_provider_attempts_total{outcome="rate_limit"}.
  • Rate limiting, which a key at its ceiling would pin. Watch gateway_rate_limit_denied_total.
To find a client stuck in a rejection loop, rank the keys first:
Then break the top key down by code, with the full key id in place of <vk-id>:

Realtime voice

Control plane

endpoint is one of resolve-key, guardrail-check, config, codex-refresh. The change-feed long poll is excluded, because it blocks until an event or its own timeout and its timing says little about control-plane health.

Spend emission

Every request writes a spend record to a bounded on-disk spool, and a background drainer ships the spool to the control plane. The control plane debits budgets from those records, so a record the spool drops is spend that is never billed and never enforced against. reason is intake when the spool’s writer could not take the record, and overflow when the oldest sealed segments were deleted to keep the spool inside its 64 MiB bound. Alert on any sustained positive rate:
Both counters read 0 on a pod whose spool failed to open. That pod serves traffic and emits no spend at all. It logs the failure at startup, and you can spot it from a scrape by reading these two counters against a live gateway_http_requests_total. The spool is pod-local and stays off a volume. A pod deleted with records still unshipped loses them, bounded by the drain lag of about a second of traffic. The registry also carries the standard Go runtime and process collectors (go_*, process_*). Also check: Troubleshooting for reading a failed request end to end, Security for what the gateway records and what it never logs, Self-hosting: Configuration for the environment variables.
Last modified on September 6, 2026