阿里云可观测性与 Datadog 发布 OpenTelemetry Go 自动化探针工具

发布: (2026年3月18日 GMT+8 10:57)
7 分钟阅读
原文: Dev.to

Source: Dev.to

(请提供您希望翻译的正文内容,我将为您翻译成简体中文并保持原有的格式、Markdown 语法以及技术术语不变。)

工作原理

自动化插桩工具利用 Go 编译器的 -toolexec 参数。-toolexec 会拦截 go 命令并用我们的插桩工具替换它,从而让我们有机会在编译前分析并修改源码。整个过程分为两个阶段:

1. 依赖分析

  • 编译开始前,工具会运行 go build -n 来分析构建流程,检测项目中使用的第三方库(例如 net/httpgrpcredis)。
  • 然后自动生成一个名为 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 的微服务来说,手动添加此类代码在工作量和维护方面是灾难性的

自动仪表化

  1. 下载工具 – 从 Release 页面1获取二进制文件。

  2. 编译应用程序

    ./otel-linux-amd64 go build -o myapp
  3. 配置并运行

    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]。

追踪分析

Tracing analysis illustration

连续剖析

该方案已在多个领域的客户中成功验证,包括电子商务、短视频、AI 视频和汽车行业。在看到它为用户带来的巨大价值并确认其稳定性和可行性后,我们决定将其核心能力贡献给 OpenTelemetry 社区,希望它能够成为一种包容性的技术。

我们还与观测领域的领先供应商 Datadog 合作,共同推广并最终促成了该官方项目的诞生 [1]。

该项目目前正处于积极开发中。欢迎大家尝试、提供反馈,并为构建更好的云原生观测生态系统贡献力量。

参考文献

  1. OpenTelemetry Go 编译时插桩项目
  2. 发布链接
  3. 阿里云 ARMS Go Agent(商业版)
  4. 自定义扩展

Footnotes

  1. Release page – https://github.com/open-telemetry/opentelemetry-go-compile-instrumentation/releases

  2. Alibaba Cloud Observability – ARMS documentation (internal link)

0 浏览
Back to Blog

相关文章

阅读更多 »