Go 语言使用 loongsuite-go 上报观测云最佳实践
本文详解 OpenTelemetry 标准协议接入观测云 DataKit 实操,零码无侵入搭建可观测体系,实现日志、调用链路联动分析。
背景
Go 应用接入链路追踪时,常见方案是在代码中手动引入 OpenTelemetry SDK,并为 HTTP、gRPC、数据库、Redis、MongoDB 等组件逐一添加 instrumentation。这种方式可控性强,但对已有项目改造成本较高,也容易出现埋点不完整、上下文传播遗漏、依赖版本不兼容等问题。
loongsuite-go 是阿里巴巴开源的 Go 编译时自动插桩工具。它在 go build 阶段将 OpenTelemetry 埋点逻辑注入到应用中,应用运行后通过标准 OTEL 协议上报链路数据。对于希望快速把 Go 应用接入观测云的场景,loongsuite-go 的优势是:
- 对业务代码侵入小,HTTP、gRPC、MySQL、Redis、MongoDB 等常见组件可以通过编译时插桩自动生成 span。
- 使用 OpenTelemetry 标准协议,上报端可以直接对接观测云 DataKit 的 OTEL 接收端。
- 适合容器化交付,把
otel编译工具放进构建镜像,运行镜像只保留最终二进制。 - 可以结合 JSON 日志,把
trace_id、span_id写入日志字段,便于在观测云中实现日志和链路关联。
本文以 go-demo1 和 go-demo2 为例:
go-demo1:HTTP 服务,提供POST /createOrder,通过 gRPC 调用go-demo2。go-demo2:gRPC 服务,处理支付逻辑,并调用 MySQL、Redis、MongoDB。- 两个服务均使用 loongsuite-go 编译时插桩。
- 链路通过 OTEL gRPC 上报到主机上的 DataKit:
192.168.0.245:4317。
前置条件
- 开通观测云
- 安装 DataKit,能访问 192.168.0.245:9529
- 开通 OpenTelemetry 采集器
1. 使用 loongsuite-go 编译时插桩
loongsuite-go 的关键不是运行时代理,而是构建阶段使用:
otel go build -o app .
当前项目为避免构建时远程下载失败,提前把 otel-linux-amd64 和 install.sh 文件放在项目根目录。
install.sh 只负责把本地 otel-linux-amd64 安装到 /usr/local/bin/otel:
#!/bin/bash
set -e
install() {
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
EXECUTABLE="${1:-${SCRIPT_DIR}/otel-linux-amd64}"
INSTALL_DIR="${INSTALL_DIR:-/usr/local/bin}"
if [ ! -f "$EXECUTABLE" ]; then
echo "Executable $EXECUTABLE not found"
exit 1
fi
echo "Installing $EXECUTABLE to $INSTALL_DIR"
mkdir -p "$INSTALL_DIR"
cp "$EXECUTABLE" "$INSTALL_DIR/otel"
chmod +x "$INSTALL_DIR/otel"
}
install "$@"
这样 Docker 构建时不会再访问 GitHub 下载 otel 工具,适合网络不稳定或内网环境。
2. Dockerfile 推荐写法
以 go-demo2 为例:
FROM golang:1.26 AS builder
WORKDIR /src
ARG GOPROXY=https://goproxy.cn,direct
COPY go-demo2/go.mod ./
RUN --mount=type=cache,target=/go/pkg/mod \
GOPROXY="${GOPROXY}" go mod download
COPY install.sh otel-linux-amd64 /tmp/
RUN chmod +x /tmp/install.sh && /tmp/install.sh /tmp/otel-linux-amd64
COPY go-demo2/ .
RUN --mount=type=cache,target=/go/pkg/mod \
--mount=type=cache,target=/root/.cache/go-build \
GOPROXY="${GOPROXY}" OTELTOOL_VERBOSE=true otel go build -o /out/go-demo2 .
FROM debian:bookworm-slim
WORKDIR /app
COPY --from=builder /out/go-demo2 /app/go-demo2
EXPOSE 9090
ENTRYPOINT ["/app/go-demo2"]
实践建议:
- 构建阶段使用
golang镜像,运行阶段使用更小的debian:bookworm-slim。 go mod download和go build使用 BuildKit cache,加快重复构建。- 使用
OTELTOOL_VERBOSE=true,便于确认哪些规则参与了插桩。 - 生产环境建议固定 Go 版本、依赖版本和
otel-linux-amd64版本,避免构建结果漂移。
3. 配置服务名和上报地址
每个服务必须设置独立的 OTEL_SERVICE_NAME,否则观测云中服务名会混乱。
OTEL_SERVICE_NAME: "go-demo2"
OTEL_EXPORTER_OTLP_ENDPOINT: "http://192.168.0.245:4317"
OTEL_EXPORTER_OTLP_INSECURE: true
OTEL_EXPORTER_OTLP_PROTOCOL: "grpc"
OTEL_EXPORTER_OTLP_TRACES_PROTOCOL: "grpc"
OTEL_TRACE_SAMPLER: "1.0"
- name: OTEL_SERVICE_NAME
value: xxxx
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: http://datakit-service.datakit:4317
- name: OTEL_EXPORTER_OTLP_PROTOCOL
value: grpc
4. Json日志与 trace_id 关联
loongsuite-go 可能会对日志做自动 trace 注入,输出类似:
trace_id=... span_id=...order_id=...
如果应用使用 JSON 日志,不建议依赖这种文本前缀式注入,因为它可能破坏 JSON 格式。更推荐在日志代码中从 context.Context 获取当前 span,再把 trace_id 和 span_id 写成 JSON 字段。
示例:
import (
"context"
"log/slog"
"os"
"go.opentelemetry.io/otel/trace"
)
var logger = slog.New(slog.NewJSONHandler(os.Stdout, nil))
func logAttrs(ctx context.Context, level slog.Level, message string, attrs ...slog.Attr) {
spanContext := trace.SpanContextFromContext(ctx)
if spanContext.IsValid() {
attrs = append(attrs,
slog.String("trace_id", spanContext.TraceID().String()),
slog.String("span_id", spanContext.SpanID().String()),
)
}
logger.LogAttrs(ctx, level, message, attrs...)
}
业务日志:
logAttrs(
ctx,
slog.LevelInfo,
"支付完成",
slog.String("order_id", req.OrderID),
slog.String("pay_id", payID),
)
输出示例:
{
"time": "2026-07-20 02:32:38.927",
"level": "INFO",
"msg": "支付完成",
"order_id": "order-10001",
"pay_id": "pay-82612a021dc38219",
"trace_id": "d28d5c26510ce9d62827e5c3dcab2786",
"span_id": "f73228669d3ccb53"
}
5. Pipeline
登录 观测云控制台,点击「日志」 -「Pipelines」 -「新建Pipeline」,按下图配置Pipeline。

解析规则内容如下:
json_data = load_json(_)
add_key(time,json_data["time"])
add_key(status,json_data["level"])
add_key(trace_id,json_data["trace_id"])
add_key(span_id,json_data["span_id"])
default_time(time,"Asia/Shanghai")
6. 效果展示

总结
Go 应用使用 loongsuite-go 接入观测云时,推荐采用以下实践:
- 使用
otel go build做编译时自动插桩。 - 通过 OTEL gRPC 上报到 DataKit。
- 每个服务明确设置
OTEL_SERVICE_NAME。 - 容器内上报地址使用可达的宿主机 IP,而不是
127.0.0.1。 - 日志使用 JSON 格式,并把
trace_id、span_id作为结构化字段输出。 - 构建阶段使用本地
otel-linux-amd64,减少外网依赖,提高构建稳定性。
参考:


