Prometheus Metrics in Rust: prometheus and metrics-exporter-prometheus Libraries

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Prometheus Metrics in Rust: Performance Monitoring



Prometheus is the de facto standard for collecting and analyzing metrics in modern microservice architectures. In the Rust ecosystem, there are several mature libraries that make it easy to integrate metric export in Prometheus format. In this article, we will look at two main libraries: prometheus (official client) and metrics-exporter-prometheus (part of the metrics framework).



Why are metrics needed in Rust?



Monitoring Rust applications is critical for:

  • Tracking performance (latency, throughput)
  • Identifying memory leaks and resource issues
  • Setting up alerts based on threshold values
  • Analyzing trends and capacity planning


The prometheus Library (prometheus-rs)



The official Rust client for Prometheus. Provides a full set of tools for creating and exporting metrics.



Installation

Add to Cargo.toml:

[dependencies]prometheus = { version = "0.13", features = ["process"] }hyper = { version = "0.14", features = ["http1", "server"] }


Basic Example: HTTP Server with Metrics

use prometheus::{Counter, HistogramOpts, HistogramVec, IntCounter, Registry, TextEncoder};use std::net::SocketAddr;use hyper::{Body, Request, Response, Server};use hyper::service::{make_service_fn, service_fn};use std::convert::Infallible;use std::sync::Arc;use tokio::sync::Mutex;

#[tokio::main]async fn main() { let registry = Registry::new();

// Create a request counter let request_counter = IntCounter::new("http_requests_total", "Total HTTP requests") .unwrap(); registry.register(Box::new(request_counter.clone())).unwrap();

// Histogram for response time let request_duration = HistogramVec::new( HistogramOpts::new("http_request_duration_seconds", "HTTP request duration"), &["method", "path"] ).unwrap(); registry.register(Box::new(request_duration.clone())).unwrap();

let data = Arc::new(Mutex::new((request_counter, request_duration)));

let make_svc = make_service_fn(move |_conn| { let data = data.clone(); async move { Ok::<_, Infallible>(service_fn(move |req: Request| { let data = data.clone(); async move { let start = std::time::Instant::now(); let (counter, duration) = &*data.lock().await; counter.inc();

// Handle request let response = match req.uri().path() { "/metrics" => { let encoder = TextEncoder::new(); let metric_families = registry.gather(); let mut buffer = vec![]; encoder.encode(&metric_families, &mut buffer).unwrap(); Response::new(Body::from(buffer)) } "/" => Response::new(Body::from("Hello, World!")), _ => Response::builder() .status(404) .body(Body::from("Not Found")) .unwrap(), };

let elapsed = start.elapsed().as_secs_f64(); duration .with_label_values(&[req.method().as_str(), req.uri().path()]) .observe(elapsed);

Ok::<_, Infallible>(response) } })) } });

let addr = SocketAddr::from(([127, 0, 0, 1], 8080)); let server = Server::bind(&addr).serve(make_svc); println!("Listening on http://{}", addr); if let Err(e) = server.a

Recommendations