从零给一个 Go 服务接入 OpenTelemetry,把 Trace/Metrics/Logs 三路信号导出到炬鲸 OBSERVE,含 SDK 初始化、资源属性、采样策略与常见坑。
假设你有一个跑在 Kubernetes 里的 Go 服务,已经用结构化日志打点。目标是把 Trace、Metrics、Logs 三路信号都送进炬鲸 OBSERVE,并且能和日志检索、告警联动。
先拿到接入地址和 token:控制台 → 接入向导 → OpenTelemetry,会生成一个带 token 的 OTLP endpoint,形如 https://ob.jjhub.cn/otlp,token 放在 HTTP 头 Authorization 里。
用官方 SDK,在 main 里初始化 trace 和 metric provider:
res := resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceName("order-service"),
semconv.ServiceVersion("v1.2.3"),
attribute.String("deployment.environment", "prod"),
)
ctx := context.Background()
exp, _ := otlptracehttp.New(ctx,
otlptracehttp.WithEndpoint("ob.jjhub.cn"),
otlptracehttp.WithHeaders(map[string]string{"Authorization": token}),
)
tp := sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exp),
sdktrace.WithResource(res),
sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(0.1))),
)
otel.SetTracerProvider(tp)
三个点值得注意:ServiceName 一定要设,它是 OBSERVE 里按服务维度聚合的 key;环境名用 deployment.environment,别用自定义 key,否则和 Trace 面板的环境过滤对不上;采样率生产环境建议从 0.1 起步,全量采样会吃掉大量存储和网络。
RPC/HTTP 用 otelhttp 包一层 middleware 就能自动埋点,数据库用 otelsql 或对应驱动的 instrumentation。业务里需要手动建 span 的地方用 tracer.Start:
tr := otel.Tracer("order-service")
ctx, span := tr.Start(ctx, "create_order")
defer span.End()
span.SetAttributes(attribute.Int("order.id", id))
重点是把业务 ID(订单号、用户 ID)用 SetAttributes 挂到 span 上,之后在 OBSERVE 里能按这些属性检索链路、定位到具体业务对象。
让日志能跳转到 Trace,核心是往日志里注入 traceId / spanId。用 zap 或 logrus 的话,接一个 OTel 的 hook,自动把当前 span 的 traceId 写进每条日志。这样在 OBSERVE 里点一条日志就能看到它属于哪条链路,反过来从链路也能点进日志。