Managed Service for OpenTelemetry recopila datos de rastreo de aplicaciones Java y ofrece topología de aplicaciones, trazas, análisis de transacciones anómalas y lentas, así como análisis de SQL. Existen tres enfoques de instrumentación disponibles, que van desde la configuración de un agente sin código hasta el control total mediante SDK.
|
Enfoque |
Esfuerzo |
Cuándo utilizarlo |
|
Agente de Java para OpenTelemetry (recomendado) |
Mínimo: solo se adjunta un JAR, sin cambios en el código |
Para la mayoría de las aplicaciones. Comience aquí. |
|
Moderado: requiere escribir código de instrumentación |
Cuando necesita spans personalizados, atributos específicos o frameworks no compatibles |
|
|
Moderado: el agente cubre lo básico y el SDK agrega spans personalizados |
Cobertura automática combinada con instrumentación personalizada dirigida |
Código de ejemplo
Clone o explore el proyecto de ejemplo para tener una referencia funcional:
git clone https://github.com/alibabacloud-observability/java-demo.git
cd java-demo/opentelemetry-demo
Método 1: Instrumentación automática con el agente de Java para OpenTelemetry
El agente de Java para OpenTelemetry se adjunta a su JVM durante el inicio e instrumenta cientos de bibliotecas y frameworks sin necesidad de modificar el código. Este es el punto de partida recomendado para la mayoría de las aplicaciones.
Paso 1: Descargar el agente
Descargue el JAR del agente más reciente desde 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
Paso 2: Configurar los parámetros de la JVM e iniciar la aplicación
Agregue la bandera -javaagent antes del argumento -jar. Elija el protocolo HTTP o gRPC según corresponda.
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
Reemplace los marcadores de posición con sus valores reales:
|
Marcador de posición |
Descripción |
Ejemplo |
|
|
Nombre que identifica a su aplicación |
|
|
|
Versión de la aplicación |
|
|
|
Entorno de despliegue |
|
|
|
Endpoint de rastreo indicado en la sección de requisitos previos |
|
|
|
Endpoint de métricas indicado en la sección de requisitos previos |
|
Ejemplo:
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
Reemplace los marcadores de posición con sus valores reales:
|
Marcador de posición |
Descripción |
Ejemplo |
|
|
Token de autenticación indicado en la sección de requisitos previos |
|
|
|
Endpoint gRPC indicado en la sección de requisitos previos |
|
Ejemplo:
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 reenviar datos de rastreo a través de un OpenTelemetry Collector, elimine-Dotel.exporter.otlp.headers=Authentication=<token>y configure<endpoint>con la dirección del Collector en su máquina local.
Paso 3: Verificar los datos de rastreo
En la página Applications, haga clic en el nombre de su aplicación.
Confirme que las trazas aparecen en la página de detalles de la aplicación.
Solución de problemas:
Si no se muestran datos, compruebe que el endpoint y el token sean correctos.
-
Habilite el registro de depuración para inspeccionar el comportamiento del agente:
-Dotel.javaagent.debug=true -
Deshabilite temporalmente el agente sin eliminarlo del comando de inicio:
-Dotel.javaagent.enabled=false
Método 2: Instrumentación manual con el SDK de OpenTelemetry para Java
Utilice el SDK de OpenTelemetry para Java cuando requiera control total sobre qué operaciones generan spans, qué atributos contienen, o cuando el agente automático no sea compatible con su framework.
Paso 1: Agregar dependencias de Maven
Agregue lo siguiente a su archivo 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>
Paso 2: Inicializar el tracer
Cree una clase auxiliar que configure el exportador, los atributos del recurso y el tracer. Seleccione el protocolo que coincida con su entorno.
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;
}
}
Paso 3: Crear spans
Utilice el tracer para crear spans padre e hijo. Cada span captura una unidad de trabajo, junto con sus atributos y estado de error correspondientes.
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();
}
}
Paso 4: Iniciar la aplicación y verificar
Inicie la aplicación y luego abra la consola de Managed Service for OpenTelemetry. En la página Applications, haga clic en el nombre de su aplicación y confirme que las trazas aparezcan correctamente.
Método 3: Combinar el agente de Java con el SDK
Utilice el agente para obtener una cobertura automática amplia y el SDK para crear spans personalizados específicos. El agente configura automáticamente el SDK al iniciarse mediante la dependencia opentelemetry-sdk-extension-autoconfigure, por lo que no necesitará la clase auxiliar OpenTelemetrySupport del Método 2.
Paso 1: Descargar el agente
Descargue el agente de Java para OpenTelemetry tal como se describe en el Método 1, Paso 1.
Paso 2: Agregar dependencias de Maven
Además de las dependencias indicadas en el Método 2, Paso 1, agregue las siguientes:
<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>
La dependencia opentelemetry-sdk-extension-autoconfigure transfiere automáticamente la configuración del agente al SDK, por lo que no es necesario configurar el exportador ni los atributos del recurso en el código.
Paso 3: Obtener un tracer
Dado que el agente se encarga de la inicialización del SDK, obtenga el tracer global directamente:
OpenTelemetry openTelemetry = GlobalOpenTelemetry.get();
Tracer tracer = openTelemetry.getTracer("instrumentation-library-name", "1.0.0");
Paso 4: Agregar instrumentación personalizada
Existen tres técnicas para agregar instrumentación adicional sobre el agente:
Técnica 1: Agregar atributos a un span creado automáticamente
Llame a Span.current() dentro de un método ya instrumentado para adjuntar atributos de negocio:
@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 instrumentación basada en anotaciones
Anote un método con @WithSpan para crear un span automáticamente. Utilice @SpanAttribute para registrar parámetros:
@WithSpan
private void child(@SpanAttribute("user.type") String userType) {
System.out.println(userType);
biz();
}
Técnica 3: Crear spans manualmente con un tracer
Para tener control total, construya spans mediante la API del tracer. Este ejemplo también propaga el contexto hacia un hilo asíncrono:
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 del controlador y del servicio
Controlador (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();
}
}
}
Servicio (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 -- ");
}
}
Paso 5: Configurar los parámetros de la JVM e iniciar la aplicación
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
Ejemplo:
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 reenviar datos de rastreo a través de un OpenTelemetry Collector, elimine-Dotel.exporter.otlp.headers=Authentication=<token>y configure<endpoint>con la dirección del Collector en su máquina local.
Abra la consola de Managed Service for OpenTelemetry. En la página Applications, haga clic en el nombre de su aplicación y confirme que las trazas aparezcan correctamente.
Frameworks de Java compatibles
El agente de Java de OpenTelemetry instrumenta automáticamente los siguientes frameworks. Para consultar la lista completa y actualizada, consulte Supported libraries, frameworks, application servers, and JVMs.