在追踪应用的链路数据之前,您需要通过客户端将应用数据上报至链路追踪服务端。本文介绍如何通过OpenTelemetry Go SDK上报Go应用数据。
前提条件
获取接入点信息
登录链路追踪控制台 ,在页面顶部选择需要接入的地域。
在接入点信息 页签的集群信息 区域打开显示Token 开关。
在客户端采集工具 区域单击OpenTelemetry 。
在下方表格的相关信息 列中,获取接入点信息。
说明:
对于ACK集群应用,建议通过ARMS OpenTelemetry Collector上报应用数据。ARMS OpenTelemetry Collector支持本地集群内的链路采样与指标无损统计,在降低链路传输、存储成本的同时,不影响监控或告警指标的准确性。更多信息,请参见ARMS OpenTelemetry Collector 。
如果应用部署于阿里云生产环境,则选择私网接入点,否则选择公网接入点。
背景信息
OpenTelemetry Go SDK 提供了Go语言的分布式链路追踪能力,您可以直接使用OTLP gRPC或者HTTP协议向链路追踪服务端上报数据。
使用gRPC协议上报
添加OpenTelemetry Go依赖。 go get go.opentelemetry.io/otel
go get go.opentelemetry.io/otel/trace
go get go.opentelemetry.io/otel/sdk
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc # otlp grpc
初始化OpenTelemetry Go SDK。 您可以选择通过OpenTelemetry SDK直接上报或通过开源OpenTelemetry Collector转发。
如果选择直接上报,请将otelAgentAddr和xtraceToken替换为前提条件获取的接入点和鉴权Token。
如果选择使用OpenTelemetry Collector转发,请将otelAgentAddr替换为您本地部署的服务地址,并删除Header信息。
func initProvider() func() {
ctx := context.Background()
otelAgentAddr, xtraceToken, ok := common.ObtainXTraceInfo()
if !ok {
log.Fatalf("Cannot init OpenTelemetry, exit")
os.Exit(-1)
}
headers := map[string]string{"Authentication": xtraceToken} //将xtraceToken替换为前提条件中获取的鉴权Token。
traceClient := otlptracegrpc.NewClient(
otlptracegrpc.WithInsecure(),
otlptracegrpc.WithEndpoint(otelAgentAddr), //将otelAgentAddr替换为前提条件中获取的接入点。
otlptracegrpc.WithHeaders(headers),
otlptracegrpc.WithDialOption(grpc.WithBlock()))
log.Println("start to connect to server")
traceExp, err := otlptrace.New(ctx, traceClient)
handleErr(err, "Failed to create the collector trace exporter")
res, err := resource.New(ctx,
resource.WithFromEnv(),
resource.WithProcess(),
resource.WithTelemetrySDK(),
resource.WithHost(),
resource.WithAttributes(
// 在链路追踪后端显示的服务名称。
semconv.ServiceNameKey.String(common.ServerServiceName),
),
)
handleErr(err, "failed to create resource")
bsp := sdktrace.NewBatchSpanProcessor(traceExp)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
// 设置全局propagator为tracecontext(默认不设置)。
otel.SetTextMapPropagator(propagation.TraceContext{})
otel.SetTracerProvider(tracerProvider)
return func() {
cxt, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
if err := traceExp.Shutdown(cxt); err != nil {
otel.Handle(err)
}
}
}
添加埋点。 shutdown := initProvider()
defer shutdown()
//meter := global.Meter("demo-server-meter")
serverAttribute := attribute.String("server-attribute", "foo")
fmt.Println("start to gen chars for trace data")
initTraceDemoData()
fmt.Println("gen trace data done")
tracer := otel.Tracer(common.TraceInstrumentationName)
// 在OpenTelemetry中创建一个handler。
handler := http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
// 模拟延迟
var sleep int64
switch modulus := time.Now().Unix() % 5; modulus {
case 0:
sleep = rng.Int63n(2000)
case 1:
sleep = rng.Int63n(15)
case 2:
sleep = rng.Int63n(917)
case 3:
sleep = rng.Int63n(87)
case 4:
sleep = rng.Int63n(1173)
}
ctx := req.Context()
span := trace.SpanFromContext(ctx)
span.SetAttributes(serverAttribute)
actionChild(tracer, ctx, sleep)
w.Write([]byte("Hello World"))
})
wrappedHandler := otelhttp.NewHandler(handler, "/hello")
http.Handle("/hello", wrappedHandler)
http.ListenAndServe(":7080", nil)
启动应用程序。
使用HTTP协议上报
添加OpenTelemetry Go依赖。 go get go.opentelemetry.io/otel
go get go.opentelemetry.io/otel/trace
go get go.opentelemetry.io/otel/sdk
go get go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp # otlp http
初始化OpenTelemetry Go SDK,其中Endpoint和URLPath需替换为前提条件中获取的接入点信息。 您可以选择通过OpenTelemetry SDK直接上报或通过开源OpenTelemetry Collector转发。
如果选择直接上报,请将Endpoint和URLPath替换为前提条件获取的接入点信息。
如果选择使用OpenTelemetry Collector转发,请将Endpoint替换为您本地部署的服务地址,并删除Header信息。
func initProvider() func() {
ctx := context.Background()
traceClientHttp := otlptracehttp.NewClient(
otlptracehttp.WithEndpoint("127.0.XX.XX:8080"), //Endpoint需替换为前提条件中获取的接入点信息。
otlptracehttp.WithURLPath("/adapt_xxxxx/api/otlp/traces"), //URLPath需替换为前提条件中获取的接入点信息。
otlptracehttp.WithInsecure())
otlptracehttp.WithCompression(1)
traceExp, err := otlptrace.New(ctx, traceClientHttp)
handleErr(err, "Failed to create the collector trace exporter")
res, err := resource.New(ctx,
resource.WithFromEnv(),
resource.WithProcess(),
resource.WithTelemetrySDK(),
resource.WithHost(),
resource.WithAttributes(
// 在链路追踪后端显示的服务名称。
semconv.ServiceNameKey.String(common.ClientServiceName),
),
)
handleErr(err, "failed to create resource")
bsp := sdktrace.NewBatchSpanProcessor(traceExp)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.AlwaysSample()),
sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
// 设置全局propagator为tracecontext(默认不设置)。
otel.SetTextMapPropagator(propagation.TraceContext{})
otel.SetTracerProvider(tracerProvider)
log.Println("OTEL init success")
return func() {
cxt, cancel := context.WithTimeout(ctx, time.Second)
defer cancel()
if err := traceExp.Shutdown(cxt); err != nil {
otel.Handle(err)
}
}
}
添加埋点。 tracer := otel.Tracer(common.TraceInstrumentationName)
method, _ := baggage.NewMember("method", "repl")
client, _ := baggage.NewMember("client", "cli")
bag, _ := baggage.New(method, client)
defaultCtx := baggage.ContextWithBaggage(context.Background(), bag)
for {
ctx, span := tracer.Start(defaultCtx, "ExecuteRequest")
makeRequest(ctx)
span.End()
time.Sleep(time.Duration(1) * time.Second)
}
启动应用程序。