O Managed Service for OpenTelemetry coleta dados de rastreamento de aplicações Java e fornece topologia de aplicação, traces, análise de transações anômalas e lentas, além de análise de SQL. Estão disponíveis três abordagens de instrumentação, desde a configuração de agente sem código até o controle total via SDK.
|
Abordagem |
Esforço |
Quando usar |
|
Agente Java do OpenTelemetry (recomendado) |
Mínimo — anexe um JAR, sem alterações de código |
Para a maioria das aplicações. Comece por aqui. |
|
Moderado — escreva código de instrumentação |
Spans personalizados, atributos específicos ou frameworks não suportados |
|
|
Moderado — o agente cuida do básico, o SDK adiciona spans personalizados |
Cobertura automática combinada com instrumentação personalizada direcionada |
Código de exemplo
Clone ou navegue pelo projeto de exemplo para obter uma referência funcional:
git clone https://github.com/alibabacloud-observability/java-demo.git
cd java-demo/opentelemetry-demo
Método 1: Instrumentação automática com o agente Java do OpenTelemetry
O agente Java do OpenTelemetry se anexa à JVM na inicialização e instrumenta centenas de bibliotecas e frameworks sem exigir alterações no código. Este é o ponto de partida recomendado para a maioria das aplicações.
Etapa 1: Baixe o agente
Baixe o JAR do agente mais recente em GitHub Releases:
# wget
wget -O opentelemetry-javaagent.jar \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
# or curl
curl -Lo opentelemetry-javaagent.jar \
https://github.com/open-telemetry/opentelemetry-java-instrumentation/releases/latest/download/opentelemetry-javaagent.jar
Etapa 2: Configure parâmetros da JVM e execute a aplicação
Adicione a flag -javaagent antes do argumento -jar. Escolha o protocolo HTTP ou gRPC.
HTTP
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=<your-service-name>,service.version=<your-version>,deployment.environment=<your-env> \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.traces.endpoint=<traces-endpoint> \
-Dotel.exporter.otlp.metrics.endpoint=<metrics-endpoint> \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jar
Substitua os placeholders pelos valores reais:
|
Placeholder |
Descrição |
Exemplo |
|
|
Nome que identifica sua aplicação |
|
|
|
Versão da aplicação |
|
|
|
Ambiente de implantação |
|
|
|
Endpoint de rastreamento da seção Pré-requisitos |
|
|
|
Endpoint de métricas da seção Pré-requisitos |
|
Exemplo:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=order-service,service.version=1.0.0,deployment.environment=production \
-Dotel.exporter.otlp.protocol=http/protobuf \
-Dotel.exporter.otlp.traces.endpoint=http://tracing-analysis-dc-hz-internal.aliyuncs.com/adapt_ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe****/api/otlp/traces \
-Dotel.exporter.otlp.metrics.endpoint=http://tracing-analysis-dc-hz-internal.aliyuncs.com/adapt_ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe****/api/otlp/metrics \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jar
gRPC
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=<your-service-name>,service.version=<your-version>,deployment.environment=<your-env> \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.headers=Authentication=<token> \
-Dotel.exporter.otlp.endpoint=<endpoint> \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jar
Substitua os placeholders pelos valores reais:
|
Placeholder |
Descrição |
Exemplo |
|
|
Token de autenticação da seção Pré-requisitos |
|
|
|
Endpoint gRPC da seção Pré-requisitos |
|
Exemplo:
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=order-service,service.version=1.0.0,deployment.environment=production \
-Dotel.exporter.otlp.protocol=grpc \
-Dotel.exporter.otlp.headers=Authentication=ggxw4l****@7323a5caae3****_ggxw4l****@53df7ad2afe**** \
-Dotel.exporter.otlp.endpoint=http://tracing-analysis-dc-hz-internal.aliyuncs.com:8090 \
-Dotel.logs.exporter=none \
-jar /path/to/your/app.jar
Para encaminhar dados de rastreamento por meio de um OpenTelemetry Collector, remova-Dotel.exporter.otlp.headers=Authentication=<token>e defina<endpoint>como o endereço do Collector na máquina local.
Etapa 3: Verifique dados de rastreamento
Na página Applications, clique em nome da aplicação.
Confirme se os traces aparecem na página de detalhes da aplicação.
Solução de problemas:
Se nenhum dado aparecer, verifique se o endpoint e o token estão corretos.
-
Ative o log de depuração para inspecionar o comportamento do agente:
-Dotel.javaagent.debug=true -
Desative temporariamente o agente sem removê-lo do comando de inicialização:
-Dotel.javaagent.enabled=false
Método 2: Instrumentação manual com o SDK do OpenTelemetry para Java
Use o SDK do OpenTelemetry para Java quando precisar de controle total sobre quais operações geram spans, quais atributos eles carregam ou quando o agente automático não cobrir seu framework.
Etapa 1: Adicionar dependências Maven
Adicione o seguinte ao seu pom.xml:
<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.30.0-alpha</version>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>io.opentelemetry</groupId>
<artifactId>opentelemetry-bom</artifactId>
<version>1.30.0</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
Etapa 2: Inicializar o tracer
Crie uma classe auxiliar para configurar o exporter, os atributos de resource e o tracer. Selecione o protocolo correspondente ao seu ambiente.
HTTP
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.http.trace.OtlpHttpSpanExporter;
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 {
// Define the resource that describes this service
Resource resource = Resource.getDefault()
.merge(Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME, "<your-service-name>",
ResourceAttributes.SERVICE_VERSION, "<your-version>",
ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "<your-env>",
ResourceAttributes.HOST_NAME, "<your-host-name>"
)));
// Build a tracer provider with the OTLP HTTP exporter
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpHttpSpanExporter.builder()
.setEndpoint("<endpoint>") // Trace endpoint from the Prerequisites section
.build()).build())
.setResource(resource)
.build();
// Register the SDK globally
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal();
tracer = openTelemetry.getTracer("OpenTelemetry Tracer", "1.0.0");
}
private static Tracer tracer;
public static Tracer getTracer() {
return tracer;
}
}
gRPC
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 {
// Define the resource that describes this service
Resource resource = Resource.getDefault()
.merge(Resource.create(Attributes.of(
ResourceAttributes.SERVICE_NAME, "<your-service-name>",
ResourceAttributes.SERVICE_VERSION, "<your-version>",
ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "<your-env>",
ResourceAttributes.HOST_NAME, "<your-host-name>"
)));
// Build a tracer provider with the OTLP gRPC exporter
SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder()
.addSpanProcessor(BatchSpanProcessor.builder(OtlpGrpcSpanExporter.builder()
.setEndpoint("<endpoint>") // gRPC endpoint from the Prerequisites section
.addHeader("Authentication", "<token>") // Authentication token from the Prerequisites section
.build()).build())
.setResource(resource)
.build();
// Register the SDK globally
OpenTelemetry openTelemetry = OpenTelemetrySdk.builder()
.setTracerProvider(sdkTracerProvider)
.setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance()))
.buildAndRegisterGlobal();
tracer = openTelemetry.getTracer("OpenTelemetry Tracer", "1.0.0");
}
private static Tracer tracer;
public static Tracer getTracer() {
return tracer;
}
}
Etapa 3: Crie spans
Use o tracer para criar spans pai e filho. Cada span captura uma unidade de trabalho, juntamente com atributos e status de erro.
import io.opentelemetry.api.trace.Span;
import io.opentelemetry.api.trace.StatusCode;
import io.opentelemetry.context.Scope;
public class Main {
public static void parentMethod() {
// Start a parent span
Span span = OpenTelemetrySupport.getTracer().spanBuilder("parent span").startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("good", "job");
childMethod();
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle parent span error");
} finally {
span.end();
}
}
public static void childMethod() {
// Start a child span -- automatically linked to the parent through Context
Span span = OpenTelemetrySupport.getTracer().spanBuilder("child span").startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("hello", "world");
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle child span error");
} finally {
span.end();
}
}
public static void main(String[] args) {
parentMethod();
}
}
Etapa 4: Execute a aplicação e verifique
Execute a aplicação e abra o console do Managed Service for OpenTelemetry. Na página Applications, clique em nome da aplicação e confirme se os traces aparecem.
Método 3: Combinar o agente Java com o SDK
Use o agente para ampla cobertura automática e o SDK para spans personalizados direcionados. O agente configura automaticamente o SDK na inicialização por meio da dependência opentelemetry-sdk-extension-autoconfigure, eliminando a necessidade da classe auxiliar OpenTelemetrySupport do Método 2.
Etapa 1: Baixe o agente
Baixe o agente Java do OpenTelemetry conforme descrito na Etapa 1 do Método 1.
Etapa 2: Adicionar dependências Maven
Além das dependências listadas na Etapa 1 do Método 2, adicione as seguintes:
<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>
A dependência opentelemetry-sdk-extension-autoconfigure transfere as configurações do agente para o SDK automaticamente, dispensando a configuração do exporter ou dos atributos de resource no código.
Etapa 3: Obter um tracer
Como o agente gerencia a inicialização do SDK, obtenha o tracer global diretamente:
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
Etapa 4: Adicionar instrumentação personalizada
Existem três técnicas para adicionar instrumentação complementar ao agente:
Técnica 1: Adicionar atributos a um span criado automaticamente
Chame Span.current() dentro de um método já instrumentado para anexar atributos de negócio:
@RequestMapping("/async")
public String async() {
Span span = Span.current();
span.setAttribute("user.id", "123456");
userService.async();
child("vip");
return "async";
}
Técnica 2: Usar @WithSpan para instrumentação baseada em anotações
Anote um método com @WithSpan para criar um span automaticamente. Use @SpanAttribute para registrar parâmetros:
@WithSpan
private void child(@SpanAttribute("user.type") String userType) {
System.out.println(userType);
biz();
}
Técnica 3: Criar spans manualmente com um tracer
Para controle total, construa spans com a API do tracer. Este exemplo também propaga o contexto para uma thread assíncrona:
private void biz() {
Tracer tracer = GlobalOpenTelemetry.get().getTracer("tracer");
Span span = tracer.spanBuilder("biz (manual)")
.setParent(Context.current().with(Span.current())) // optional -- set automatically
.startSpan();
try (Scope scope = span.makeCurrent()) {
span.setAttribute("biz-id", "111");
// Propagate context into an async task
es.submit(() -> {
Span asyncSpan = tracer.spanBuilder("async")
.setParent(Context.current().with(span))
.startSpan();
try {
Thread.sleep(1000L); // simulate async work
} catch (Throwable e) {
// handle error
}
asyncSpan.end();
});
Thread.sleep(1000); // simulate business logic
} catch (Throwable t) {
span.setStatus(StatusCode.ERROR, "handle biz error");
} finally {
span.end();
}
}
Código completo do controller e service
Controller (com.alibaba.arms.brightroar.console.controller):
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;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
private ExecutorService es = Executors.newFixedThreadPool(5);
// Technique 1: Add attributes to an auto-created span
@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";
}
// Technique 2: Annotation-based instrumentation
@WithSpan
private void child(@SpanAttribute("user.type") String userType) {
System.out.println(userType);
biz();
}
// Technique 3: Manual span creation
private void biz() {
Tracer tracer = GlobalOpenTelemetry.get().getTracer("tracer");
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); // simulate async work
} catch (Throwable e) {
}
asyncSpan.end();
}
});
Thread.sleep(1000); // simulate business 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();
}
}
}
Service (com.alibaba.arms.brightroar.console.service):
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 -- ");
}
}
Etapa 5: Configure parâmetros da JVM e execute a aplicação
java -javaagent:/path/to/opentelemetry-javaagent.jar \
-Dotel.resource.attributes=service.name=<your-service-name> \
-Dotel.exporter.otlp.headers=Authentication=<token> \
-Dotel.exporter.otlp.endpoint=<endpoint> \
-jar /path/to/your/app.jar
Exemplo:
java -javaagent:/path/to/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 \
-jar /path/to/your/app.jar
Para encaminhar dados de rastreamento por meio de um OpenTelemetry Collector, remova-Dotel.exporter.otlp.headers=Authentication=<token>e defina<endpoint>como o endereço do Collector na máquina local.
Abra o console do Managed Service for OpenTelemetry. Na página Applications, clique em nome da aplicação e confirme se os traces aparecem.
Frameworks Java suportados
O agente Java do OpenTelemetry instrumenta automaticamente os frameworks listados abaixo. Para obter a lista completa e atualizada, consulte Bibliotecas, frameworks, servidores de aplicação e JVMs suportados.