Before you can view the trace data of your application in the Tracing Analysis console, you must submit the trace data to Tracing Analysis. This topic describes how to instrument an application and submit trace data.
Prerequisites
- Log on to the Tracing Analysis console.
- In the left-side navigation pane, click Cluster Configurations. Then, click the Access point information tab.
- In the top navigation bar, select a region. In the Cluster Information section, turn on Show Token.
- In the Client section, click OpenTelemetry. Obtain an endpoint of OpenTelemetry in the Related Information column of the table in the lower part.Note If your application is deployed in an Alibaba Cloud production environment, use an access point of Alibaba Cloud VPC. Otherwise, use a public endpoint.
Sample code
Download the sample code from java-opentelemetry-demo.
Method 1: Use the OpenTelemetry Java Agent to perform automatic instrumentation on an application
The OpenTelemetry Java Agent allows you to connect OpenTelemetry to Tracing Analysis in a non-intrusive manner and can be used to automatically upload trace data in dozens of Java frameworks. For more information about the frameworks, see Supported Libraries and Versions.
Download the OpenTelemetry Java Agent.
Modify the VM parameters in the Java startup configuration to submit trace data:
-javaagent:/path/to/opentelemetry-javaagent.jar // Replace the path with the URL that you use to download the OpenTelemetry Java Agent. -Dotel.resource.attributes=service.name=<appName> // Replace <appName> with an actual application name. -Dotel.exporter.otlp.headers=Authentication=<token> -Dotel.exporter.otlp.endpoint=<endpoint> -Dotel.metrics.exporter=none
If you want to directly submit trace data, replace
<token>
with the token that you obtained in the "Connect to Tracing Analysis and authenticate clients" topic. Then, replace<endpoint>
with the endpoint of the region to which you want to submit the trace data.Example:
-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 -Dotel.metrics.exporter=none
If you want to use the OpenTelemetry Collector to forward trace data, remove
-Dotel.exporter.otlp.headers=Authentication=<token>
and replace<endpoint>
with the URL of the service that is deployed on an on-premises machine.
Method 2: Use OpenTelemetry SDK for Java to manually instrument an application
The OpenTelemetry Java Agent is implemented based on OpenTelemetry SDK for Java. The SDK provides various custom features. If the instrumentation that is added by using the OpenTelemetry Java Agent no longer meets your business requirements or you want to add instrumentation based on your business requirements, perform the following steps:
Add the following dependencies to the pom.xml file of a Maven project:
<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> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-semconv</artifactId> <version>1.23.0-alpha</version> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-bom</artifactId> <version>1.23.0</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement>
Obtain an OpenTelemetry tracer.
<logical-service-name>
specifies the name of the service, and<host-name>
specifies the hostname. Specify the values based on your business requirements.If you want to directly submit trace data, replace
<token>
with the token that you obtained in the "Connect to Tracing Analysis and authenticate clients" topic. Then, replace<endpoint>
with the endpoint of the region to which you want to submit the trace data.
package com.alibaba.arms.brightroar.console.util; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.common.Attributes; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.api.trace.propagation.W3CTraceContextPropagator; import io.opentelemetry.context.propagation.ContextPropagators; import io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter; import io.opentelemetry.sdk.OpenTelemetrySdk; import io.opentelemetry.sdk.resources.Resource; import io.opentelemetry.sdk.trace.SdkTracerProvider; import io.opentelemetry.sdk.trace.export.BatchSpanProcessor; import io.opentelemetry.semconv.resource.attributes.ResourceAttributes; public class OpenTelemetrySupport { static { // Obtain an OpenTelemetry tracer. Resource resource = Resource.getDefault() .merge(Resource.create(Attributes.of( ResourceAttributes.SERVICE_NAME, "<logical-service-name>", ResourceAttributes.HOST_NAME, "<host-name>" ))); SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder() .setEndpoint("<endpoint>") .addHeader("Authentication", "<token>") .build()).build()) .setResource(resource) .build(); OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .buildAndRegisterGlobal(); tracer = openTelemetry.getTracer("<your_tracer_name>", "1.0.0"); } private static Tracer tracer; public static Tracer getTracer() { return tracer; } }
Modify the controller code and service code.
Sample controller code:
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.StatusCode; import io.opentelemetry.api.trace.Tracer; import io.opentelemetry.context.Context; import io.opentelemetry.context.Scope; 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; /** * References: * 1. https://opentelemetry.io/docs/java/manual_instrumentation/ */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; private ExecutorService es = Executors.newFixedThreadPool(5); private void biz() { Tracer tracer = OpenTelemetrySupport.getTracer(); Span span = tracer.spanBuilder("biz (manual)") .setParent(Context.current().with(Span.current())) // Optional. The system automatically configures the settings. .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(); } } private void child(String userType) { Span span = OpenTelemetrySupport.getTracer().spanBuilder("child span").startSpan(); try (Scope scope = span.makeCurrent()) { span.setAttribute("user.type", userType); System.out.println(userType); biz(); } catch (Throwable t) { span.setStatus(StatusCode.ERROR, "handle child span error"); } finally { span.end(); } } @RequestMapping("/async") public String async() { System.out.println("UserController.async -- " + Thread.currentThread().getId()); Span span = OpenTelemetrySupport.getTracer().spanBuilder("parent span").startSpan(); span.setAttribute("user.id", "123456"); try (Scope scope = span.makeCurrent()) { userService.async(); child("vip"); } catch (Throwable t) { span.setStatus(StatusCode.ERROR, "handle parent span error"); } finally { span.end(); } return "async"; } }
Sample service code:
package com.alibaba.arms.brightroar.console.service; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class UserService { @Async public void async() { System.out.println("UserService.async -- " + Thread.currentThread().getId()); System.out.println("my name is async"); System.out.println("UserService.async -- "); } }
- Start the application. Log on to the ARMS console. In the left-side navigation pane, choose . On the Applications page, click the name of the application. On the page that appears, view the trace data.Note If the
icon is displayed in the Language column, the application is connected to Application Monitoring. If a hyphen (-) is displayed, the application is connected to Managed Service for OpenTelemetry.
Method 3: Use the OpenTelemetry Java Agent and OpenTelemetry SDK for Java to instrument applications
You can use the OpenTelemetry Java Agent to perform automatic instrumentation and use OpenTelemetry SDK for Java to add instrumentation based on your business requirements.
Download the OpenTelemetry Java Agent.
Add the following dependencies to the pom.xml file of the Maven project in addition to the dependencies of Method 2:
<dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-extension-annotations</artifactId> </dependency> <dependency> <groupId>io.opentelemetry</groupId> <artifactId>opentelemetry-sdk-extension-autoconfigure</artifactId> <version>1.23.0-alpha</version> </dependency>
NoteIn the preceding code, the
opentelemetry-sdk-extension-autoconfigure
dependency is used to automatically configure OpenTelemetry SDK for Java and transfer the settings of the OpenTelemetry Java Agent to the SDK.Obtain an OpenTelemetry tracer.
If you use the OpenTelemetry Java Agent and OpenTelemetry SDK for Java to instrument applications, you do not need to use the OpenTelemetrySupport class used in Method 2 to obtain an OpenTelemetry tracer.
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get(); Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
Modify the controller code and service code.
We recommend that you use Method 1 and Method 2 in the following sample controller code:
package com.alibaba.arms.brightroar.console.controller; import com.alibaba.arms.brightroar.console.service.UserService; import io.opentelemetry.api.GlobalOpenTelemetry; import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.api.trace.Span; 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; /** * References: * 1. https://opentelemetry.io/docs/java/manual_instrumentation/ */ @RestController @RequestMapping("/user") public class UserController { @Autowired private UserService userService; private ExecutorService es = Executors.newFixedThreadPool(5); // Method 3: Use a tracer to manually instrument an application. private void biz() { Tracer tracer = GlobalOpenTelemetry.get().getTracer("tracer"); Span span = tracer.spanBuilder("biz (manual)") .setParent(Context.current().with(Span.current())) // Optional. The system automatically configures the settings. .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(); } } // Method 2: Instrument an application based on tags. @WithSpan private void child(@SpanAttribute("user.type") String userType) { System.out.println(userType); biz(); } // Method 1: Perform automatic instrumentation on an application. Call an API operation to add information. @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"; } }
Sample service code:
package com.alibaba.arms.brightroar.console.service; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; @Service public class UserService { @Async public void async() { System.out.println("UserService.async -- " + Thread.currentThread().getId()); System.out.println("my name is async"); System.out.println("UserService.async -- "); } }
Modify the VM parameters in the Java startup configuration to submit trace data:
-javaagent:/path/to/opentelemetry-javaagent.jar // Replace the path with the URL that you use to download the OpenTelemetry Java Agent. -Dotel.resource.attributes=service.name=<appName> // Replace <appName> with an actual application name. -Dotel.exporter.otlp.headers=Authentication=<token> -Dotel.exporter.otlp.endpoint=<endpoint>
If you want to directly submit trace data, replace
<token>
with the token that you obtained in the "Connect to Tracing Analysis and authenticate clients" topic. Then, replace<endpoint>
with the endpoint of the region to which you want to submit the trace data.Example:
-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
If you want to use the OpenTelemetry Collector to forward trace data, remove
-Dotel.exporter.otlp.headers=Authentication=<token>
and replace<endpoint>
with the URL of the service that is deployed on an on-premises machine.
- Start the application. Log on to the ARMS console. In the left-side navigation pane, choose . On the Applications page, click the name of the application. On the page that appears, view the trace data.Note If the
icon is displayed in the Language column, the application is connected to Application Monitoring. If a hyphen (-) is displayed, the application is connected to Managed Service for OpenTelemetry.