Métricas de Prometheus en Rust: bibliotecas prometheus y metrics-exporter-prometheus

Entrenador de Python en Línea para Principiantes

Aprende Python fácilmente sin sobrecargarte de teoría. Resuelve tareas prácticas con verificación automática, recibe pistas y escribe código directamente en el navegador, sin instalar nada.

Start Course

Métricas de Prometheus en Rust: monitoreo de rendimiento



Prometheus es el estándar de facto para la recopilación y análisis de métricas en arquitecturas modernas de microservicios. En el ecosistema de Rust existen varias bibliotecas maduras que permiten integrar fácilmente la exportación de métricas en formato Prometheus. En este artículo, analizaremos dos bibliotecas principales: prometheus (cliente oficial) y metrics-exporter-prometheus (parte del framework metrics).



¿Por qué son necesarias las métricas en Rust?



El monitoreo de aplicaciones Rust es fundamental para:

  • Seguimiento del rendimiento (latencia, rendimiento)
  • Detección de fugas de memoria y problemas de recursos
  • Configuración de alertas basadas en valores umbral
  • Análisis de tendencias y planificación de capacidad


Biblioteca prometheus (prometheus-rs)



Cliente oficial de Rust para Prometheus. Proporciona un conjunto completo de herramientas para crear y exportar métricas.



Instalación

Agregue a Cargo.toml:

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


Ejemplo básico: servidor HTTP con métricas

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();

// Creamos un contador de solicitudes let request_counter = IntCounter::new("http_requests_total", "Total HTTP requests") .unwrap(); registry.register(Box::new(request_counter.clone())).unwrap();

// Histograma para el tiempo de respuesta 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();

// Procesamiento de la solicitud 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