GET /stats
Public process-wide runtime statistics — engine, compile, prewarm, deltas, sessions, datafeed and HTTP counters.
This page
Abstract
GET /stats is a public (no API key) snapshot of what this worker has been doing since it started: request counts and latency, execution-engine runs, compile cache outcomes, prewarm results, live-session delta sizes, and datafeed traffic.
It is process-local. Counters reset when the worker restarts — which is honest for the single-worker gunicorn setup live sessions require, but means the numbers describe this process, since it booted, not a durable time series. Export them if you need dashboards.
Interface surface
GET /stats
{
"status": "ok",
"service": "pynescript-pro-api",
"version": "1.0.0",
"timestamp": 1791968289,
"debug": { "env": "PYNE_DEBUG", "enabled": true, "scopes": [], "level": "DEBUG" },
"counters": { "run.total": { "total": 4 }, "run.by_mode": { "total": 2, "by": { "auto": 2 } } },
"latencies": { "run.total": { "count": 4, "total_ms": 9251.2, "avg_ms": 2312.8,
"min_ms": 0.36, "max_ms": 9250.3,
"p50_ms": 1.2, "p95_ms": 8974.6 } },
"gauges": { "sessions.active": 1, "sessions.capacity": 64, "http.in_flight": 0 },
"compile_cache": { "source_entries": 2, "ir_entries": 1, "has_numba": true, … },
"sessions": { "sessions": 1, "max_sessions": 64, "ttl_seconds": 900.0 },
"notes": "in-process counters; reset on worker restart"
}
Three metric kinds
| Kind | Shape | Notes |
|---|---|---|
counters | {total, by?} | Monotonic. by is a dimension breakdown (mode, endpoint, status class, fallback reason). |
latencies | {count, total_ms, avg_ms, min_ms, max_ms, p50_ms, p95_ms} | Percentiles come from a bounded reservoir of the last 512 samples per metric, so they describe recent behaviour, not the whole run. |
gauges | number | Last value — in-flight requests, active sessions, cache entries. |
Metric names are dotted (run.total, delta.bars_appended, http.request) so the payload groups naturally.
What is tracked
| Namespace | Examples |
|---|---|
http | requests, by_endpoint, by_status_class, client_errors, server_errors, slow_requests; in_flight gauge |
run | total, bars, by_mode, mode_resolved, auto_backend, errors, error_kind, timed_out, compile_cached, compile_fallback_reasons |
interpret | bars, bar_loop latency, errors by kind, timeouts |
compile | attempts, eligibility, host_cache (hit/miss), errors, run / total latency |
compile_script | cache split by memory_raw / memory_sanitized / disk / ir_share / miss |
prewarm | calls, builtin_warm, scripts_ok, scripts_failed, total latency |
delta | append_calls, bars_appended, update_last_bar_calls; bars_per_append_max gauge |
session / sessions | engine created and parse; store created, dropped, evicted, active, capacity, active_max |
datafeed | streams, exchanges_connected, reconnects, errors, session_binds, watch_connections, watch_bars, gateway ohlcv / markets counters and latency |
provider | created, fetches, bars_fetched, fetch_errors |
Relationship to other surfaces
GET /stats complements, and does not replace:
- the per-run profile in the
/runenvelope (total_ms,parse_ms,eval_ms, per-line rows) — that is client-visible, per-run detail; - the
compileblock onGET /health— that is capability plus cache configuration; GET /auth/usage— that is business metering for rate limits.
/health deliberately stays a cheap liveness probe. It does not absorb these counters.
Cardinality
Dimension values come from closed sets — route rules, interpret/compile/auto, 2xx–5xx, a small set of exchange ids. compile_fallback_reasons is truncated to 120 characters for the same reason. The registry is not a Prometheus-style label store; do not point a high-cardinality metric at it.
Failure modes
| Symptom | Cause | Fix |
|---|---|---|
| All counters reset | Worker restarted / redeployed | Expected — counters are in-process |
| Counters look low behind a load balancer | Multiple workers, each counting its own slice | Aggregate per worker, or run with GUNICORN_WORKERS=1 |
p95_ms disagrees with max_ms | Percentiles use a 512-sample reservoir | Treat p95 as recent-window; max_ms is all-time |
compile_cache or sessions shows error | Engine import failed | The rest of the payload still serves — /stats never fails the request |
Internals (map)
| Path | Role |
|---|---|
src/pynescript/stats.py | Thread-safe counter / latency / gauge registry |
src/pynescript/debug.py | PYNE_DEBUG toggle (reported under debug) |
backend/logging_setup.py | debug_report() |
backend/app.py | /stats route, request hooks |
backend/api/datafeed.py, backend/middleware/sessions.py | Datafeed + session counters |
See also
- Observability —
PYNE_DEBUGlogging - App lifecycle
- POST /run