Una vez que instrumenta una aplicación con OpenTelemetry y reporta datos de trazas a Managed Service for OpenTelemetry, Managed Service for OpenTelemetry comienza a monitorear la aplicación. Puede consultar diversos datos de monitoreo, como la topología de la aplicación, trazas, transacciones anómalas, transacciones lentas y análisis de SQL. Este tema describe cómo instrumentar una aplicación de Android con OpenTelemetry y reportar datos.
Requisitos previos
Aplicación de ejemplo
Este tema usa una aplicación de ejemplo para mostrar cómo reportar datos de trazas desde una aplicación de Android con OpenTelemetry. El procedimiento se aplica a aplicaciones escritas tanto en Java como en Kotlin.
Repositorio de código de ejemplo: opentelemetry-android-demo
Paso 1: Cree y configure la aplicación
-
Cree una aplicación.
En Android Studio, cree una aplicación nueva. Seleccione la plantilla Basic Views Activity y haga clic en Next.
Seleccione Java o Kotlin como lenguaje, seleccione API 24: Android 7.0 (Nougat) como versión mínima del SDK y, a continuación, haga clic en Finish.
-
Agregue dependencias.
En el archivo build.gradle de nivel de módulo o de proyecto, agregue las siguientes dependencias.
Este ejemplo usa la versión 1.25.0 del SDK de OpenTelemetry para Java. Para consultar otras versiones, consulte Versiones de OpenTelemetry Java. Para consultar el archivo build.gradle completo, consulte build.gradle.
implementation platform('io.opentelemetry:opentelemetry-bom:1.25.0') implementation "io.opentelemetry:opentelemetry-api" implementation "io.opentelemetry:opentelemetry-context" implementation 'io.opentelemetry:opentelemetry-exporter-otlp' implementation 'io.opentelemetry:opentelemetry-exporter-logging' implementation 'io.opentelemetry:opentelemetry-extension-kotlin' implementation 'io.opentelemetry:opentelemetry-sdk' implementation 'io.opentelemetry:opentelemetry-semconv' -
Agregue la configuración de red.
-
En el directorio
app/res/xml, cree un archivo llamado network_security_config.xml y agregue el siguiente contenido.<!-- For the complete file content, see https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/res/xml/network_security_config.xml --> <?xml version="1.0" encoding="utf-8"?> <network-security-config> <domain-config cleartextTrafficPermitted="true"> <!-- Replace the following domain name with the endpoint you obtained in the Prerequisites section. Do not include "http://", the port number, or the URL path. --> <domain includeSubdomains="true">tracing-analysis-dc-hz.aliyuncs.com</domain> </domain-config> </network-security-config> -
Modifique el archivo
app/src/main/AndroidManifest.xml. Agregue las dos líneas siguientes para conceder permiso de red a la aplicación.<!-- For the complete file content, see https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/AndroidManifest.xml --> <?xml version="1.0" encoding="utf-8"?> <manifest ...> <!-- Add the following line to grant network permission. --> <uses-permission android:name="android.permission.INTERNET" /> <application ... <!-- Add the following line to configure network settings for the domain to which you want to report data. --> android:networkSecurityConfig="@xml/network_security_config" ...> ... </application> </manifest>
-
Paso 2: Inicialice OpenTelemetry
-
Cree una clase de utilidad de OpenTelemetry.
En el mismo directorio que MainActivity, cree un archivo llamado
OpenTelemetryUtily agregue el siguiente contenido.-
Opción 1: Reportar datos de trazas mediante gRPC
/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/OpenTelemetryUtil.java */ Resource otelResource = Resource.getDefault().merge( Resource.create( Attributes.of( // Replace <your-service-name> with your application name. ResourceAttributes.SERVICE_NAME, "<your-service-name>", // Replace <your-host-name> with your host name. ResourceAttributes.HOST_NAME, "<your-host-name>" ) ) ); SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional: Prints trace data to the console. Comment out this line to disable this feature. // Replace <gRPC-endpoint> with the endpoint you obtained in the Prerequisites section and replace <gRPC-token> with your authentication token. .addSpanProcessor(BatchSpanProcessor.builder( OtlpGrpcSpanExporter.builder() .setEndpoint("<gRPC-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com:8090 .addHeader("Authentication", "<gRPC-token>") // Example: xxxx@xxxx_xxxx@xxxx .build()).build() ) .setResource(otelResource) .build(); OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .buildAndRegisterGlobal(); // Obtain a tracer to create spans. tracer = openTelemetry.getTracer("android-tracer", "1.0.0");/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt */ val otelResource = Resource.getDefault().merge( Resource.create( Attributes.of( ResourceAttributes.SERVICE_NAME, "<your-service-name>", // Replace <your-service-name> with your application name. ResourceAttributes.HOST_NAME, "<your-host-name>" // Replace <your-host-name> with your host name. ) ) ) /* Report trace data over gRPC. */ val sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional: Prints trace data to the console. Comment out this line to disable this feature. // Replace <gRPC-endpoint> with the endpoint you obtained in the Prerequisites section and replace <gRPC-token> with your authentication token. .addSpanProcessor( BatchSpanProcessor.builder( OtlpGrpcSpanExporter.builder() .setEndpoint("<gRPC-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com:8090 .addHeader("Authentication", "<gRPC-token>") // Example: xxxx@xxxx_xxxx@xxxx .build() ).build() ) .setResource(otelResource) .build() val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .buildAndRegisterGlobal() // Obtain a tracer to create spans. tracer = openTelemetry.getTracer("android-tracer", "1.0.0") -
Opción 2: Reportar datos de trazas mediante HTTP
/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/OpenTelemetryUtil.java */ Resource otelResource = Resource.getDefault().merge( Resource.create( Attributes.of( // Replace <your-service-name> with your application name. ResourceAttributes.SERVICE_NAME, "<your-service-name>", // Replace <your-host-name> with your host name. ResourceAttributes.HOST_NAME, "<your-host-name>" ) ) ); SdkTracerProvider sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional: Prints trace data to the console. Comment out this line to disable this feature. // Replace <HTTP-endpoint> with the endpoint you obtained in the Prerequisites section. .addSpanProcessor(BatchSpanProcessor.builder( OtlpHttpSpanExporter.builder() .setEndpoint("<HTTP-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces .build()).build() ) .setResource(otelResource) .build(); OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .buildAndRegisterGlobal(); // Obtain a tracer to create spans. tracer = openTelemetry.getTracer("android-tracer", "1.0.0");/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/OpenTelemetryUtil.kt */ val otelResource = Resource.getDefault().merge( Resource.create( Attributes.of( ResourceAttributes.SERVICE_NAME, "<your-service-name>", // Replace <your-service-name> with your application name. ResourceAttributes.HOST_NAME, "<your-host-name>" // Replace <your-host-name> with your host name. ) ) ) /* Report trace data over HTTP. */ val sdkTracerProvider = SdkTracerProvider.builder() .addSpanProcessor(SimpleSpanProcessor.create(LoggingSpanExporter.create())) // Optional: Prints trace data to the console. Comment out this line to disable this feature. // Replace <HTTP-endpoint> with the endpoint you obtained in the Prerequisites section. .addSpanProcessor(BatchSpanProcessor.builder( OtlpHttpSpanExporter.builder() .setEndpoint("<HTTP-endpoint>") // Example: http://tracing-analysis-dc-hz.aliyuncs.com/adapt_xxxx@xxxx_xxxx@xxxx/api/otlp/traces .build()).build() ) .setResource(otelResource) .build(); val openTelemetry: OpenTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(W3CTraceContextPropagator.getInstance())) .buildAndRegisterGlobal() // Obtain a tracer to create spans. tracer = openTelemetry.getTracer("android-tracer", "1.0.0")
-
-
Inicialice OpenTelemetry cuando se inicie la aplicación.
En el método
onCreatedeMainActivity, llame al método OpenTelemetryUtil.init()./** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/MainActivity.java */ ... public class MainActivity extends AppCompatActivity { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Add this line to initialize OpenTelemetry. OpenTelemetryUtil.init(); ... } ... }/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/MainActivity.kt */ ... class MainActivity : AppCompatActivity() { ... override fun onCreate(savedInstanceState: Bundle?) { WindowCompat.setDecorFitsSystemWindows(window, false) super.onCreate(savedInstanceState) // Add this line to initialize OpenTelemetry. OpenTelemetryUtil.init() ... } }
Paso 3: Cree spans para trazar datos
-
Cree un span.
En el archivo FirstFragment, cree un span llamado First Fragment Button onClick en el controlador de clic del botón.
/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java */ public void onClick(View view) { // Get the tracer. Tracer tracer = OpenTelemetryUtil.getTracer(); // Create a span. Span span = tracer.spanBuilder("First Fragment Button onClick").startSpan(); try (Scope scope = span.makeCurrent()) { // Get the trace ID. System.out.println(span.getSpanContext().getTraceId()); ... } finally { span.end(); } }/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt */ binding.buttonFirst.setOnClickListener { // Get the tracer. val tracer: Tracer = OpenTelemetryUtil.getTracer()!! // Create a span. val span = tracer.spanBuilder("First Fragment Button onClick").startSpan() try { span.makeCurrent().use { scope -> // Get the trace ID. println(span.spanContext.traceId) // Get the span ID. println(span.spanContext.spanId) findNavController().navigate(R.id.action_FirstFragment_to_SecondFragment) } } catch (t: Throwable) { span.setStatus(StatusCode.ERROR, "Something wrong in onClick") throw t } finally { span.end() } } -
Establezca atributos y eventos para el span.
/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java */ // Set an attribute. span.setAttribute("key", "value"); Attributes eventAttributes = Attributes.of( AttributeKey.stringKey("key"), "value", AttributeKey.longKey("result"), 0L); // Add an event. span.addEvent("onClick", eventAttributes);/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt */ // Set an attribute. span.setAttribute("key", "value") val eventAttributes = Attributes.of( AttributeKey.stringKey("key"), "value", AttributeKey.longKey("result"), 0L ) // Add an event. span.addEvent("onClick", eventAttributes) -
Establezca el estado del span.
/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java */ ... try (Scope scope = span.makeCurrent()) { ... } catch (Throwable t) { // Set the span status. span.setStatus(StatusCode.ERROR, "Something wrong in onClick"); throw t; } finally { span.end(); }/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt */ ... try { ... } catch (t: Throwable) { // Set the span status. span.setStatus(StatusCode.ERROR, "Something wrong in onClick") throw t } finally { span.end() } -
Cree un span anidado.
/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidJavaDemo/app/src/main/java/com/example/androidjavademo/FirstFragment.java */ public void parentSpan() { // Get the tracer. Tracer tracer = OpenTelemetryUtil.getTracer(); // Create a span. Span span = tracer.spanBuilder("Parent Span").startSpan(); try (Scope scope = span.makeCurrent()) { // Get the trace ID. System.out.println(span.getSpanContext().getTraceId()); // Get the span ID. System.out.println(span.getSpanContext().getSpanId()); childSpan(); } finally { span.end(); } } public void childSpan() { // Get the tracer. Tracer tracer = OpenTelemetryUtil.getTracer(); // Create a span. Span span = tracer.spanBuilder("Child Span").startSpan(); try (Scope scope = span.makeCurrent()) { // Get the trace ID. System.out.println(span.getSpanContext().getTraceId()); // Get the span ID. System.out.println(span.getSpanContext().getSpanId()); } finally { span.end(); } }/** For the complete code, visit the following link: https://github.com/alibabacloud-observability/android-demo/blob/master/AndroidKotlinDemo/app/src/main/java/com/example/androidkotlindemo/FirstFragment.kt */ // Nested span fun parentSpan() { // Get the tracer. val tracer: Tracer = OpenTelemetryUtil.getTracer()!! // Create a span. val span = tracer.spanBuilder("Parent Span").startSpan() try { span.makeCurrent().use { scope -> // Get the trace ID. println(span.spanContext.traceId) // Get the span ID. println(span.spanContext.spanId) childSpan() } } finally { span.end() } } // Nested span fun childSpan() { // Get the tracer. val tracer: Tracer = OpenTelemetryUtil.getTracer()!! // Create a span. val span = tracer.spanBuilder("Child Span").startSpan() try { span.makeCurrent().use { scope -> // Get the trace ID. println(span.spanContext.traceId) // Get the span ID. println(span.spanContext.spanId) } } finally { span.end() } }
Paso 4: Ejecute el proyecto y consulte los datos de trazas
-
Ejecute el proyecto y toque el botón en la página de la aplicación de demostración. En el panel Running Devices de Android Studio, el emulador (por ejemplo, Pixel 3a API 33) ejecuta correctamente la aplicación AndroidJavaDemo. También muestra la página First Fragment predeterminada.
Revise Logcat para consultar la información de los spans exportada por
LoggingSpanExporter.System.out I 0c8b92db3d8b038ea3eedd0ec25a4abb System.out I 9ecd666297f5d8f6 System.out I 0c8b92db3d8b038ea3eedd0ec25a4abb System.out I 7e7eaffe7bd23cb8 System.out I 0c8b92db3d8b038ea3eedd0ec25a4abb System.out I 98ef17d962ecf4d1 LoggingSpanExporter I 'Child Span' : 0c8b92db3d8b038ea3eedd0ec25a4abb 98ef17d962ecf4d1 INTERNAL [tracer: android-tracer:1.0.0] LoggingSpanExporter I 'Parent Span' : 0c8b92db3d8b038ea3eedd0ec25a4abb 7e7eaffe7bd23cb8 INTERNAL [tracer: android-tracer:1.0.0] LoggingSpanExporter I 'First Fragment Button onClick' : 0c8b92db3d8b038ea3eedd0ec25a4abb 9ecd666297f5d8f6 INTERNAL [tracer: android-tracer:1.0.0] EGL_emulation D app_time_stats: avg=460.19ms min=2.23ms max=3653.05ms count=8 -
La página de detalles de trazas muestra métricas de resumen, como duración, número de aplicaciones, profundidad de la traza y número total de spans. También muestra una lista de spans. El ejemplo incluye una jerarquía de spans de tres niveles. El span raíz es First Fragment Button onClick (duración: 6.835 ms). El span secundario es Parent Span (duración: 2.998 ms). El span descendiente es Child Span (duración: 0.14 ms). El nombre de la aplicación para todos los spans es
otel-android-demo. Esto muestra el desglose de tiempo y las relaciones entre spans primarios y secundarios.Inicie sesión en la consola de ARMS. En el panel de navegación izquierdo, elija . En la página Applications, haga clic en el nombre de la aplicación. En la página que aparece, consulte los datos de trazas.
NotaSi el icono
se muestra en la columna Language, la aplicación está conectada a Application Monitoring. Si se muestra un guion (-), la aplicación está conectada a Managed Service for OpenTelemetry.
Paso 5: Conecte las trazas del cliente y del servidor
-
Modifique el formato de propagación del contexto de traza en los encabezados.
Los distintos protocolos usan diferentes encabezados HTTP para transmitir el contexto de traza a los servicios descendentes. Por ejemplo, OpenTelemetry usa el formato W3C Trace Context de forma predeterminada, pero también es compatible con otros formatos. Zipkin usa el formato B3 o B3 Multi. Para obtener más información sobre los formatos de propagación de contexto, consulte Specify the context propagation format for OpenTelemetry.
-
Para conectar las trazas del cliente y del servidor, configure
textPropagatorsen el cliente para que coincida con el protocolo que usa el servidor:Si el servidor usa el formato W3C Trace Context predeterminado de OpenTelemetry, no es necesario configurar
textPropagatorsen el cliente.-
Si el servidor usa el formato B3 o B3 Multi de Zipkin, debe establecer
textPropagatorsen el cliente enB3Propagator.// Set the B3 context propagation format. OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(TextMapPropagator.composite( B3Propagator.injectingMultiHeaders(), B3Propagator.injectingSingleHeader()))) .buildAndRegisterGlobal(); -
Si el servidor usa el protocolo Jaeger, debe establecer
textPropagatorsen el cliente enJaegerPropagator.// Set the Jaeger context propagation format. OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(TextMapPropagator.composite( JaegerPropagator.getInstance()))) .buildAndRegisterGlobal(); -
También puede establecer varios formatos de propagación de contexto de traza.
// Use W3C Trace Context, B3, and Jaeger as the trace context propagation formats. OpenTelemetry openTelemetry = OpenTelemetrySdk.builder() .setTracerProvider(sdkTracerProvider) .setPropagators(ContextPropagators.create(TextMapPropagator.composite( W3CTraceContextPropagator.getInstance(), B3Propagator.injectingMultiHeaders(), B3Propagator.injectingSingleHeader(), JaegerPropagator.getInstance()))) .buildAndRegisterGlobal();
-
Importe okhttp3 y opentelemetry-okhttp.
El plugin
opentelemetry-okhttp-3.0para OkHttp instrumenta automáticamente su aplicación al interceptar todas las solicitudes de red enviadas mediante OkHttp3 y crear trazas.-
Agregue las dos dependencias siguientes al archivo
build.gradle.dependencies { ... implementation 'io.opentelemetry.instrumentation:opentelemetry-okhttp-3.0:2.3.0-alpha' implementation 'com.squareup.okhttp3:okhttp:4.12.0' } -
Cree
OkHttpConfiguration.import io.opentelemetry.api.OpenTelemetry; import io.opentelemetry.instrumentation.okhttp.v3_0.OkHttpTelemetry; import okhttp3.Call; import okhttp3.OkHttpClient; public class OkHttpConfiguration { //Use this Call.Factory implementation for making standard http client calls. public Call.Factory createTracedClient(OpenTelemetry openTelemetry) { return OkHttpTelemetry.builder(openTelemetry).build().newCallFactory(createClient()); } //your configuration of the OkHttpClient goes here: private OkHttpClient createClient() { return new OkHttpClient.Builder().build(); } }
-
-
Use OkHttp3 para enviar una solicitud de red al servidor.
private void callHttpService() throws IOException { Tracer tracer = OpenTelemetryUtil.getTracer(); // Create a span. Span span = tracer.spanBuilder("AsyncRequestZipkinServer").startSpan(); System.out.println("AsyncRequestZipkinServer TraceID: " + span.getSpanContext().getTraceId()); System.out.println("AsyncRequestZipkinServer SpanID: " + span.getSpanContext().getSpanId()); try (Scope scope = span.makeCurrent()) { // Send a network request, for example, by using OkHttp. OkHttpConfiguration configuration = new OkHttpConfiguration(); Call.Factory tracedClient = configuration.createTracedClient(GlobalOpenTelemetry.get()); Request request = new Request.Builder().url("${ServerAddress}").get().build(); Call call = tracedClient.newCall(request); try (Response response = call.execute()) { // Process the response. String responseBody = response.body().string(); System.out.println(responseBody); } catch (IOException e) { // Handle the error. e.printStackTrace(); } } finally { span.end(); } } -
En la página Trace Explorer, consulte la traza de extremo a extremo entre el cliente y el servidor.
AsyncRequestZipkinServeres la aplicación de Android yzipkin-demo-serveres la aplicación del servidor.
