eggrd/ docs

Operations

Three endpoints, one metrics format, and one decision to make about which port they live on. eggrd exports Prometheus text on a plain HTTP path — there is no agent, no sidecar and no push.

Ops endpoints

PathAnswersUse it for
/__edgeguard/health 200 always Liveness. Is the eggrd process itself up and serving? It does not consult the upstream, so it stays 200 during an upstream outage — restarting eggrd would not help.
/__edgeguard/ready 200 / 503 Readiness. Opens a TCP connection to the upstream with a 2-second timeout. 503 while the upstream is unreachable, so a load balancer stops sending traffic eggrd cannot serve.
/__edgeguard/metrics Prometheus text Scrape target. See below.

The split matters more than it looks. Pointing a liveness probe at readiness restarts a perfectly healthy proxy every time the app behind it hiccups, which turns one outage into two.

Keeping them off the public port

By default these paths live on the public listener. Set server.admin_port to a non-zero value and eggrd binds a second, plain-HTTP listener for them — the public port then serves only the proxy.

[server]
admin_port = 9090
admin_addr = "127.0.0.1"   # same-host only; 0.0.0.0 for a private network interface

admin_addr defaults to 127.0.0.1, so the endpoints are reachable only from the same host unless you widen it deliberately. Point your platform's health check at the admin port once you enable it, or it will be checking a port that no longer answers.

Metrics

Prometheus text format, scraped from /__edgeguard/metrics. The core series:

SeriesTypeWhat it tells you
edgeguard_requests_totalcounterRequests by outcome label — the single most useful series here. See below.
edgeguard_request_duration_secondshistogramEnd-to-end latency through the proxy, with _bucket, _sum and _count.
edgeguard_ratelimit_hits_totalcounterRequests the limiter rejected.
edgeguard_waf_hits_totalcounterWAF matches, labelled by rule (sqli, traversal, and so on).
edgeguard_csp_reports_totalcounterCSP violation reports received at the browser-facing report sink.

Request outcomes

Every request lands in exactly one outcome bucket on edgeguard_requests_total. Alerting on the shape of this label is usually more informative than alerting on status codes, because it distinguishes which gate refused.

OutcomeMeaning
okProxied to the upstream and returned.
unauthorizedAuth refused it. 401.
forbiddenWAF, DLP, or a model allowlist refused it. 403.
ip_deniedClient address outside the access list. 403.
rate_limitedOver the configured rate. 429.
limiter_errorShared limiter store unreachable and failing closed. 503.
over_budgetAn LLM budget was exhausted. 429 for a token cap, 402 for a cost cap.
unpriced_modelModel absent from the price book while the policy requires one. 402.
payload_too_largeRequest body over validation.max_body. 413.
header_too_largeHeaders over the configured cap.
method_not_allowedMethod outside the allowlist. 405.
not_foundNo route matched.
bad_gatewayUpstream unreachable or answered unusably. 502.
upstream_errorUpstream failed mid-response.
upstream_timeoutUpstream exceeded validation.upstream_timeout. 504.
ws_upgradeConnection upgraded to a WebSocket and passed through.

LLM gateway metrics

Present only when [llm] is enabled. Token counts come from the upstream's own usage object — eggrd does not tokenize anything itself, so the numbers are the provider's, not an estimate.

SeriesWhat it tells you
edgeguard_llm_requests_totalRequests by result — including unpriced, which is how you find a model missing from the price book.
edgeguard_llm_tokens_totalTotal tokens, with _model_, _key_ and _team_ variants for attribution.
edgeguard_llm_cost_microdollars_totalCost in microdollars, with the same three attribution variants. Integer microdollars rather than floats, so summing does not drift.
edgeguard_llm_cached_tokens_totalThe cached subset of prompt tokens, where the provider reports it.
edgeguard_llm_reasoning_tokens_totalReasoning tokens, where the provider reports them separately.
edgeguard_llm_budget_consumed_ratioGauge, 0–1, per budget. The series to alert on before a cap starts refusing traffic.
edgeguard_llm_budget_blocked_totalRequests a budget refused.
edgeguard_llm_budget_reconcile_failures_totalReservations that could not be reconciled to actual usage. Non-zero means recorded spend is drifting from reality — worth an alert.
edgeguard_llm_dlp_findings_totalDLP matches by category.
edgeguard_llm_dlp_blocked_totalRequests DLP refused outright.
edgeguard_llm_keyvault_totalVirtual-key lookups, including denials.
edgeguard_llm_ttft_secondsHistogram: time to first token.
edgeguard_llm_tpot_secondsHistogram: time per output token.

What fails closed

Two shared stores can be unreachable, and both refuse traffic rather than waving it through by default. An outage that silently disabled rate limiting, or silently uncapped spend, would be the worst possible failure for either feature.

StoreSettingDefaultOn store error
Rate limiterratelimit.fail_openfalse503, and the request never reaches the upstream.
LLM budgetsllm.fail_openfalse503, and the provider is never called.

Setting either to true trades correctness for availability: requests are admitted unlimited while the store is down. That is a legitimate choice for a rate limiter in front of a resilient app, and a dangerous one for a spend cap.

Endpoint behaviour and metric names were read from the shipped source rather than from memory. The configuration reference is generated from it directly.