OpenTelemetry Go(otelc)¶
OpenTelemetry Go Compile-Time Instrumentation 使用 otelc 在 Go 编译阶段自动注入 OpenTelemetry SDK 初始化和组件插桩逻辑。应用不需要修改业务代码,只需将原来的 go build 替换为 go tool otelc go build,即可通过 OTLP 将遥测数据上报到 DataKit,并转发至 观测云。
本文以 otelc v1.1.0、主机安装的 DataKit 和 OTLP/gRPC 为例,完成 Go HTTP 服务的 Trace 接入:
说明:
otelc的“零代码”表示业务代码不需要手动引入和初始化 OpenTelemetry SDK,并不表示无需重新构建。已经生成的普通 Go 二进制不能直接附加插桩,必须使用otelc重新编译并部署新产物。
前置条件¶
- Go 1.25 或更高版本;
- 项目使用 Go Module,并且可以通过普通
go build正常编译; - 已安装 DataKit,且 DataKit 已连接到目标 观测云 工作空间;
- Go 应用到 DataKit 的网络可达:OTLP/gRPC 默认使用
4317,OTLP/HTTP 使用 DataKit HTTP 端口9529; - 应用使用的框架或组件已被
otelc v1.1.0支持; - 应用没有重复初始化 OpenTelemetry SDK。需要自行控制 SDK 生命周期的项目应使用 OpenTelemetry Go SDK 接入方式。
本文使用 Linux 主机和 net/http 服务进行说明,不包含 Kubernetes 部署。
一、开启 OpenTelemetry 采集器¶
进入 DataKit 的 OpenTelemetry 采集器目录。如果尚未创建配置文件,复制示例配置:
确认 opentelemetry.conf 至少包含以下配置:
[[inputs.opentelemetry]]
# 需要保留为 观测云 标签的自定义属性白名单。
customer_tags = ["team", "project"]
[inputs.opentelemetry.http]
http_status_ok = 200
trace_api = "/otel/v1/traces"
metric_api = "/otel/v1/metrics"
[inputs.opentelemetry.grpc]
addr = "127.0.0.1:4317"
以上配置对应以下接收地址:
| 协议 | 数据类型 | DataKit 接收地址 |
|---|---|---|
| OTLP/gRPC | Trace、Metric | http://<DataKit-IP>:4317 |
| OTLP/HTTP + Protobuf | Trace | http://<DataKit-IP>:9529/otel/v1/traces |
| OTLP/HTTP + Protobuf | Metric | http://<DataKit-IP>:9529/otel/v1/metrics |
应用与 DataKit 不在同一主机时,将 gRPC 的 addr 调整为应用可访问的监听地址,例如 0.0.0.0:4317,并同步配置防火墙或其他网络访问控制。不要将 OTLP 接收端口直接暴露到公网。
重启 DataKit 使配置生效:
检查 DataKit 及 gRPC 端口:
二、应用接入 OpenTelemetry¶
插桩前检查¶
进入应用的 Go Module 根目录,先确认原始项目可以正常构建:
如果当前目录还没有 go.mod,先初始化 Module:
检查项目是否已经直接依赖 OpenTelemetry SDK 或 Contrib 插桩库:
otelc 会注入 SDK 初始化逻辑。项目中已有另一套 SDK 初始化或重复的 HTTP instrumentation 时,可能产生重复 Span、Provider 被覆盖或依赖版本冲突。本文推荐业务代码不直接接入 SDK。
安装 otelc¶
使用 Go tool 指令安装并固定 otelc v1.1.0:
确认工具版本:
预期输出:
生产构建应在 go.mod 和 go.sum 中固定版本,不要使用未固定版本的 @latest。
使用 otelc 编译¶
先保持原有构建参数不变,仅在 go build 前增加 go tool otelc:
带有常用构建参数的示例:
mkdir -p ./bin
go tool otelc go build \
-trimpath \
-ldflags="-s -w" \
-o ./bin/my-service \
./cmd/my-service
otelc go 当前支持 go build、go install 和 go test。第一次插桩构建需要下载并编译 OpenTelemetry 依赖,通常明显慢于普通 go build;看到终端重新出现命令提示符后,才表示构建完成。
构建完成后,.otelc-build/matched.json 中会记录匹配的规则。检查 HTTP 服务端 Hook:
jq -e '[.. | objects | .name?] | index("server_hook") != null' \
.otelc-build/matched.json >/dev/null
注意:发布流程必须部署
go tool otelc go build生成的二进制。后续如果使用普通go build覆盖产物,运行时将不包含自动插桩。
配置 OTLP/gRPC 并启动¶
以下配置只启用 net/http Trace,并通过 OTLP/gRPC 上报到本机 DataKit:
export OTEL_SERVICE_NAME="my-service"
export OTEL_RESOURCE_ATTRIBUTES="deployment.environment.name=prod,service.version=1.0.0,team=backend"
export OTEL_TRACES_EXPORTER="otlp"
export OTEL_METRICS_EXPORTER="none"
export OTEL_LOGS_EXPORTER="none"
export OTEL_EXPORTER_OTLP_PROTOCOL="grpc"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:4317"
export OTEL_EXPORTER_OTLP_INSECURE="true"
export OTEL_GO_ENABLED_INSTRUMENTATIONS="nethttp"
./my-service
运行参数必须配置在插桩后二进制的实际运行环境中,而不只是配置在编译主机上。应用启动后,请求一个由受支持组件处理的接口,以生成可验证的 Span。
生产环境应使用 TLS endpoint,并通过 Secret 管理证书和认证 Header。http://127.0.0.1:4317 仅适用于本机接入。
使用 OTLP/HTTP¶
如需改用 OTLP/HTTP + Protobuf,替换协议和 endpoint:
export OTEL_EXPORTER_OTLP_PROTOCOL="http/protobuf"
export OTEL_EXPORTER_OTLP_ENDPOINT="http://127.0.0.1:9529/otel"
export OTEL_EXPORTER_OTLP_INSECURE="true"
Exporter 会根据数据类型追加 /v1/traces 或 /v1/metrics。仅设置 Trace endpoint 时,也可以直接使用:
三、数据上报参数¶
资源和 Exporter 参数¶
| 环境变量 | 说明 | 建议值或示例 |
|---|---|---|
OTEL_SERVICE_NAME |
观测云 中 APM 服务归属的核心字段 | my-service,必须显式设置 |
OTEL_RESOURCE_ATTRIBUTES |
资源属性,多个 key=value 使用逗号分隔 |
deployment.environment.name=prod,service.version=1.0.0 |
OTEL_TRACES_EXPORTER |
Trace Exporter | 上报到 DataKit 时设置为 otlp |
OTEL_METRICS_EXPORTER |
Metric Exporter | 不采集时设置为 none |
OTEL_LOGS_EXPORTER |
Log Exporter | 不通过 OTLP 采集应用日志时设置为 none |
OTEL_EXPORTER_OTLP_PROTOCOL |
通用 OTLP 协议 | grpc 或 http/protobuf |
OTEL_EXPORTER_OTLP_ENDPOINT |
各 OTLP 信号共用的 endpoint | gRPC:http://datakit-host:4317 |
OTEL_EXPORTER_OTLP_TRACES_ENDPOINT |
仅 Trace 使用的 endpoint,优先于通用值 | HTTP:http://datakit-host:9529/otel/v1/traces |
OTEL_EXPORTER_OTLP_INSECURE |
是否使用非 TLS 连接 | 本地明文连接设置为 true |
OTEL_EXPORTER_OTLP_HEADERS |
OTLP 请求认证 Header | 通过 Secret 注入,不写入代码或镜像 |
插桩、采样和调试参数¶
| 环境变量 | 说明 | 建议值或示例 |
|---|---|---|
OTEL_GO_ENABLED_INSTRUMENTATIONS |
运行时插桩白名单 | HTTP 服务使用 nethttp |
OTEL_GO_DISABLED_INSTRUMENTATIONS |
运行时插桩黑名单 | 按需禁用,例如 redis |
OTEL_TRACES_SAMPLER |
Trace 采样器 | 接入验证使用 parentbased_always_on |
OTEL_TRACES_SAMPLER_ARG |
比例采样参数 | 例如 0.10,配合 parentbased_traceidratio |
OTEL_PROPAGATORS |
Trace Context 传播格式 | tracecontext,baggage |
OTEL_LOG_LEVEL |
otelc 注入运行时的日志级别 |
默认 info,排障时使用 debug |
OTEL_GO_SIMPLE_SPAN_PROCESSOR |
是否逐条立即导出 Span | 仅本地排障时设置为 true |
OTEL_SDK_DISABLED |
是否禁用注入的 SDK | true 会停止采集和上报 |
OTELC_DEBUG |
是否记录详细构建日志 | 排障时设置为 1 |
OTEL_GO_ENABLED_INSTRUMENTATIONS 和 OTEL_GO_DISABLED_INSTRUMENTATIONS 只控制已经编译进二进制的插桩。两个变量同时存在时,先应用白名单,再排除黑名单内容。
生产环境应根据流量和数据预算设置采样率。应用侧采样和 DataKit 侧采样同时开启时,最终保留率会叠加降低,应统一规划采样位置。
支持的组件¶
otelc v1.1.0 内置规则覆盖以下常见组件:
| 类型 | 组件 |
|---|---|
| HTTP | net/http 客户端与服务端、Gin |
| RPC | gRPC 客户端与服务端 |
| 数据库 | database/sql、Redis v9、MongoDB |
| 消息队列 | Kafka Go |
| 云和基础设施 | Kubernetes client-go、AWS SDK for Go v2、Linode Go v2 |
| GenAI | OpenAI Go v1/v2/v3、Anthropic Go SDK |
| 日志关联 | 标准库 log、log/slog、Logrus |
实际支持范围还会受到组件版本和构建方式影响。升级应用依赖或 otelc 后,应重新检查 .otelc-build/matched.json 并执行链路回归测试。
字段映射¶
DataKit OpenTelemetry 采集器会将常见 OpenTelemetry Span Attributes 转换为 观测云 链路字段:
| OpenTelemetry 属性 | DataKit 字段 |
|---|---|
http.request.method |
http_method |
http.response.status_code |
http_status_code |
network.protocol.name |
net_protocol_name |
network.protocol.version |
net_protocol_version |
db.system.name |
db_system |
db.operation.name |
db_operation |
db.query.text |
db_statement |
rpc.system.name |
rpc_system |
rpc.method |
rpc_method |
如需将其他 Attributes 保留为 观测云 标签,可在 DataKit opentelemetry.conf 中配置 customer_tags。不要把用户 ID、订单号等高基数值批量提升为标签,也不要上报密码、Token、完整数据库连接串等敏感信息。
验证接入¶
- 确认工具版本和插桩构建均成功:
- 启动应用,确认日志中出现以下内容,并且没有 OTLP export error:
trace provider initialized with auto-export
OpenTelemetry initialized
HTTP server instrumentation initialized
- 请求应用接口产生 Trace:
- 检查构建规则包含
server_hook:
- 使用 OTLP/gRPC 时,可以在 DataKit 主机观察接收计数是否增长:
curl -fsS http://127.0.0.1:9529/metrics \
| grep 'opentelemetry.proto.collector.trace.v1.TraceService/Export'
- 进入 观测云「应用性能监测 > 链路」,按
service:my-service查询,确认能够看到刚才请求产生的 Trace。
常见问题¶
go.mod file not found¶
go get -tool 必须在 Go Module 中执行。进入项目根目录,或者先执行:
编译停在 WORK=/tmp/go-build...¶
第一次插桩构建会编译较多依赖。只要 go tool otelc go build 进程仍在运行,就继续等待;终端重新出现命令提示符后才表示构建结束。不要在编译过程中提前执行应用二进制。
请求端口连接失败¶
先确认编译已经结束并启动插桩后的二进制,再检查监听端口:
应用正常但 观测云 没有 Trace¶
依次检查:
- 部署的是否为
go tool otelc go build生成的二进制; OTEL_SERVICE_NAME、Exporter、协议和 endpoint 是否配置在实际运行进程中;.otelc-build/matched.json是否包含预期规则;OTEL_GO_ENABLED_INSTRUMENTATIONS是否包含目标组件;- DataKit OpenTelemetry 采集器是否开启并重启生效;
- 应用到 DataKit 的网络和
4317或9529端口是否可达。
构建问题可以临时启用详细日志:
详细日志位于 .otelc-build/debug.log。排障结束后关闭 Debug,避免日志持续增长。
第一次 Ctrl+C 后应用没有退出¶
otelc v1.1.0 注入的运行时会监听 SIGINT 和 SIGTERM,第一次信号用于刷新遥测数据,但应用仍负责自己的退出流程。未实现优雅关闭的简单应用可能需要再次发送信号。生产服务应使用 Go 标准库实现 HTTP Server 优雅退出,并预留遥测刷新时间。