Rust监控与追踪库metrics-tracing-context的使用:实现上下文感知的指标收集与分布式追踪集成
metrics-tracing-context
一个使用追踪上下文作为指标标签的crate。
元数据 版本:0.18.1 发布时间:2个月前 最小Rust版本:v1.71.1 许可证:MIT 大小:11.6 KiB
安装 在项目目录中运行以下Cargo命令: cargo add metrics-tracing-context
或在Cargo.toml中添加以下行: metrics-tracing-context = “0.18.1”
文档 docs.rs/metrics-tracing-context/0.18.1
仓库 github.com/metrics-rs/metrics
所有者 Toby Lawrence
分类 调试工具::调试
完整示例代码:
use metrics_tracing_context::MetricsLayer;
use tracing_subscriber::prelude::*;
fn main() {
// 设置追踪订阅器
tracing_subscriber::registry()
.with(MetricsLayer::new())
.init();
// 创建一个span
let span = tracing::info_span!("request", method = "GET", path = "/api/data");
let _enter = span.enter();
// 记录一些指标
metrics::counter!("requests.total").increment(1);
metrics::gauge!("active_requests", 1.0);
// 执行一些工作
process_request();
}
fn process_request() {
// 在子span中工作
let _span = tracing::info_span!("process").entered();
// 记录处理时间
let start = std::time::Instant::now();
// 模拟工作
std::thread::sleep(std::time::Duration::from_millis(100));
// 记录持续时间指标
metrics::histogram!("request.duration").record(start.elapsed());
}
此示例展示了如何:
- 设置metrics-tracing-context集成
- 创建带有上下文的追踪span
- 记录自动带有追踪上下文标签的指标
- 在分布式追踪环境中收集上下文感知的指标
完整示例代码:
use metrics_tracing_context::MetricsLayer;
use tracing_subscriber::prelude::*;
use metrics_exporter_prometheus::PrometheusBuilder;
use metrics_util::MetricKindMask;
fn main() {
// 设置Prometheus导出器
let builder = PrometheusBuilder::new();
let recorder = builder.build();
metrics::set_boxed_recorder(Box::new(recorder)).unwrap();
// 设置追踪订阅器并集成MetricsLayer
tracing_subscriber::registry()
.with(MetricsLayer::new())
.init();
// 模拟处理多个请求
for i in 0..5 {
let method = if i % 2 == 0 { "GET" } else { "POST" };
let path = format!("/api/data/{}", i);
// 创建带有上下文的span
let span = tracing::info_span!("request", method = method, path = path.as_str());
let _enter = span.enter();
// 记录请求指标
metrics::counter!("http.requests.total").increment(1);
metrics::gauge!("http.active_requests", 1.0);
// 处理请求
process_request(i);
// 离开span时会自动记录持续时间
}
}
fn process_request(request_id: u32) {
// 创建处理子span
let _span = tracing::info_span!("process_request", request_id = request_id).entered();
// 记录开始时间
let start = std::time::Instant::now();
// 模拟不同的处理时间
let sleep_duration = std::time::Duration::from_millis(50 + (request_id * 20) as u64);
std::thread::sleep(sleep_duration);
// 记录处理时间指标
metrics::histogram!("request.processing_time").record(start.elapsed());
// 模拟处理结果
if request_id % 10 == 0 {
metrics::counter!("request.errors").increment(1);
} else {
metrics::counter!("request.successes").increment(1);
}
}
1 回复
Rust监控与追踪库metrics-tracing-context使用指南
概述
metrics-tracing-context是一个专门用于在Rust应用中实现上下文感知的指标收集和分布式追踪集成的库。它通过将metrics和tracing两个生态系统的功能结合起来,为微服务架构提供完整的可观测性解决方案。
核心特性
- 上下文感知的指标收集
- 无缝集成分布式追踪
- 支持异步运行时
- 与主流监控系统兼容
安装方法
在Cargo.toml中添加依赖:
[dependencies]
metrics-tracing-context = "0.3"
tracing = "0.1"
metrics = "0.21"
基本用法
1. 初始化设置
use metrics_tracing_context::{MetricsLayer, TracingContextLayer};
use tracing_subscriber::prelude::*;
fn setup_telemetry() {
let metrics_layer = MetricsLayer::new();
let tracing_layer = TracingContextLayer::new();
tracing_subscriber::registry()
.with(metrics_layer)
.with(tracing_layer)
.init();
}
2. 创建带上下文的指标
use metrics::{counter, histogram};
use tracing::{info_span, Instrument};
async fn process_request() {
let span = info_span!("request_processing");
let _guard = span.enter();
// 这些指标会自动附加追踪上下文
counter!("requests.total").increment(1);
let start = std::time::Instant::now();
// 业务逻辑处理
histogram!("request.duration").record(start.elapsed());
}
3. 分布式追踪集成示例
use tracing::{info, warn};
use metrics::gauge;
#[tracing::instrument]
async fn handle_user_request(user_id: u64) -> Result<(), Box<dyn std::error::Error>> {
gauge!("active_requests").increment(1.0);
info!("Processing user request");
// 模拟业务处理
if user_id % 2 == 0 {
counter!("requests.even").increment(1);
} else {
counter!("requests.odd").increment(1);
}
gauge!("active_requests").decrement(1.0);
Ok(())
}
4. 自定义标签和上下文
use metrics_tracing_context::with_context;
fn process_with_custom_context() {
let span = tracing::info_span!("custom_operation", user_id = 123, service = "auth");
span.in_scope(|| {
with_context(|| {
counter!("operations.total", "service" => "auth").increment(1);
histogram!("operation.latency").record(0.150);
});
});
}
配置选项
指标前缀配置
use metrics_tracing_context::MetricsLayerBuilder;
let layer = MetricsLayerBuilder::new()
.with_prefix("myapp")
.with_default_tags(vec![("env", "production")])
.build();
过滤设置
let layer = MetricsLayerBuilder::new()
.with_filter(|metadata| {
metadata.target().starts_with("myapp::")
})
.build();
最佳实践
- 上下文传播:确保在所有异步边界正确传播追踪上下文
- 标签管理:合理使用标签维度,避免基数爆炸问题
- 性能考虑:在高频操作中注意指标收集的开销
- 错误处理:为关键操作添加错误计数指标
集成示例
与Prometheus集成
use metrics_exporter_prometheus::PrometheusBuilder;
fn setup_prometheus() {
PrometheusBuilder::new()
.install()
.expect("failed to install Prometheus recorder");
setup_telemetry();
}
与Jaeger集成
use tracing_subscriber::EnvFilter;
use tracing_jaeger::JaegerLayer;
use opentelemetry::global;
fn setup_jaeger() {
global::set_text_map_propagator(opentelemetry_jaeger::Propagator::new());
let tracer = opentelemetry_jaeger::new_pipeline()
.install_simple()
.expect("failed to install Jaeger tracer");
let jaeger_layer = JaegerLayer::new(tracer);
tracing_subscriber::registry()
.with(EnvFilter::from_default_env())
.with(jaeger_layer)
.with(MetricsLayer::new())
.init();
}
完整示例demo
//! 完整的metrics-tracing-context使用示例
use metrics::{counter, gauge, histogram};
use metrics_exporter_prometheus::PrometheusBuilder;
use metrics_tracing_context::{MetricsLayer, TracingContextLayer};
use tracing::{info, info_span, Instrument};
use tracing_subscriber::prelude::*;
// 初始化遥测系统
fn setup_telemetry() {
// 配置Prometheus导出器
PrometheusBuilder::new()
.install()
.expect("Failed to install Prometheus recorder");
// 设置metrics和tracing层
let metrics_layer = MetricsLayer::new();
let tracing_layer = TracingContextLayer::new();
tracing_subscriber::registry()
.with(metrics_layer)
.with(tracing_layer)
.init();
info!("Telemetry system initialized");
}
// 处理用户请求的异步函数
#[tracing::instrument]
async fn handle_user_request(user_id: u64) -> Result<(), Box<dyn std::error::Error>> {
// 记录活跃请求数
gauge!("app.active_requests").increment(1.0);
info!("Processing request for user {}", user_id);
// 记录请求总数
counter!("app.requests.total").increment(1);
let start = std::time::Instant::now();
// 模拟业务处理逻辑
tokio::time::sleep(std::time::Duration::from_millis(100)).await;
// 根据用户ID奇偶性记录不同指标
if user_id % 2 == 0 {
counter!("app.requests.even").increment(1);
info!("Even user ID processed");
} else {
counter!("app.requests.odd").increment(1);
info!("Odd user ID processed");
}
// 记录请求处理时长
histogram!("app.request.duration_ms").record(start.elapsed().as_millis() as f64);
// 减少活跃请求数
gauge!("app.active_requests").decrement(1.0);
Ok(())
}
// 自定义上下文处理示例
fn process_with_custom_attributes() {
let span = info_span!("custom_processing", user_type = "vip", region = "us-west");
span.in_scope(|| {
metrics_tracing_context::with_context(|| {
counter!("app.custom_operations", "user_type" => "vip", "region" => "us-west")
.increment(1);
histogram!("app.custom_latency").record(0.250);
});
});
}
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 初始化遥测系统
setup_telemetry();
info!("Starting application");
// 模拟处理多个用户请求
for user_id in 1..=5 {
handle_user_request(user_id).await?;
}
// 执行自定义上下文操作
process_with_custom_attributes();
info!("Application completed");
Ok(())
}
#[cfg(test)]
mod tests {
use super::*;
#[tokio::test]
async fn test_user_request_handling() {
setup_telemetry();
let result = handle_user_request(1).await;
assert!(result.is_ok());
let result = handle_user_request(2).await;
assert!(result.is_ok());
}
}
这个库通过统一指标收集和分布式追踪,为Rust应用提供了完整的可观测性解决方案,特别适合微服务架构下的监控需求。