通过OpenTelemetry接入Java Trace数据

本文介绍通过OpenTelemetry Java SDK将Java应用的Trace数据接入到日志服务的操作步骤。

前提条件

  • 已创建Trace实例。更多信息,请参见创建Trace实例

  • 已安装Java 8及以上版本的开发环境。

    说明

    建议使用JDK 8u252及以上版本。

(推荐)方案一:通过Java Agent自动上传Trace数据

目前有数十种Java框架支持通过Java Agent自动上传Trace数据到日志服务,详细的Java框架列表请参见SupportedLibraries

重要

Java Agent上传方式不支持和其他类似的方案(例如SkyWalking Agent、Zipkin Agent等)同时使用,可能会产生未定义行为。

  1. 下载最新版本Java Agent。更多信息,请参见OpenTelemetry Release列表

  2. 集成Java Agent。

    此处以JVM的-javaagent为例,配置相关的环境变量。更多信息,请参见opentelemetry-java-instrumentation。其中,代码中的变量(例如${endpoint}${project}等)需根据实际情况替换。

    export OTEL_EXPORTER_OTLP_PROTOCOL=grpc
    export OTEL_EXPORTER_OTLP_ENDPOINT=https://${endpoint}
    export OTEL_EXPORTER_OTLP_COMPRESSION=gzip
    export OTEL_EXPORTER_OTLP_HEADERS=x-sls-otel-project=${project},x-sls-otel-instance-id=${instance},x-sls-otel-ak-id=${access-key-id},x-sls-otel-ak-secret=${access-key-secret}
    java -javaagent:/path/to/opentelemetry-javaagent-all.jar  -Dotel.resource.attributes=service.namespace=${service.namespace},service.name=${service},service.version=${version},host.name=${host},deployment.environment=${environment} -jar /path/to/your/app.jar

    表 1. 变量说明

    变量

    说明

    示例

    ${endpoint}

    日志服务Project的接入地址,格式为${project}.${region-endpoint}:Port,其中:

    • ${project}:日志服务Project名称。

    • ${region-endpoint}:日志服务Project所在地域的访问域名,支持公网和阿里云内网(经典网络、VPC)。更多信息,请参见服务入口

    • Port:网络端口,固定为10010。

    test-project.cn-hangzhou.log.aliyuncs.com:10010

    ${project}

    日志服务Project名称。

    test-project

    ${instance}

    Trace服务实例ID。更多信息,请参见创建Trace实例

    test-traces

    ${access-key-id}

    阿里云账号AccessKey ID。

    建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey(包括AccessKey ID和AccessKey Secret)。授予RAM用户向指定Project写入数据权限的具体操作,请参见授权。如何获取AccessKey的具体操作,请参见访问密钥

    ${access-key-secret}

    阿里云账号AccessKey Secret。

    建议您使用只具备日志服务Project写入权限的RAM用户的AccessKey。

    ${service.namespace}

    服务归属的命名空间。

    order

    ${service}

    服务名。根据您的实际场景配置。

    payment

    ${version}

    服务版本号。建议按照va.b.c格式定义。

    v0.1.2

    ${host}

    主机名。

    localhost

    ${environment}

    部署环境。例如测试环境、生产环境。根据您的实际场景配置。

    pre

方案二:手动构造Trace数据并上传

当您使用自建框架或有其他需求时,可以手动构造Trace数据并上传到日志服务。此处以Maven方式为例,更多信息,请参见Manual Instrumentation示例代码,请参见OpenTelemetry Manual API Demo

  1. 添加Maven依赖。

    <dependencies>
        <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-api</artifactId>
        </dependency>
        <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-sdk</artifactId>
        </dependency>
        <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-exporter-otlp</artifactId>
        </dependency>
        <dependency>
          <groupId>io.opentelemetry</groupId>
          <artifactId>opentelemetry-semconv</artifactId>
          <version>1.20.1-alpha</version>
        </dependency>
      </dependencies>
      <dependencyManagement>
        <dependencies>
          <dependency>
            <groupId>io.opentelemetry</groupId>
            <artifactId>opentelemetry-bom</artifactId>
            <version>1.20.1</version>
            <type>pom</type>
            <scope>import</scope>
          </dependency>
        </dependencies>
      </dependencyManagement>
  2. 添加初始化代码。

    代码中的变量(例如${endpoint}${project}等)需根据实际情况替换。关于变量的详细说明,请参见变量说明

      Resource resource = Resource.getDefault()
                    .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAME, "service-name")))
                    .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_NAMESPACE, "namespace")))
                    .merge(Resource.create(Attributes.of(ResourceAttributes.SERVICE_VERSION, "1.0.0")))
                    .merge(Resource.create(Attributes.of(ResourceAttributes.HOST_NAME, "host-name")));
    
            SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
                    .addSpanProcessor(
                            BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder().setEndpoint("https://${endpoint}") // 配置.setEndpoint参数时,必须添加https://,例如https://test-project.cn-hangzhou.log.aliyuncs.com:10010。
                                    .addHeader("x-sls-otel-project", "${project}")
                                    .addHeader("x-sls-otel-instance-id", "${instance}")
                                    .addHeader("x-sls-otel-ak-id", "${access-key-id}")
                                    .addHeader("x-sls-otel-ak-secret", "${access-key-secret}").build()).build())
                    .setResource(resource).build();
    
            OpenTelemetry openTelemetry = OpenTelemetrySdk.builder().setTracerProvider(sdkTracerProvider)
                    .buildAndRegisterGlobal();
    
            Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
            Span parentSpan = tracer.spanBuilder("parent").startSpan();
    
            try {
                Span childSpan = tracer.spanBuilder("child").setParent(Context.current().with(parentSpan)).startSpan();
                childSpan.setAttribute("test", "vllelel");
                childSpan.end();
            } finally {
                parentSpan.end();
            }

常见问题

当您使用JDK 8u252之前版本时,Java Agent中可能出现Could not find TLS ALPN provider错误,如何处理?Counld not find TLS ALPN provider

您可以参见如下步骤解决:

  1. 下载引导包

  2. 执行如下命令添加相关的.jar包。

    ${youpath}为各个.jar包所在路径,请根据实际情况替换。

    java -Xbootclasspath/p:${youpath}/netty-tcnative-boringssl-static-2.0.25.Final.jar -javaagent:${youpath}/opentelemetry-javaagent-all.jar -jar ${youpath}/demo2-0.0.1-SNAPSHOT.jar

后续步骤