3. OpenTelemetry SDK 安装:核心库、Exporter 与 Instrumentation
本章将完成 OpenTelemetry Go SDK 的安装与初始化配置。正确的 SDK 安装是后续实现慢查询追踪的基础,涉及三个核心组件:SDK 核心库、OTLP Exporter 以及 HTTP/gRPC Instrumentation。我们将按照依赖注入的顺序,逐步完成 Go 模块的引入与初始化代码的编写。
3.1 安装概览与组件关系
在开始安装之前,需要理解这三个组件在追踪链路中的角色:
| 组件 | Go 模块路径 | 职责 |
|---|---|---|
| SDK 核心库 | go.opentelemetry.io/otelgo.opentelemetry.io/otel/sdk |
提供 TracerProvider、SpanProcessor 等核心抽象,管理追踪生命周期 |
| OTLP Exporter | go.opentelemetry.io/otel/exporters/otlp/otlptrace |
将 Span 数据通过 OTLP 协议发送到后端(如 Jaeger、Grafana Tempo) |
| HTTP/gRPC Instrumentation | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttpgo.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc |
自动拦截 HTTP 请求和 gRPC 调用,创建并传播追踪上下文 |
版本对齐提示: 截至本文撰写时,推荐使用
otel v1.28.0 及以上版本,contrib v0.53.0 及以上版本。请确保 SDK 核心库与 Instrumentation 的版本兼容,避免因 API 变更导致的编译错误。
3.2 安装步骤:三步完成依赖注入
以下步骤在 Go 项目根目录下执行,使用 go get 命令安装所需模块。
步骤一:安装 SDK 核心库
核心库提供 TracerProvider 的创建与配置能力,是所有追踪功能的基石。
go get go.opentelemetry.io/otel@v1.28.0
go get go.opentelemetry.io/otel/sdk@v1.28.0
go get go.opentelemetry.io/otel/trace@v1.28.0
步骤二:安装 OTLP Exporter
OTLP Exporter 负责将追踪数据序列化并通过 gRPC 或 HTTP 协议发送。我们同时安装 gRPC 和 HTTP 两种传输方式,以便根据部署环境灵活选择。
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace@v1.28.0
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc@v1.28.0
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp@v1.28.0
步骤三:安装 HTTP 与 gRPC Instrumentation
Instrumentation 库自动为 Go 标准库的 HTTP 处理函数和 gRPC 拦截器注入追踪能力。
go get go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp@v0.53.0
go get go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc@v0.53.0
验证安装: 执行
go mod tidy 清理依赖,然后运行 go build ./... 确保所有模块编译通过,无缺失依赖或版本冲突。
3.3 组件协作架构
下图展示了 SDK 核心库、Exporter 与 Instrumentation 在 Go Web 服务中的协作关系:
3.4 初始化代码模板
安装完成后,需要在服务启动时初始化 SDK。以下是一个标准的初始化函数模板,整合了 OTLP gRPC Exporter 与 HTTP Instrumentation:
package main
import (
"context"
"log"
"net/http"
"time"
"go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.26.0"
)
// initTracer 初始化 OTel TracerProvider,使用 OTLP gRPC Exporter
func initTracer() func() {
ctx := context.Background()
// 1. 创建 OTLP Exporter(gRPC 方式)
exporter, err := otlptrace.New(
ctx,
otlptracegrpc.NewClient(
otlptracegrpc.WithEndpoint("localhost:4317"), // 后端地址
otlptracegrpc.WithInsecure(), // 开发环境跳过 TLS
),
)
if err != nil {
log.Fatalf("创建 OTLP Exporter 失败: %v", err)
}
// 2. 创建资源(标识服务名称和版本)
res, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String("go-web-svc"),
semconv.ServiceVersionKey.String("1.0.0"),
),
)
if err != nil {
log.Fatalf("创建资源失败: %v", err)
}
// 3. 创建 TracerProvider
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exporter, sdktrace.WithBatchTimeout(5*time.Second)),
sdktrace.WithResource(res),
)
// 4. 设置为全局 TracerProvider
otel.SetTracerProvider(tp)
// 返回关闭函数,用于优雅关闭
return func() {
if err := tp.Shutdown(ctx); err != nil {
log.Printf("关闭 TracerProvider 失败: %v", err)
}
}
}
func main() {
// 初始化追踪
cleanup := initTracer()
defer cleanup()
// 使用 otelhttp 包装 HTTP 处理函数
handler := otelhttp.NewHandler(
http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, OpenTelemetry!"))
}),
"hello-handler",
)
http.Handle("/hello", handler)
log.Println("服务启动于 :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
常见错误: 忘记调用
otel.SetTracerProvider(tp) 会导致 Instrumentation 库无法获取到正确的 TracerProvider,从而产生空 Span 或追踪数据丢失。务必在服务启动时完成全局设置。
3.5 安装验证清单
完成安装与初始化后,使用以下清单进行快速验证:
- 编译检查:
go build ./...无错误输出。 - 依赖完整性:
go mod tidy后go.mod中仅包含所需模块,无冗余依赖。 - Exporter 连接: 启动后端(如 Jaeger 容器),服务启动日志无连接超时或拒绝连接错误。
- Span 生成: 访问
/hello端点后,后端 UI 中出现对应的 Trace 记录。