Métricas Prometheus em Rust: monitoramento de desempenho
Prometheus é o padrão de facto para coleta e análise de métricas em arquiteturas modernas de microsserviços. No ecossistema Rust, existem várias bibliotecas maduras que permitem integrar facilmente a exportação de métricas no formato Prometheus. Neste artigo, abordaremos duas bibliotecas principais: prometheus (cliente oficial) e metrics-exporter-prometheus (parte do framework metrics).
Por que métricas em Rust?
O monitoramento de aplicações Rust é essencial para:
- Acompanhamento de desempenho (latência, throughput)
- Identificação de vazamentos de memória e problemas com recursos
- Configuração de alertas com base em valores limite
- Análise de tendências e planejamento de capacidade
Biblioteca prometheus (prometheus-rs)
Cliente Rust oficial para Prometheus. Fornece um conjunto completo de ferramentas para criar e exportar métricas.
Instalação
Adicione ao Cargo.toml:
[dependencies]prometheus = { version = "0.13", features = ["process"] }hyper = { version = "0.14", features = ["http1", "server"] }Exemplo básico: servidor HTTP com 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();
// Criando um contador de requisições let request_counter = IntCounter::new("http_requests_total", "Total HTTP requests") .unwrap(); registry.register(Box::new(request_counter.clone())).unwrap();
// Histograma para tempo de resposta 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();
// Processamento da requisição 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 Também na biblioteca
range-v3 para C++: guia completo com exemplos
Migrações de banco de dados em Kotlin: Visão geral de ferramentas e abordagens
Processamento de Imagens em Java: Redimensionamento e Corte (resize, crop)
Internacionalização (i18n) em Go (Golang): Guia Completo
Lottie Android para Kotlin: guia completo com exemplos práticos