Skip to main content

Monitoring and operations

Metrics and health at a glanceโ€‹

SignalEndpointFormat
Prometheus metricsGET /metricsPrometheus text
Deep health checkGET /healthJSON
Provider listGET /admin/providersJSON

See Observability for the full metrics reference and log field docs.

Prometheus scrape setupโ€‹

# prometheus.yml
scrape_configs:
- job_name: ferrogw
static_configs:
- targets: ["gateway-host:8080"]
scrape_interval: 15s
groups:
- name: ferrogw
rules:
# High error rate
- alert: GatewayHighErrorRate
expr: |
sum(rate(gateway_requests_total{status="error"}[5m])) /
sum(rate(gateway_requests_total[5m])) > 0.05
for: 2m
labels:
severity: warning
annotations:
summary: "Gateway error rate > 5%"

# P99 latency
- alert: GatewayHighLatency
expr: |
histogram_quantile(0.99,
rate(gateway_request_duration_seconds_bucket[5m])
) > 10
for: 5m
labels:
severity: warning
annotations:
summary: "P99 request latency > 10s"

# Circuit breaker open
- alert: GatewayCircuitBreakerOpen
expr: gateway_circuit_breaker_state == 1
for: 1m
labels:
severity: critical
annotations:
summary: "Circuit breaker open on {{ $labels.provider }}"

# All providers unhealthy
- alert: GatewayNoHealthyProviders
expr: up{job="ferrogw"} == 0
for: 1m
labels:
severity: critical
annotations:
summary: "Gateway has no healthy providers"

# Model catalog falling back to the embedded backup
- alert: GatewayCatalogFallback
expr: increase(gateway_catalog_loads_total{source="fallback"}[15m]) > 0
for: 15m
labels:
severity: warning
annotations:
summary: "Model catalog using embedded fallback (remote source unreachable)"

Grafana dashboardโ€‹

A community Grafana dashboard JSON is available in the repository at docs/grafana-dashboard.json. Import it into your Grafana instance and point the data source to your Prometheus server.

Key panels to build manually if you prefer:

PanelQuery
Requests / secrate(gateway_requests_total[1m])
Error rate %sum(rate(gateway_requests_total{status="error"}[5m])) / sum(rate(gateway_requests_total[5m])) * 100
P50 / P95 / P99 latencyhistogram_quantile(0.99, rate(gateway_request_duration_seconds_bucket[5m]))
Token usage / min(rate(gateway_tokens_input_total[1m]) + rate(gateway_tokens_output_total[1m])) * 60
Estimated spend / hoursum by (model) (rate(gateway_request_cost_usd_total[5m])) * 3600
Provider breakdownsum by (provider) (rate(gateway_requests_total[5m]))
Catalog loads by sourcesum by (source, result) (rate(gateway_catalog_loads_total[15m]))

Logging pipelineโ€‹

Ship stdout JSON logs to your log aggregator:

# Pipe to a log collector
./ferrogw 2>&1 | your-log-shipper --format=json

# Or use Docker logging drivers
docker run ... --log-driver=awslogs ghcr.io/ferro-labs/ai-gateway:latest

Filter gateway logs by trace_id in your aggregator to correlate all events for a single request across plugins and provider calls.

Resiliency controlsโ€‹

  • Circuit breakers โ€” automatically exclude failing providers; see the gateway_circuit_breaker_state metric
  • Retries โ€” configurable per target with status-code filtering (on_status_codes)
  • Fallback strategy โ€” automatically promotes to the next target when primary fails
  • Health endpoint โ€” integrate into your load balancer's health check for automatic traffic shifting