在追踪应用的链路数据之前,您需要通过客户端将应用数据上报至链路追踪服务端。本文介绍如何通过OpenTelemetry Go SDK上报Go应用数据。

前提条件

  1. 登录链路追踪控制台,在页面顶部选择需要接入的地域。
  2. 接入点信息页签的集群信息区域打开显示Token开关。
  3. 客户端采集工具区域单击OpenTelemetry

    在下方表格的相关信息列中,获取接入点信息。

Tracing Analysis Endpoint Section

说明:

  • 如果应用部署于阿里云生产环境,则选择私网接入点,否则选择公网接入点。

背景信息

OpenTelemetry Go SDK提供了Go语言的分布式链路追踪能力,您可以直接使用OTLP gRPC或者HTTP协议向链路追踪服务端上报数据。

示例Demo

oltp-exporter

使用gRPC协议上报

  1. 添加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
  2. 初始化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)
            }
        }
    }
  3. 添加埋点。
    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)
  4. 启动应用程序。
    go run main.go

    链路追踪Tracing Analysis控制台应用列表页面选择新创建的应用,查看链路数据。

使用HTTP协议上报

  1. 添加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
  2. 初始化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)
            }
        }
    }
  3. 添加埋点。
    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)
        }
  4. 启动应用程序。
    go run main.go

    链路追踪Tracing Analysis控制台应用列表页面选择新创建的应用,查看链路数据。