Prometheus Metrics in Rust: Performance and Fault Tolerance Monitoring
In modern Rust backend development, monitoring has become an integral part of the production infrastructure. Prometheus is the de facto standard for collecting and storing metrics, and its integration with Rust allows you to track performance, CPU load, request count, errors, and much more. In this article, we'll look at two main libraries: prometheus (the official client) and metrics + metrics-exporter-prometheus (a more abstract approach).
Why Do You Need Metrics in Rust?
Metrics allow you to:
- Track service status in real-time
- Detect bottlenecks (latency, errors)
- Build dashboards in Grafana
- Configure alerts (e.g., when QPS drops or errors increase)
Installing and Configuring the prometheus Library
Add to Cargo.toml:
[dependencies]prometheus = { version = "0.13", features = ["process"] }actix-web = "4" # for the web server exampletokio = { version = "1", features = ["full"] }The prometheus library provides three main metric types: Counter, Gauge, Histogram.
Example: Creating and Registering Metrics
use prometheus::{Counter, Gauge, Histogram, HistogramOpts, Opts, Registry};
fn main() { // Create a metric registry let registry = Registry::new();
// Counter — request counter let request_counter = Counter::with_opts( Opts::new("http_requests_total", "Total HTTP requests") .const_label("service", "my_app") ).unwrap(); registry.register(Box::new(request_counter.clone())).unwrap();
// Gauge — current number of active connections let active_connections = Gauge::with_opts( Opts::new("active_connections", "Number of active connections") ).unwrap(); registry.register(Box::new(active_connections.clone())).unwrap();
// Histogram — response time distribution let request_duration = Histogram::with_opts( HistogramOpts::new("http_request_duration_seconds", "Request duration in seconds") .buckets(vec![0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]) ).unwrap(); registry.register(Box::new(request_duration.clone())).unwrap();
// Simulate usage request_counter.inc(); active_connections.set(42.0); request_duration.observe(0.123);}Exporting Metrics via HTTP (actix-web)
For Prometheus to collect metrics, you need to expose them in the /metrics format:
use actix_web::{web, App, HttpServer, HttpResponse, Responder};use prometheus::{Encoder, TextEncoder, Registry};use std::sync::Arc;
async fn metrics_handler(registry: web::Data<Arc<Registry>>) -> impl Responder { let encoder = TextEncoder::new(); let mut buffer = Vec::new(); encoder.encode(®istry.gather(), &mut buffer).unwrap(); HttpResponse::Ok() .content_type("text/plain; charset=utf-8") .body(buffer)}
#[actix_web::main]async fn main() -> std::io::Result<()> { let registry = Arc::new(Registry::new()); // ... register metrics as above ...
HttpServer::new(move || { App::new() .app_data(web::Data::new(registry.clone())) .route("/metrics", web::get().to(metrics_handler)) }) .bind("127.0.0.1:9090")? .run() .await}The metrics Library — A High-Level Approach
An alternative is the metrics crate with the metrics-exporter-prometheus exporter. It provides macros for quickly creating metrics:
[dependencies]metrics = "0.21"metrics-exporter-prometheus = "0.