9 个版本
| 0.1.1 | 2023 年 9 月 7 日 | 
|---|---|
| 0.1.0 | 2023 年 9 月 7 日 | 
| 0.0.7 | 2023 年 4 月 3 日 | 
| 0.0.1 | 2023 年 3 月 31 日 | 
1220 在 Web 编程 中
每月下载 272 次
18KB
165 行
Datadog 为 Rust 服务提供跟踪和日志关联。
Datadog 为 Python 提供官方支持,包括各种 SDK 和其他工具(如 Python 的 ddtrace 库)用于在 Python 应用程序中进行跟踪和日志记录。
对于 Rust,他们没有类似的支持。但是,他们支持日志和跟踪的 OpenTelemetry 格式。此 crate 包含连接 OpenTelemetry 和 Datadog 之间差距所需的粘合剂。
功能
ddtrace 有以下功能
- 跟踪:构建发送跟踪到 Datadog 代理的 OpenTelemetry 跟踪器/层的工具
- 日志关联:将跟踪 ID 和跨度 ID 转换为 Datadog 本地格式并注入到 dd.trace_id和dd.span_id字段中的日志格式化程序 (更多信息)
- 传播:一个实用函数,用于将 Datadog 传播者设置为全局传播者
- axum(通过 axum功能启用):重新公开 axum-tracing-opentelemetry 的功能
完整示例
以下是一个使用 ddtrace 的示例,其中启用了 axum 功能,以设置一个将跟踪和日志发送到 Datadog 的 axum 服务。
use std::net::SocketAddr;
use std::time::Duration;
use axum::{routing::get, Router};
use ddtrace::axum::opentelemetry_tracing_layer;
use ddtrace::formatter::DatadogFormatter;
use ddtrace::set_global_propagator;
use ddtrace::tracer::{build_layer, TraceResult};
use tracing_subscriber::layer::SubscriberExt;
use tracing_subscriber::util::SubscriberInitExt;
#[tokio::main]
async fn main() -> TraceResult<()> {
    let service_name = std::env::var("DD_SERVICE").unwrap_or("my-service".to_string());
    let tracing_layer = build_layer(&service_name)?;
    tracing_subscriber::registry()
        .with(tracing_subscriber::EnvFilter::new(
            std::env::var("RUST_LOG").unwrap_or_else(|_| "info".into()),
        ))
        .with(
            tracing_subscriber::fmt::layer()
                .json()
                .event_format(DatadogFormatter),
        )
        .with(tracing_layer)
        .init();
    set_global_propagator();
    let app = Router::new()
        .route("/", get(root))
        .layer(opentelemetry_tracing_layer())
        .route("/health", get(health));
    let addr = SocketAddr::from(([0, 0, 0, 0], 3025));
    tracing::info!("listening on {}", addr);
    axum::Server::bind(&addr)
        .serve(app.into_make_service())
        .with_graceful_shutdown(ddtrace::axum::shutdown_signal())
        .await
        .unwrap();
    Ok(())
}
async fn root() -> &'static str {
    do_something().await;
    "Hello, World!"
}
#[tracing::instrument]
async fn do_something() {
    tokio::time::sleep(Duration::from_millis(120)).await;
    do_something_else().await;
    tracing::info!("in the middle of doing something");
    tokio::time::sleep(Duration::from_millis(10)).await;
    do_something_else().await;
    tokio::time::sleep(Duration::from_millis(20)).await;
}
#[tracing::instrument]
async fn do_something_else() {
    tokio::time::sleep(Duration::from_millis(40)).await;
}
async fn health() -> &'static str {
    "healthy"
}
请参阅完整的项目,其中包含 Cargo.toml,请在此处查看。
Datadog 代理设置
Datadog 代理需要配置为通过 gRPC 接收 OTel 跟踪。请参考 Datadog 文档设置代理。
更多上下文和理由
导出跟踪
对于追踪,官方的Datadog代理可以处理OTel追踪数据,只需正确设置环境变量。追踪数据可以通过HTTP或gRPC发送。更多相关信息请参阅这里。
OpenTelemetry有一个官方的Rust crate,其中包含对主要格式/提供程序的扩展。这包括一个Datadog导出器。我们发现这个导出器的可靠性不如将数据发送到Datadog代理OTel端点的标准OTel导出器。这个crate是在OTel导出器的基础上构建的。
传播
两种常用的传播标准是B3(OpenZipkin的传播风格)和Jaeger。OpenTelemetry支持这两种。
大多数Datadog SDK都支持B3和Datadog本地的传播风格。例如,Python的ddtrace库支持B3,但需要显式启用。
为了方便与其他使用官方Datadog SDK编写的服务集成,我们选择了坚持使用Datadog风格的传播而不是B3。这是通过set_global_propagator函数设置的。
Reqwest传播
Python库会自动处理追踪上下文的传播。不幸的是,在Rust中我们需要手动处理。
可以说,HTTP请求中的传播是最常见的需求。这个crate不提供任何额外支持,但我们建议在使用reqwest时使用reqwest-middleware crate来注入必要的头信息。如果您使用ddtrace设置了全局传播器,它将直接生效。
use ddtrace::set_global_propagator;
use reqwest_middleware::{ClientBuilder, ClientWithMiddleware};
use reqwest_tracing::TracingMiddleware;
#[tokio::main]
async fn main() {
    set_global_propagator();
    client = get_http_client();
    
    // configure tracing, setup your app and inject the client
}
fn get_http_client() -> ClientWithMiddleware {
    ClientBuilder::new(reqwest::Client::new())
        .with(TracingMiddleware::default())
        .build()
}
依赖关系
~15–27MB
~392K SLoC