Overview
As in Go, the time-series story is mostly metrics exposition — your service publishes, Prometheus scrapes — plus client paths for the stores you query directly. Rust's exposition landscape has two poles: the official CNCF prometheus-client crate (openmetrics-first, typed registries) and the metrics facade (instrument once, choose an exporter later — the Micrometer role). And the ecosystem note that colors everything: the new generation of time-series engines — InfluxDB 3, GreptimeDB, QuestDB's ILP ecosystem — is increasingly written in Rust, so first-party client attention follows.
Key points
- prometheus-client (official): typed metric families
(
Family<Labels, Counter>), label sets as structs withEncodeLabelSetderives, OpenMetrics text exposition — wire it to an axum/metricshandler and you're scrapeable; the olderprometheuscrate remains widespread in existing code. - The metrics facade:
counter!("http_requests_total", "route" => "/users")macros in library/app code,metrics-exporter-prometheus(or OTLP) chosen at the binary edge — instrument-once-decide-later, the same argument as Micrometer's; the tracing ecosystem interoperates (tracing spans → metrics via layers). - OpenTelemetry:
opentelemetry+opentelemetry-otlpfor the collector-centric shops; maturing steadily, and the natural pick when traces and metrics should share pipelines — same convergence story as the other two stacks. - InfluxDB: influxdb2 for the 2.x Flux/line-protocol API; InfluxDB 3's (itself Rust) FlightSQL path via arrow-flight — line protocol remains the lowest-common-denominator write path.
- The PG-wire stores need no special client: TimescaleDB and QuestDB speak
Postgres wire, so sqlx/tokio-postgres
apply unchanged — hypertables and
time_bucketare SQL, not API. - GreptimeDB / QuestDB ILP: official ingestion clients (
greptimedb-ingester,questdb-rs) for the high-throughput write paths of the Rust/Java newcomers. - Querying Prometheus from Rust (dashboard/automation use) is a plain HTTP+serde affair (prometheus-http-query wraps it) — PromQL over the HTTP API, no special driver.
Examples
// prometheus-client exposition
#[derive(Clone, Hash, PartialEq, Eq, EncodeLabelSet, Debug)]
struct Labels { route: &'static str, status: u16 }
let requests = Family::<Labels, Counter>::default();
registry.register("http_requests", "Requests served", requests.clone());
requests.get_or_create(&Labels { route: "/users", status: 200 }).inc();
async fn metrics(State(reg): State<Arc<Registry>>) -> impl IntoResponse {
let mut buf = String::new();
encode(&mut buf, ®).unwrap();
([(header::CONTENT_TYPE, "application/openmetrics-text; version=1.0.0")], buf)
}
Related
- Storage access from Rust — the map — parent map.
- Relational databases from Rust — the PG-wire path for Timescale/QuestDB.
- Time-series stores from Go — Prometheus's native habitat; the exposition patterns mirrored here.
- Time-series stores from Java — Micrometer, the facade the metrics crate parallels.
- OpenTelemetry — the standard the
opentelemetry_sdk/tracing-opentelemetrypath exports through; signals, OTLP, and the Collector.