在使用链路追踪控制台追踪应用的链路数据之前,需要将应用数据上报至链路追踪。本文介绍如何为应用埋点并上报链路数据。

前提条件

  1. 登录链路追踪控制台,在左侧导航栏,单击集群配置
  2. 集群配置页面上单击接入点信息页签,在集群信息区域打开显示Token开关。
  3. 客户端采集工具区域单击需要使用的链路数据采集客户端。
  4. 在下方表格的相关信息列中,单击接入点信息末尾的复制图标。

Tracing Analysis Endpoint Section

说明:如果应用部署于阿里云生产环境,则选择私网接入点,否则选择公网接入点。对于Zipkin,一般情况下请使用v2版接入点,v1版接入点仅限对Zipkin十分了解的高阶用户使用。

使用OpenTelemetry Java Agent自动埋点

OpenTelemetry Java Agent提供了无侵入的接入方式,支持数十种框架。更多信息,请参见OpenTelemetry官方文档

  1. 下载Java Agent
  2. 通过修改Java启动的VM参数上报链路数据。
    -javaagent:/path/to/opentelemetry-javaagent.jar    //请将路径修改为您文件下载的实际地址。
    -Dotel.resource.attributes=service.name=<appName>     //<appName> 为应用名。
    -Dotel.exporter.otlp.headers=Authentication=<token>
    -Dotel.exporter.otlp.endpoint=<endpoint>
    • 如果您选择直接上报数据,请将<token>替换成从前提条件中获取的Token,将<endpoint>替换成对应地域的Endpoint。

      例如:

      -javaagent:/Users/carpela/Downloads/opentelemetry-javaagent.jar
      -Dotel.resource.attributes=service.name=ot-java-agent-sample
      -Dotel.exporter.otlp.headers=Authentication=b590xxxxuqs@3a75d95xxxxx9b_b59xxxxguqs@53dxxxx2afe8301
      -Dotel.exporter.otlp.endpoint=http://tracing-analysis-dc-bj:8090
    • 如果您选择使用OpenTelemetry Collector转发,则需删除-Dotel.exporter.otlp.headers=Authentication=<token>并修改<endpoint>为您本地部署的服务地址。

使用OpenTelemetry Java SDK手动埋点

OpenTelemetry Java SDK是OpenTelemetry Java Agent实现的基础,提供了丰富的自定义能力。当OpenTelemetry Java Agent的埋点不满足您的场景或者需要增加一些自定义业务埋点时,可以使用以下方式接入。

  1. 引入Maven POM依赖。
    <dependencies>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-api</artifactId>
            </dependency>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-sdk-trace</artifactId>
            </dependency>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-exporter-otlp</artifactId>
            </dependency>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-sdk</artifactId>
            </dependency>
        </dependencies>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>io.opentelemetry</groupId>
                    <artifactId>opentelemetry-bom</artifactId>
                    <version>1.9.0</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
        </dependencyManagement>
  2. 获取OpenTelemetry Tracer。
    SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
                    .addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder()
                            .setEndpoint("<endpoint>")
                            .addHeader("Authentication", "<token>")
                            .build()).build())
                    .build();
    
    OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
                    .setTracerProvider(sdkTracerProvider)
                    .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
                    .buildAndRegisterGlobal();
    
    Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
  3. 参考OpenTelemetry官方文档修改以下代码。
    package com.alibaba.arms.brightroar.console.controller;
    
    import com.alibaba.arms.brightroar.console.service.UserService;
    import com.alibaba.arms.brightroar.console.util.OpenTelemetrySupport;
    import io.opentelemetry.api.GlobalOpenTelemetry;
    import io.opentelemetry.api.OpenTelemetry;
    import io.opentelemetry.api.trace.Span;
    import io.opentelemetry.api.trace.SpanContext;
    import io.opentelemetry.api.trace.StatusCode;
    import io.opentelemetry.api.trace.Tracer;
    import io.opentelemetry.context.Context;
    import io.opentelemetry.context.Scope;
    import io.opentelemetry.extension.annotations.SpanAttribute;
    import io.opentelemetry.extension.annotations.WithSpan;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * 参考文档:
     * 1. https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/manual-instrumentation.md#creating-spans-manually-with-a-tracer
     * 2. https://opentelemetry.io/docs/java/manual_instrumentation/
     */
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        private ExecutorService es = Executors.newFixedThreadPool(5);
    
        // 第三种:获得Tracer纯手工埋点
        private void biz() {
            Tracer tracer = OpenTelemetrySupport.getTracer();
            Span span = tracer.spanBuilder("biz (manual)")
                    .setParent(Context.current().with(Span.current())) // 可选,自动设置
                    .startSpan();
    
            try (Scope scope = span.makeCurrent()) {
                span.setAttribute("biz-id", "111");
    
                es.submit(new Runnable() {
                    @Override
                    public void run() {
                        Span asyncSpan = tracer.spanBuilder("async")
                                .setParent(Context.current().with(span))
                                .startSpan();
    
                        try {
                            Thread.sleep(1000L); // some async jobs
                        } catch (Throwable e) {
                        }
                        asyncSpan.end();
                    }
                });
    
                Thread.sleep(1000); // fake biz logic
                System.out.println("biz done");
                OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
                openTelemetry.getPropagators();
            } catch (Throwable t) {
                span.setStatus(StatusCode.ERROR, "handle biz error");
            } finally {
                span.end();
            }
        }
    
    
    
    }
                            
  4. 通过修改Java启动的VM参数上报链路数据。
    -javaagent:/path/to/opentelemetry-javaagent.jar    //请将路径修改为您文件下载的实际地址。
    -Dotel.resource.attributes=service.name=<appName>     //<appName> 为应用名。
    -Dotel.exporter.otlp.headers=Authentication=<token>
    -Dotel.exporter.otlp.endpoint=<endpoint>
    • 如果您选择直接上报数据,请将<token>替换成从前提条件中获取的Token,将<endpoint>替换成对应地域的Endpoint。

      例如:

      -javaagent:/Users/carpela/Downloads/opentelemetry-javaagent.jar
      -Dotel.resource.attributes=service.name=ot-java-agent-sample
      -Dotel.exporter.otlp.headers=Authentication=b590xxxxuqs@3a75d95xxxxx9b_b59xxxxguqs@53dxxxx2afe8301
      -Dotel.exporter.otlp.endpoint=http://tracing-analysis-dc-bj:8090
    • 如果您选择使用OpenTelemetry Collector转发,则需删除-Dotel.exporter.otlp.headers=Authentication=<token>并修改<endpoint>为您本地部署的服务地址。
  5. 启动应用。

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

同时使用Java Agent和Java SDK埋点

您可以在使用Java Agent获得自动埋点能力的同时,使用Java SDK添加自定义业务埋点。

  1. 通过Java Agent方式接入应用。
  2. 在Java SDK的基础上新增Maven依赖。
    <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-extension-annotations</artifactId>
            </dependency>
            <dependency>
                <groupId>io.opentelemetry</groupId>
                <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId>
                <version>1.9.0-alpha</version>
            </dependency>
    说明 其中opentelemetry-sdk-extension-autoconfigure完成了SDK的自动配置,将Java Agent的配置传递到Java SDK中。
  3. 获得OpenTelemetry Tracer。
    OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
    Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
  4. 修改以下代码,建议使用代码中的第一种和第二种方式。更多信息,请参见OpenTelemetry官方文档
    package com.alibaba.arms.brightroar.console.controller;
    
    import com.alibaba.arms.brightroar.console.service.UserService;
    import com.alibaba.arms.brightroar.console.util.OpenTelemetrySupport;
    import io.opentelemetry.api.GlobalOpenTelemetry;
    import io.opentelemetry.api.OpenTelemetry;
    import io.opentelemetry.api.trace.Span;
    import io.opentelemetry.api.trace.SpanContext;
    import io.opentelemetry.api.trace.StatusCode;
    import io.opentelemetry.api.trace.Tracer;
    import io.opentelemetry.context.Context;
    import io.opentelemetry.context.Scope;
    import io.opentelemetry.extension.annotations.SpanAttribute;
    import io.opentelemetry.extension.annotations.WithSpan;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RestController;
    
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    
    /**
     * 参考文档:
     * 1. https://github.com/open-telemetry/opentelemetry-java-instrumentation/blob/main/docs/manual-instrumentation.md#creating-spans-manually-with-a-tracer
     * 2. https://opentelemetry.io/docs/java/manual_instrumentation/
     */
    @RestController
    @RequestMapping("/user")
    public class UserController {
    
        @Autowired
        private UserService userService;
    
        private ExecutorService es = Executors.newFixedThreadPool(5);
    
        // 第三种:获得Tracer纯手工埋点
        private void biz() {
            Tracer tracer = OpenTelemetrySupport.getTracer();
            Span span = tracer.spanBuilder("biz (manual)")
                    .setParent(Context.current().with(Span.current())) // 可选,自动设置
                    .startSpan();
    
            try (Scope scope = span.makeCurrent()) {
                span.setAttribute("biz-id", "111");
    
                es.submit(new Runnable() {
                    @Override
                    public void run() {
                        Span asyncSpan = tracer.spanBuilder("async")
                                .setParent(Context.current().with(span))
                                .startSpan();
    
                        try {
                            Thread.sleep(1000L); // some async jobs
                        } catch (Throwable e) {
                        }
                        asyncSpan.end();
                    }
                });
    
                Thread.sleep(1000); // fake biz logic
                System.out.println("biz done");
                OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
                openTelemetry.getPropagators();
            } catch (Throwable t) {
                span.setStatus(StatusCode.ERROR, "handle biz error");
            } finally {
                span.end();
            }
        }
    
        // 第二种:基于标签手工埋点
        @WithSpan
        private void child(@SpanAttribute("user.type") String userType) {
            System.out.println(userType);
            biz();
        }
    
        // 第一种:自动埋点,基于API手工添加信息
        @RequestMapping("/async")
        public String async() {
            System.out.println("UserController.async -- " + Thread.currentThread().getId());
            Span span = Span.current();
            span.setAttribute("user.id", "123456");
            userService.async();
            child("vip");
            return "async";
        }
    
    }
                            
  5. 通过修改Java启动的VM参数上报链路数据。
    -javaagent:/path/to/opentelemetry-javaagent.jar    //请将路径修改为您文件下载的实际地址。
    -Dotel.resource.attributes=service.name=<appName>     //<appName> 为应用名。
    -Dotel.exporter.otlp.headers=Authentication=<token>
    -Dotel.exporter.otlp.endpoint=<endpoint>
    • 如果您选择直接上报数据,请将<token>替换成从前提条件中获取的Token,将<endpoint>替换成对应地域的Endpoint。

      例如:

      -javaagent:/Users/carpela/Downloads/opentelemetry-javaagent.jar
      -Dotel.resource.attributes=service.name=ot-java-agent-sample
      -Dotel.exporter.otlp.headers=Authentication=b590xxxxuqs@3a75d95xxxxx9b_b59xxxxguqs@53dxxxx2afe8301
      -Dotel.exporter.otlp.endpoint=http://tracing-analysis-dc-bj:8090
    • 如果您选择使用OpenTelemetry Collector转发,则需删除-Dotel.exporter.otlp.headers=Authentication=<token>并修改<endpoint>为您本地部署的服务地址。
  6. 启动应用。

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