# Revoke Trace
Revoke 分布式追踪模块,提供基于 OpenTelemetry 的追踪功能。
## 功能特性
- **OpenTelemetry 兼容**:完全兼容 OpenTelemetry 标准
- **OTLP 导出器支持**:使用 OpenTelemetry Protocol 导出追踪数据
- **灵活的采样策略**:
- 始终采样
- 从不采样
- 概率采样
- 基于 Trace ID 的确定性采样
- 自定义采样函数
- **W3C TraceContext 传播**:支持标准的追踪上下文传播
- **与 Rust tracing 生态系统集成**:无缝集成 tracing 和 tracing-subscriber
## 安装
```toml
[dependencies]
revoke-trace = { version = "0.1.0", features = ["otlp"] }
```
### Feature 标志
- `otlp`: 启用 OTLP 导出器(默认)
## 快速开始
```rust
use revoke_trace::{init_tracer, shutdown_tracer, tracer::TracerConfig};
use tracing::{info, instrument};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 配置追踪器
let config = TracerConfig {
service_name: "my-service".to_string(),
service_version: "1.0.0".to_string(),
environment: "production".to_string(),
..Default::default()
};
// 初始化全局追踪器
init_tracer(config).await?;
// 使用 tracing 宏
my_function().await;
// 关闭追踪器
shutdown_tracer().await?;
Ok(())
}
#[instrument]
async fn my_function() {
info!("Hello from my function");
}
```
## 高级用法
### 自定义采样器
```rust
use revoke_trace::{
sampler::{TraceSampler, SamplingStrategy},
tracer::TracerConfig,
};
let config = TracerConfig {
sampler: TraceSampler::probability(0.1), // 10% 采样率
..Default::default()
};
// 或使用自定义采样逻辑
let custom_sampler = TraceSampler::new(SamplingStrategy::Custom(Arc::new(
|trace_id, span_name| {
// 自定义采样逻辑
if span_name.contains("health") {
SamplingDecision::Drop // 不采样健康检查
} else {
SamplingDecision::RecordAndSample
}
}
)));
```
### 手动创建 Span
```rust
use revoke_trace::span::{SpanBuilder, SpanKind};
let span = SpanBuilder::new("http_request")
.with_kind(SpanKind::Server)
.with_attribute("http.method", "GET")
.with_attribute("http.url", "/api/users")
.with_attribute("http.status_code", "200")
.start();
// 在 span 的作用域内执行代码
let _guard = span.enter();
// ... 你的代码 ...
```
### 追踪上下文传播
```rust
use revoke_trace::{
propagator::{TracePropagator, HttpHeaders},
context::TraceContextExt,
};
// 注入追踪上下文到 HTTP 头
let mut headers = HttpHeaders::new();
let propagator = TracePropagator::w3c();
propagator.inject(¤t_context, &mut headers);
// 从 HTTP 头提取追踪上下文
let context = propagator.extract(&headers);
```
### 使用不同的导出器
```rust
use revoke_trace::{
exporter::{TraceExporter, ExporterConfig},
tracer::{TracerConfig, TracerBuilder},
};
// OTLP 导出器(推荐)
let exporter_config = ExporterConfig {
endpoint: "http://localhost:4317".to_string(),
..Default::default()
};
let config = TracerConfig {
exporter_config,
..Default::default()
};
// 控制台导出器(调试用)
let tracer = TracerBuilder::new("debug-service")
.with_logging(true)
.build()
.await?;
```
## 配置选项
### TracerConfig
| `service_name` | `String` | `"revoke-service"` | 服务名称 |
| `service_version` | `String` | 当前版本 | 服务版本 |
| `environment` | `String` | `"development"` | 部署环境 |
| `sampler` | `TraceSampler` | 始终采样 | 采样策略 |
| `exporter_config` | `ExporterConfig` | OTLP 默认配置 | 导出器配置 |
| `enable_logging` | `bool` | `true` | 是否启用日志集成 |
| `log_filter` | `String` | `"info"` | 日志级别过滤器 |
### ExporterConfig
| `endpoint` | `String` | `"http://localhost:4317"` | 导出端点 |
| `timeout` | `Duration` | 10秒 | 导出超时 |
| `use_tls` | `bool` | `false` | 是否使用 TLS |
| `headers` | `Vec<(String, String)>` | 空 | 自定义头部 |
## 环境变量
支持通过环境变量配置:
- `RUST_LOG`: 设置日志级别(例如:`info`, `debug`, `trace`)
- `OTEL_SERVICE_NAME`: 覆盖服务名称
- `OTEL_EXPORTER_OTLP_ENDPOINT`: 覆盖 OTLP 端点
## 与 OpenTelemetry Collector 集成
推荐使用 OpenTelemetry Collector 作为追踪数据的中转站:
```yaml
# otel-collector-config.yaml
receivers:
otlp:
protocols:
grpc:
endpoint: 0.0.0.0:4317
http:
endpoint: 0.0.0.0:4318
processors:
batch:
exporters:
# 导出到支持 OTLP 的后端(如 Jaeger、Zipkin、Tempo 等)
otlp:
endpoint: jaeger:4317
tls:
insecure: true
# 导出到 Prometheus
prometheus:
endpoint: "0.0.0.0:8889"
service:
pipelines:
traces:
receivers: [otlp]
processors: [batch]
exporters: [otlp]
metrics:
receivers: [otlp]
processors: [batch]
exporters: [prometheus]
```
## 最佳实践
1. **使用结构化属性**:为 span 添加有意义的属性,遵循 OpenTelemetry 语义约定
2. **合理设置采样率**:在生产环境中使用适当的采样率以平衡可观察性和性能
3. **避免敏感数据**:不要在 span 属性中包含敏感信息
4. **使用 instrument 宏**:优先使用 `#[instrument]` 宏而不是手动创建 span
5. **正确关闭**:确保在应用退出前调用 `shutdown_tracer()` 以刷新所有待处理的 span
## 故障排除
### 没有看到追踪数据
1. 检查导出器端点是否正确
2. 确认 OpenTelemetry Collector 或后端服务正在运行
3. 检查采样策略是否过于严格
4. 查看日志中的错误信息
### 性能问题
1. 调整采样率
2. 使用批量导出器
3. 增加导出超时时间
4. 考虑使用异步导出
## 示例
查看 `examples/` 目录获取更多示例:
- `basic.rs`: 基本用法
- `custom_sampler.rs`: 自定义采样器
- `propagation.rs`: 上下文传播
- `multi_service.rs`: 多服务追踪
## License
MIT