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 日

1220Web 编程

Download history 160/week @ 2024-04-08 159/week @ 2024-04-15 137/week @ 2024-04-22 185/week @ 2024-04-29 73/week @ 2024-05-06 44/week @ 2024-05-13 27/week @ 2024-05-20 19/week @ 2024-05-27 23/week @ 2024-06-03 19/week @ 2024-06-10 67/week @ 2024-06-17 111/week @ 2024-06-24 65/week @ 2024-07-01 62/week @ 2024-07-08 58/week @ 2024-07-15 87/week @ 2024-07-22

每月下载 272

MIT 许可证

18KB
165

crates-badge docs-badge Crates.io

Datadog 为 Rust 服务提供跟踪和日志关联。

Datadog 为 Python 提供官方支持,包括各种 SDK 和其他工具(如 Python 的 ddtrace 库)用于在 Python 应用程序中进行跟踪和日志记录。

对于 Rust,他们没有类似的支持。但是,他们支持日志和跟踪的 OpenTelemetry 格式。此 crate 包含连接 OpenTelemetry 和 Datadog 之间差距所需的粘合剂。

功能

ddtrace 有以下功能

  1. 跟踪:构建发送跟踪到 Datadog 代理的 OpenTelemetry 跟踪器/层的工具
  2. 日志关联:将跟踪 ID 和跨度 ID 转换为 Datadog 本地格式并注入到 dd.trace_iddd.span_id 字段中的日志格式化程序 (更多信息)
  3. 传播:一个实用函数,用于将 Datadog 传播者设置为全局传播者
  4. 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