Rust中的Prometheus指标:prometheus库与metrics-exporter-prometheus

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

Rust中的Prometheus指标:性能监控



Prometheus是现代微服务架构中收集和分析指标的事实标准。在Rust生态系统中,有多个成熟的库可以轻松集成Prometheus格式的指标导出。在本文中,我们将介绍两个主要库:prometheus(官方客户端)和metrics-exporter-prometheus(metrics框架的一部分)。



为什么Rust需要指标?



监控Rust应用程序对于以下方面至关重要:

  • 跟踪性能(延迟、吞吐量)
  • 发现内存泄漏和资源问题
  • 基于阈值设置告警
  • 分析趋势和容量规划


prometheus库(prometheus-rs)



Prometheus的官方Rust客户端。提供创建和导出指标的完整工具集。



安装

在Cargo.toml中添加:

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


基础示例:带指标的HTTP服务器

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

// 创建请求计数器 let request_counter = IntCounter::new("http_requests_total", "Total HTTP requests") .unwrap(); registry.register(Box::new(request_counter.clone())).unwrap();

// 响应时间直方图 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();

// 处理请求 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

推荐