阿里云可观测性与 Datadog 发布 OpenTelemetry Go 自动化探针工具
Source: Dev.to
(请提供您希望翻译的正文内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。)
工作原理
自动化插桩工具利用 Go 编译器的 -toolexec 参数。-toolexec 会拦截 go 命令并用我们的插桩工具替换它,从而让我们有机会在编译前分析并修改源码。整个过程分为两个阶段:
1. 依赖分析
- 编译开始前,工具会运行
go build -n来分析构建流程,检测项目中使用的第三方库(例如net/http、grpc、redis)。 - 然后自动生成一个名为
otel.runtime.go的文件,并将相应的 Hook 代码(监控逻辑)导入到构建依赖中。
2. 代码注入
- 当编译器处理目标函数时,工具再次使用
-toolexec拦截编译,并修改函数代码。 - 在函数入口点插入一段 Trampoline 代码片段,跳转到预先编写好的 Hook 函数。
Hook 执行三个动作:
| 阶段 | Hook 的行为 |
|---|---|
| Before(函数入口) | 记录开始时间,提取上下文信息(例如 HTTP 头部),并启动一个 span。 |
| During(原业务逻辑) | 按原样执行函数体,不做修改。 |
| After(函数退出) | 捕获返回值或 panic,结束 span,并记录持续时间。 |
由于插桩直接编译进二进制文件,它只会产生 零运行时开销(除监控逻辑本身不可避免的执行时间外)。与 eBPF 不同,它不需要内核空间 ↔ 用户空间的切换;也不同于 Java Agent,它不需要运行时加载步骤。
HTTP 仪表化示例
简单 HTTP 服务器(无仪表化)
package main
import (
"log"
"net/http"
)
func main() {
http.HandleFunc("/greet", func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("Hello, OpenTelemetry!"))
})
log.Fatal(http.ListenAndServe(":8080", nil))
}
手动仪表化
package main
import (
"context"
"log"
"net/http"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/sdk/trace"
)
func initTracer() func(context.Context) error {
// ... dozens of lines of initialization code ...
return func(ctx context.Context) error { return nil }
}
func main() {
// 1️⃣ 初始化 tracer。
shutdown := initTracer()
defer shutdown(context.Background())
// 2️⃣ 包装处理器。
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
// 3️⃣ 手动提取上下文并启动 span。
tracer := otel.Tracer("demo-server")
ctx, span := tracer.Start(r.Context(), "GET /greet")
defer span.End()
// 4️⃣ 如有需要,记录属性。
span.SetAttributes(attribute.String("http.method", "GET"))
// 5️⃣ 业务逻辑。
_, _ = w.Write([]byte("Hello, OpenTelemetry!"))
// 6️⃣(可选)将派生的上下文用于下游调用。
_ = ctx
})
// 7️⃣ 启动服务器。
log.Fatal(http.ListenAndServe(":8080", handler))
}
对于拥有数百或数千个 API 的微服务来说,手动添加此类代码在工作量和维护方面是灾难性的。
自动仪表化
-
下载工具 – 从 Release 页面1获取二进制文件。
-
编译应用程序
./otel-linux-amd64 go build -o myapp -
配置并运行
export OTEL_EXPORTER_OTLP_ENDPOINT="http://localhost:4317" export OTEL_SERVICE_NAME="my-app" ./myapp
编译器会悄悄地将 HTTP 请求监控逻辑“织入”二进制文件。配置好 OpenTelemetry 导出器(例如 Jaeger、控制台)后,运行服务器将自动为 /greet 端点生成并上报追踪数据,包括 URI、持续时间和状态码——无需任何代码更改。
从商业到开源
在大量 eBPF 实践中,我们认识到它的强大,但也发现它在完美处理应用层上下文方面存在困难。更重要的是,用户反馈反复强调手动追踪繁琐、维护成本高的痛点。
为了解决这个问题,我们探索了一种 Go 编译时自动插桩 方案,最初将其发布到阿里云可观测平台的 应用实时监控服务 (ARMS)2。在这个严格的“实验场”中持续迭代,使该方案成熟为一个稳健的开源解决方案,能够为 Go 应用提供 零代码追踪。
参考文献
增强的可观察性功能
该解决方案还扩展了对丰富的高级功能的支持,例如:
- 指标统计
- 运行时监控
- 持续分析
它甚至可以通过自定义扩展功能完成企业内部 SDK 的事件追踪 [4]。
追踪分析

连续剖析
该方案已在多个领域的客户中成功验证,包括电子商务、短视频、AI 视频和汽车行业。在看到它为用户带来的巨大价值并确认其稳定性和可行性后,我们决定将其核心能力贡献给 OpenTelemetry 社区,希望它能够成为一种包容性的技术。
我们还与观测领域的领先供应商 Datadog 合作,共同推广并最终促成了该官方项目的诞生 [1]。
该项目目前正处于积极开发中。欢迎大家尝试、提供反馈,并为构建更好的云原生观测生态系统贡献力量。
参考文献
- OpenTelemetry Go 编译时插桩项目 –
- 发布链接 –
- 阿里云 ARMS Go Agent(商业版) –
- 自定义扩展 –
Footnotes
-
Release page – https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases ↩
-
Alibaba Cloud Observability – ARMS documentation (internal link) ↩