Adoption & Community Savings
Most projects show you raw download counts and hope you don't ask questions. We ask them for you: downloads are bot-filtered, savings come from an opt-in census that starts at zero and can't be inflated, and every number below is computed by public code from a public git branch.
connecting to the metrics branch…
The number everyone shows vs. the one that's true
A public PyPI package receives constant traffic from supply-chain scanners (Snyk/Socket-class), package-intel crawlers (deps.dev, libraries.io), and malware sandboxes — every new release triggers fleet-wide sweeps. They report no operating system; pip on a real machine does. Even the filtered number counts events (CI reinstalls, upgrades), not people — provable people are the census tile. So we split:
Who actually runs it — and what it saves them
Machines that consented (distil census on). Anonymous install ids, schema frozen by test, fully disclosed — preview your own payload anytime with distil census show.
Two paths, three validation layers, one public datastore
Passive registry stats involve zero code on anyone's machine. The census is validated at the worker, re-validated in CI, and capped again at rollup — then stored in a git branch anyone can read.
Freshness · census re-rolls within ~1 min of any ping · registry stats nightly (PyPI publishes daily) · badges re-poll every 5 min · this page fetches on load
DO_NOT_TRACK=1 wins over everything — see TELEMETRY.md.
Metrics & Observability
Enterprises scrape; they do not poll a dashboard. distil exposes its savings as a Prometheus endpoint and as OpenTelemetry counters — the same numbers over two transports, with no dependency added to the core.
Prometheus
The gateway serves the standard text exposition format at /distil/metrics:
$ distil gateway distil gateway listening on http://127.0.0.1:8789 dashboard: http://127.0.0.1:8789/distil/dashboard metrics: http://127.0.0.1:8789/distil/metrics (Prometheus) $ curl -s localhost:8789/distil/metrics | head # HELP distil_requests_total Requests processed, by tenant. # TYPE distil_requests_total counter distil_requests_total{tenant="widget-co"} 12 # HELP distil_tokens_saved_total Input tokens kept off the wire. # TYPE distil_tokens_saved_total counter distil_tokens_saved_total{tenant="widget-co"} 38000
Series
| Metric | Type | Meaning |
|---|---|---|
distil_requests_total | counter | Requests processed, per tenant. |
distil_tokens_baseline_total | counter | Input tokens that would have been sent. |
distil_tokens_sent_total | counter | Input tokens actually sent. |
distil_tokens_saved_total | counter | Tokens kept off the wire. |
distil_dollars_saved_total | counter | Value of saved tokens at the configured input price. |
distil_compression_ratio | gauge | Fraction saved, 0–1. |
distil_build_info | gauge | Always 1; carries the version label. |
Names follow Prometheus convention — distil_ prefix, base units, _total on monotonic counters — so rate() and increase() work without relabeling. Totals are deliberately not exported as separate series: Prometheus sums labelled series itself, and shipping both invites double counting.
/distil/metrics would publish your customer list to anyone who can reach the port. It sits behind exactly the same gate as /distil/stats: open on loopback for local use, and on any non-loopback bind it requires --admin-token and refuses without it.
scrape_config for a non-loopback gateway
scrape_configs:
- job_name: distil
metrics_path: /distil/metrics
authorization:
type: Bearer
credentials: $DISTIL_ADMIN_TOKEN
static_configs:
- targets: ["distil-gateway:8789"]
OpenTelemetry
distil emits GenAI-convention spans and, independently, counters. Both are optional and both fail open — if the SDK is absent, or an exporter throws, the request path is untouched.
| Instrument | Unit | Mirrors |
|---|---|---|
distil.requests | {request} | distil_requests_total |
distil.tokens.baseline | {token} | distil_tokens_baseline_total |
distil.tokens.sent | {token} | distil_tokens_sent_total |
distil.tokens.saved | {token} | distil_tokens_saved_total |
Counters are recorded at the same instrumentation point as the span attributes, so tracing and metrics can never disagree about a request — and they are recorded before the span check, so metrics work with tracing sampled off.
# 1. the API distil records against (this is all the extra pulls in) $ pip install "distil-llm[otel]" # 2. an SDK + exporter — what actually ships the data off the box $ pip install opentelemetry-distro opentelemetry-exporter-otlp # 3. standard OTel env vars apply — no distil-specific config $ export OTEL_EXPORTER_OTLP_ENDPOINT=http://collector:4317 $ opentelemetry-instrument distil proxy
[otel] extra installs opentelemetry-api only. The API on its own is a no-op recorder — spans and counters are accepted and discarded, and nothing leaves the process until an SDK and exporter are configured. That is deliberate: it is what keeps the extra dependency-light and why a missing or misconfigured OTel install can never break the request path. If you see no data, check that step 2 ran before assuming distil is silent.
What to alert on
The useful alert is not "savings dropped" — savings vary with traffic. It is compression stopped happening at all, which usually means a config or upstream change, not a distil bug:
# compression effectively disabled for 15 minutes
rate(distil_tokens_saved_total[15m]) == 0
and rate(distil_requests_total[15m]) > 0
Pair it with the decision-equivalence signal from the certificate: savings without equivalence is not a win, and distil is the only layer that reports both.
Zero runtime dependencies: the Prometheus exporter is stdlib-only, and the OTel path imports lazily behind an extra. Neither can fail in a way that reaches your traffic.