跳转至

OpenTelemetry Rust SDK

本文采用 SDK Instrumentation:在应用代码中初始化 SDK、创建 Span 并配置 Exporter,通过 DataKit 将链路发送到 观测云。这不是零代码注入,安装依赖或设置环境变量不会自动采集所有框架调用。本文仅启用 Trace,不涉及 Kubernetes。

Rust + OpenTelemetry SDK -> OTLP/HTTP -> DataKit -> 观测云

前置条件

  • 安装 Rust stable 工具链和 Cargo;以下固定使用 OpenTelemetry 0.31.0,建议使用当前稳定工具链,并将 Cargo.lock 纳入应用版本管理。
  • 示例使用同步 main、阻塞 HTTP 客户端和后台批量导出线程,不需要 Tokio。
  • 已安装 DataKit,并使用目标工作空间的安装命令配置好上报地址和 Token;应用可访问 DataKit HTTP 端口 9529

一、开启 OpenTelemetry 采集器

在 DataKit 主机上进入配置目录。仅在配置不存在时复制示例,已有文件请直接调整:

cd /usr/local/datakit/conf.d/opentelemetry
sudo cp -n opentelemetry.conf.sample opentelemetry.conf

确认 opentelemetry.conf 中包含以下配置。自定义标签通过 customer_tags 保留:

[[inputs.opentelemetry]]
  customer_tags = ["team", "app.operation"]

  [inputs.opentelemetry.http]
    http_status_ok = 200
    trace_api = "/otel/v1/traces"
    metric_api = "/otel/v1/metrics"
    logs_api = "/otel/v1/logs"

本机接入使用 127.0.0.1:9529。跨主机接入时,在 DataKit 主配置 datakit.conf[http_api].listen 中设置应用可访问的监听地址,并限制网络访问范围。HTTP 监听地址不在采集器文件中设置。

重启并检查 DataKit:

sudo datakit service restart
curl http://127.0.0.1:9529/v1/ping

/v1/ping 只验证 HTTP 服务可达,不代表链路已入库。完整说明参见 OpenTelemetry 采集器。DataKit 负责工作空间认证,示例应用不直接配置工作空间 Token。

二、应用接入 OpenTelemetry

安装依赖

在空目录中创建示例项目,然后将 Cargo.toml 设置为以下内容。已有项目请合并依赖,不要覆盖原有配置:

cargo new otel-rust-demo
cd otel-rust-demo
[package]
name = "otel-rust-demo"
version = "0.1.0"
edition = "2021"

[dependencies]
opentelemetry = { version = "=0.31.0", default-features = false, features = ["trace"] }
opentelemetry_sdk = { version = "=0.31.0", default-features = false, features = ["trace"] }
opentelemetry-otlp = { version = "=0.31.0", default-features = false, features = ["trace", "http-proto", "reqwest-blocking-client"] }

初始化 SDK 并创建 Span

将以下内容保存为 src/main.rs。SDK 在启动时初始化一次,checkout 下创建子 Span db.lookup,退出前等待批量导出:

use opentelemetry::{
    global,
    trace::{TraceContextExt, Tracer},
    KeyValue,
};
use opentelemetry_otlp::{Protocol, SpanExporter, WithExportConfig};
use opentelemetry_sdk::{
    propagation::TraceContextPropagator,
    trace::{Sampler, SdkTracerProvider},
    Resource,
};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let exporter = SpanExporter::builder()
        .with_http()
        .with_protocol(Protocol::HttpBinary)
        .build()?;

    let provider = SdkTracerProvider::builder()
        .with_batch_exporter(exporter)
        .with_resource(Resource::builder().build())
        .with_sampler(Sampler::ParentBased(Box::new(
            Sampler::TraceIdRatioBased(1.0),
        )))
        .build();

    global::set_text_map_propagator(TraceContextPropagator::new());
    global::set_tracer_provider(provider.clone());
    let tracer = global::tracer("otel-rust-demo");

    tracer.in_span("checkout", |_cx| {
        tracer.in_span("db.lookup", |cx| {
            cx.span().set_attribute(KeyValue::new("app.operation", "lookup"));
        });
    });

    provider.shutdown()?;
    Ok(())
}

构建与运行

在启动应用的同一终端配置以下参数。跨主机时将 127.0.0.1 替换为实际 DataKit 地址:

export OTEL_SERVICE_NAME="order-service"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=prod,service.version=1.0.0,team=backend"
export OTEL_EXPORTER_OTLP_TRACES_ENDPOINT="http://127.0.0.1:9529/otel/v1/traces"

cargo run

第一次运行会下载并编译依赖;后续可执行 cargo build --release 构建生产二进制。长期服务应保留 Provider,在停止接收请求并结束正在处理的 Span 后调用 shutdown()

三、数据上报参数

参数或配置 说明
OTEL_SERVICE_NAME service.name;示例使用 order-service,应设置为稳定的服务名。
OTEL_RESOURCE_ATTRIBUTES 逗号分隔的资源属性。示例设置环境、版本和 team;自定义字段应加入 DataKit customer_tags
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT Trace 专用完整地址:http://127.0.0.1:9529/otel/v1/traces。优先于通用基础地址。
OTEL_EXPORTER_OTLP_ENDPOINT 可选基础地址:http://127.0.0.1:9529/otel。未设置 Trace 专用地址时,由 Exporter 追加 /v1/traces
OTEL_EXPORTER_OTLP_HEADERS 可选 OTLP 请求头,格式为 key=value,key2=value2。只有接收端或代理要求认证时才配置。

本例用 .with_http()Protocol::HttpBinary 在代码中选择 HTTP/Protobuf;修改 OTEL_EXPORTER_OTLP_PROTOCOL 不会把该示例自动切换到 gRPC。改用 gRPC 需要启用 grpc-tonic、改用 .with_tonic() 并提供合适的 Tokio 运行时。

采样在代码中配置为 ParentBased + 根链路比例 1.0,遵循父 Span 的采样决定。生产环境可把示例中的比例改为 0.1,约采样 10% 的根链路。本例显式设置采样器,不依赖 OTEL_TRACES_SAMPLEROTEL_TRACES_SAMPLER_ARG

示例显式创建 Trace 导出管道,OTEL_TRACES_EXPORTER 不负责选择或关闭它。未创建 Metric、Log Provider,因此不会因设置 OTEL_METRICS_EXPORTEROTEL_LOGS_EXPORTER 就启用对应信号。日志可另行使用 DataKit 日志文件采集

上下文传播与业务接入

本例注册 W3C TraceContext 传播器,但不会自动拦截网络请求。接入 HTTP/RPC 时,需要在服务端通过 Extractor 提取上游上下文并作为新 Span 的父级,在客户端通过 Injector 注入 traceparenttracestate。同步示例中的 in_span 不应直接跨 .await 使用;异步任务应使用 FutureExt::with_context 等方式传播上下文。使用 tracing 的应用还需配置兼容版本的 tracing-opentelemetry Layer。

验证与排查

  1. 执行示例后,在 观测云 应用性能监测中按 order-service 查询链路,确认有 checkout 与其子 Span db.lookup
  2. 无数据时,检查采集器是否启用、应用环境变量是否生效、HTTP 路径是否包含 /otel/v1/traces,以及 DataKit 与应用的导出错误。
  3. 确认 Span 已结束且 Provider 在退出前完成刷新。强制退出或使用根链路比例 0 会导致无法看到预期数据;网络连通不等于导出成功。

参考文档

文档评价

文档内容是否对您有帮助?