Rust应用监控:tracing库与指标

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

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

开始课程

Rust应用监控:tracing库与指标收集



监控是生产系统的关键要素。对于以性能和可靠性著称的Rust应用而言,拥有轻量且高效的遥测收集工具至关重要。tracing库已成为Rust生态系统中可观测性的事实标准。它提供结构化日志记录、用于请求追踪的跨度(span),以及与指标收集系统的集成。



什么是tracing?



tracing是一个用于Rust程序仪表化的框架。与传统的日志记录不同,它基于事件(events)和跨度(spans)工作。跨度代表代码执行的时间段(例如,处理HTTP请求),而事件是跨度内的点(例如,“数据库在10毫秒内响应”)。



主要功能:

  • 结构化日志记录 — 每个事件包含字段(键值对),而不仅仅是字符串。
  • 跨度层级 — 可以将跨度相互嵌套,追踪完整的执行路径。
  • 异步支持 — 与tokio和async/await配合良好。
  • 订阅者(Subscriber) — 可以连接各种后端:stdout、OpenTelemetry、Prometheus、文件。


安装与基本使用



在Cargo.toml中添加:

[dependencies]tracing = "0.1"tracing-subscriber = "0.3"


结构化日志记录的简单示例:

use tracing::{info, warn, error};use tracing_subscriber;

fn main() { // 初始化用于stdout输出的订阅者 tracing_subscriber::fmt::init();

let user_id = 42; let request_duration_ms = 150;

info!(user_id, duration = request_duration_ms, "请求已处理");

// 使用warn级别的日志记录 warn!(user_id, "响应时间超过阈值");

// 使用error级别的日志记录 error!("无法连接到数据库");}


输出将包含类似JSON格式的字段,便于在监控系统中解析。



跨度与追踪



跨度允许测量操作执行时间并将事件链接成链:

use tracing::{span, info, Level};use tracing_subscriber;

fn process_request(user_id: u32) { // 创建带上下文的跨度 let span = span!(Level::INFO, "process_request", user_id); let _guard = span.enter(); // 激活跨度

info!("开始处理"); std::thread::sleep(std::time::Duration::from_millis(50)); info!("处理完成");}

fn main() { tracing_subscriber::fmt::init(); process_request(100);}


输出中将显示嵌套上下文,表明事件属于process_request跨度。



使用tracing和Prometheus收集指标



对于生产监控,通常需要将指标导出到Prometheus。使用tracing-appender crate写入文件,或使用tracing-opentelemetry与OpenTelemetry集成。然而,最直接的方式是将metrics库与tracing结合使用。



与metrics-exporter-prometheus集成的示例:

[dependencies]metrics = "0.21"metrics-exporter-prometheus = "0.12"tracing = "0.1"tokio = { version = "1", features = ["full"] }


收集指标的代码:

use metrics::{counter, gauge, histogram};use metrics_exporter_prometheus::PrometheusBuilder;use std::net::SocketAddr;

#[tokio::main]async fn main() { // 启动Prometheus的HTTP服务器 let addr: SocketAddr = "0.0.0.0:9090".parse().unwrap(); let builder = PrometheusBuilder::new(); builder .wit

推荐