本文翻译自 Implementing OpenTelemetry in a Rust application for performance monitoring,原载于 Hacker News。

Rust 是一门注重性能和安全性的多范式编程语言,尤其在安全并发方面表现出色。在生产环境中运行 Rust 应用时,如何有效监控其性能表现是一个关键问题。OpenTelemetry 提供了一套完整的解决方案,可以帮助我们追踪 Rust 应用的性能问题和潜在 bug。
OpenTelemetry 是什么?
OpenTelemetry 是云原生计算基金会(CNCF)旗下的开源项目,旨在标准化遥测数据(telemetry data)的生成和收集。遥测数据包括三个核心组成部分:
- Logs(日志):应用运行时的文本记录
- Metrics(指标):数值化的性能数据
- Traces(追踪):请求在分布式系统中的完整调用链

OpenTelemetry 库用于插桩应用代码,生成遥测数据后发送到可观测性工具进行存储和可视化
OpenTelemetry 最大的优势在于厂商中立——你不会被锁定在任何特定的监控工具上,可以自由选择后端分析平台。这为构建可观测性框架提供了坚实的基础。
为什么选择 SigNoz?
在本教程中,我们使用 SigNoz 作为后端分析工具。SigNoz 是一个全栈开源 APM(应用性能监控)工具,具有以下特点:
- 原生支持 OpenTelemetry,直接使用 OTLP 数据格式
- 提供开箱即用的应用指标、日志和追踪图表
- 强大的查询和可视化能力
- 支持 self-host 或云服务两种部署方式
实战:为 Rust 应用集成 OpenTelemetry
前置准备
首先,注册一个 SigNoz Cloud 账户。你可以获得 30 天的免费试用,体验所有功能。当然,作为开源项目,你也可以选择 self-host 部署。
注册完成后,你会收到访问 SigNoz UI 的 URL 和相关的认证信息。
Step 1: 配置 Cargo.toml 依赖
在你的 Cargo.toml 文件中添加 OpenTelemetry 相关依赖:
[dependencies]
opentelemetry = { version = "0.18.0", features = ["rt-tokio", "metrics", "trace"] }
opentelemetry-otlp = { version = "0.11.0", features = ["trace", "metrics"] }
opentelemetry-semantic-conventions = { version = "0.10.0" }
opentelemetry-proto = { version = "0.1.0"}
tokio = { version = "1", features = ["full"] }
tonic = { version = "0.8.2", features = ["tls-roots"] }
dotenv = "0.15"
各依赖说明:
opentelemetry: 核心库,提供 tracing、metrics 等功能opentelemetry-otlp: OTLP 协议导出器,负责将追踪数据发送到 SigNozopentelemetry-semantic-conventions: 定义标准的追踪属性名称(如service.name)tokio: 异步运行时,OpenTelemetry 的异步操作依赖它tonic: 用于通过 gRPC 发送追踪数据dotenv: 从.env文件加载环境变量,保护敏感配置
Step 2: 在 main.rs 中导入模块
use opentelemetry::global::shutdown_tracer_provider;
use opentelemetry::sdk::Resource;
use opentelemetry::trace::TraceError;
use opentelemetry::{
global, sdk::trace as sdktrace,
trace::{TraceContextExt, Tracer},
Context, Key, KeyValue,
};
use opentelemetry_otlp::WithExportConfig;
use tonic::metadata::{MetadataMap, MetadataValue};
use dotenv::dotenv;
Step 3: 初始化 Tracer
创建一个函数来初始化 OpenTelemetry 管道:
fn init_tracer() -> Result<sdktrace::Tracer, TraceError> {
let signoz_ingestion_key = std::env::var("SIGNOZ_INGESTION_KEY")
.expect("SIGNOZ_INGESTION_KEY not set");
let mut metadata = MetadataMap::new();
metadata.insert(
"signoz-ingestion-key",
MetadataValue::from_str(&signoz_ingestion_key).unwrap(),
);
opentelemetry_otlp::new_pipeline()
.tracing()
.with_exporter(
opentelemetry_otlp::new_exporter()
.tonic()
.with_metadata(metadata)
.with_endpoint(std::env::var("SIGNOZ_ENDPOINT").expect("SIGNOZ_ENDPOINT not set")),
)
.with_trace_config(
sdktrace::config().with_resource(Resource::new(vec![
KeyValue::new(
opentelemetry_semantic_conventions::resource::SERVICE_NAME,
std::env::var("APP_NAME").expect("APP_NAME not set"),
),
])),
)
.install_batch(opentelemetry::runtime::Tokio)
}
关键点解析:
signoz_ingestion_key: 从环境变量获取 SigNoz 的认证密钥MetadataMap: 将认证信息添加到遥测数据的元数据中with_exporter: 配置导出器,指定 SigNoz 的端点地址with_trace_config: 设置追踪配置,包括服务名称install_batch: 以批处理模式安装 tracer,使用 Tokio 作为异步运行时
Step 4: 创建 .env 配置文件
在项目根目录创建 .env 文件:
PORT=1337
APP_NAME=rust-sample
SIGNOZ_ENDPOINT=https://ingest.us.signoz.cloud:443/v1/traces
SIGNOZ_INGESTION_KEY=XXXXXXXXXX
配置说明:
PORT: 应用运行的端口APP_NAME: 你的 Rust 应用名称,会在 SigNoz 中显示SIGNOZ_INGESTION_KEY: SigNoz 提供的认证密钥(需要在 SigNoz 控制台生成)SIGNOZ_ENDPOINT: 数据接收端点,根据你选择的区域不同:
| 区域 | 端点 |
|---|---|
| US | ingest.us.signoz.cloud:443/v1/traces |
| IN | ingest.in.signoz.cloud:443/v1/traces |
| EU | ingest.eu.signoz.cloud:443/v1/traces |
Step 5: 在 main 函数中初始化
将 main 函数改为异步,并加载配置:
#[tokio::main]
async fn main() {
dotenv().ok();
let _ = init_tracer();
let tracer = global::tracer("global_tracer");
let _cx = Context::new();
tracer.in_span("operation", |cx| {
let span = cx.span();
span.set_attribute(Key::new("KEY").string("value"));
span.add_event(
format!("Operations"),
vec![
Key::new("SigNoz is").string("Awesome"),
],
);
});
shutdown_tracer_provider()
}
Span 操作说明:
tracer.in_span: 创建名为 “operation” 的 span,代表一个操作span.set_attribute: 为 span 设置属性,用于过滤和分组span.add_event: 添加事件,记录 span 生命周期中的特定时间点shutdown_tracer_provider: 关闭 tracer,确保所有数据发送完毕
Step 6: 运行应用
cargo run
打开浏览器访问 http://localhost:1337,你的应用应该正常运行了。

Step 7: 生成遥测数据
访问应用的首页,或者使用 curl 发送请求来生成追踪数据:
curl -d "name=test&number=42" \
-H "Content-Type: application/x-www-form-urlencoded" \
-X POST http://localhost:1337/post
在 SigNoz 中监控应用
现在登录 SigNoz 控制台,你可以看到应用的遥测数据。
Services 视图
在 Services 标签页,你会看到你的 Rust 应用出现在被监控的服务列表中:

Traces 视图
进入 Traces 标签页,选择你的 rust-app,可以查看追踪数据。你可以使用各种过滤器(标签、状态码、服务名、操作名)来深入分析:

Flamegraph 分析
SigNoz 提供了 Flamegraph(火焰图)和 Gantt 图,让你可以详细了解请求的执行情况,包括每个操作耗时和 span 属性:

点击 Spans 表中的任意 span,可以深入查看追踪详情,了解应用在不同操作和服务间的性能表现。
个人经验分享
在 Rust 项目中集成 OpenTelemetry 有几个值得注意的点:
- 异步运行时选择:确保 OpenTelemetry 的异步特性与你使用的运行时(Tokio、async-std 等)兼容
- 版本一致性:OpenTelemetry 的各个 crate 版本需要保持兼容,建议使用相同的 minor 版本
- 资源管理:记得在应用退出时调用
shutdown_tracer_provider(),否则可能丢失最后的遥测数据 - 性能影响:虽然 OpenTelemetry 设计轻量,但在高吞吐场景下建议采样而非全量追踪
总结
使用 OpenTelemetry 为 Rust 应用实现可观测性是一个明智的选择。它不仅提供了标准化的遥测数据收集方式,还让你拥有选择后端工具的自由。配合 SigNoz 这样的开源 APM 工具,你可以构建完整的监控体系,确保应用在生产环境中的稳定运行。
关键要点:
- OpenTelemetry 是 CNCF 旗下的开源标准,支持 logs、metrics、traces 三种遥测数据
- Rust 的 OpenTelemetry 集成需要配置 OTLP exporter 和适当的异步运行时
- SigNoz 提供开箱即用的可视化能力,支持 self-host 和云服务两种部署方式
- Span 是追踪的核心单元,通过属性和事件可以添加丰富的上下文信息
OpenTelemetry 是云原生应用可观测性的未来,拥有活跃的社区支持,覆盖了广泛的技术栈和框架。使用 OpenTelemetry,工程团队可以放心地为多语言、分布式应用实现可观测性。