赛尔校园公共服务平台 Logo
平台使用
阿里云
百度云
移动云
智算服务
教育生态
登录 →
赛尔校园公共服务平台 Logo
平台使用 阿里云 百度云 移动云 智算服务 教育生态
登录
  1. 首页
  2. 阿里云
  3. 日志服务
  4. 操作指南
  5. 日志应用
  6. 全栈可观测
  7. Trace
  8. 接入Trace数据
  9. 新接入方案
  10. 通过OpenTelemetry接入Android Trace数据

通过OpenTelemetry接入Android Trace数据

  • 新接入方案
  • 发布于 2025-04-22
  • 0 次阅读
文档编辑
文档编辑

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

前提条件

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

步骤一:SDK集成

在App或Module级别的build.gradle文件中添加如下配置。

// BOM清单,用于同步依赖版本。
implementation(platform("io.opentelemetry:opentelemetry-bom:1.22.0"))
// API接口
implementation("io.opentelemetry:opentelemetry-api")
implementation("io.opentelemetry:opentelemetry-context")
// API extensions
implementation("io.opentelemetry:opentelemetry-extension-kotlin")
// SDK
implementation('io.opentelemetry:opentelemetry-sdk')
implementation('io.opentelemetry:opentelemetry-sdk-logs')
// semantic conventions
implementation("io.opentelemetry:opentelemetry-semconv")
// Exporters
// 官方gRPC Exporter
implementation("io.opentelemetry:opentelemetry-exporter-otlp")

更多信息,请参见OpenTelemetry Java SDK Release。

步骤二:权限配置

上报Trace数据时,需申请网络权限,即需要在AndroidManifest.xml文件中添加如下权限申明。

<uses-permission android:name="android.permission.INTERNET" />

步骤三:初始化SDK

一般建议在Application类的onCreate方法中进行SDK初始化。

// 初始化Exporter。Exporter用于导出Trace数据到日志服务Logstore。
OtlpGrpcSpanExporter grpcSpanExporter = OtlpGrpcSpanExporter.builder()
  .setEndpoint("https://${endpoint}") 
  .addHeader("x-sls-otel-project", "${project}")
  .addHeader("x-sls-otel-instance-id", "${instanceId}")
  .addHeader("x-sls-otel-ak-id", "${access-key-id}")
  .addHeader("x-sls-otel-ak-secret", "${access-key-secret}")
  .build();

// 初始化tracer provider。tracer provider用于暴露主要的API接口,对Span进行预处理、自定义Clock。
// 自定义TraceId、SpanId生成规则,自定义采样器等。您可以根据实际需求进行配置。
SdkTracerProvider tracerProvider = SdkTracerProvider.builder()
  .addSpanProcessor(BatchSpanProcessor.builder(grpcSpanExporter).build())
  .setResource(Resource.create(Attributes.builder()
                               .put(ResourceAttributes.SERVICE_NAME, "${service}")
                               .put(ResourceAttributes.SERVICE_NAMESPACE, "${service.namespace}")
                               .put(ResourceAttributes.SERVICE_VERSION, "${version}")
                               .put(ResourceAttributes.HOST_NAME, "${host}")
                               .put(ResourceAttributes.DEPLOYMENT_ENVIRONMENT, "${environment}")
                               .build()
                              )
              )
  .build();

// 初始化OpenTelemetrySdk。
OpenTelemetrySdk telemetrySdk = OpenTelemetrySdk.builder()
  .setTracerProvider(tracerProvider)
  .build(); // 如果通过build() 方法生成实例,则需要根据实际情况判断是否需要全局持有telemetrySdk。

// 您也可以初始化一个全局的OpenTelemetrySdk。
// OpenTelemetrySdk telemetrySdk = OpenTelemetrySdk.builder()
//    .setTracerProvider(tracerProvider)
//    .buildAndRegisterGlobal(); // 后续可通过GlobalOpenTelemetry.get()或GlobalOpenTelemetry.getTracer()进行访问。

变量

说明

示例

${endpoint}

服务入口是访问一个Project及其内部数据的URL,日志服务提供私网域名和公网域名。更多信息,请参见服务入口。

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

cn-hangzhou.log.aliyuncs.com:10010

${project}

日志服务Project名称,更多信息,请参见管理Project。

test-project

${instance}

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

test-traces

${access-key-id}

AccessKey ID用于标识用户,更多信息,请参见访问密钥。

建议您遵循最小化原则,按需授予RAM用户必要的权限。关于授权的具体操作,请参见创建RAM用户及授权,RAM自定义授权示例。

无

${access-key-secret}

AccessKey Secret是用户用于加密签名字符串和日志服务用来验证签名字符串的密钥,必须保密。

无

${service.namespace}

服务归属的命名空间。

order

${service}

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

payment

${version}

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

v1.0.0

${host}

主机名。

localhost

${environment}

部署环境,例如测试环境、生产环境。

pre

步骤四:使用SDK

创建Tracer

建议根据不同的业务场景创建Tracer。创建Tracer时,需传入instrumentation scope name,利于按照scope区分不同的Trace数据。

Tracer tracer = telemetrySdk.getTracer("otel application", "1.0.0");

创建基本Span

Span代表了事务中的操作。每个Span都封装了操作名称、起止时间戳、属性信息、事件信息和Context信息等。

final Span span = tracer.spanBuilder("root span").startSpan();
// do stuff
// ...
span.end();

创建嵌套Span

当您希望为嵌套操作关联Span时,OpenTelemetry支持在进程内和跨远程进程进行跟踪。例如针对methodA调用methodB ,您可以通过以下方式创建嵌套Span。

void methodA() {
  Span parentSpan = tracer.spanBuilder("operation A").startSpan();
  methodB(parentSpan);
  parentSpan.end();
}
void methodB(Span parentSpan) {
  Span childSpan = tracer.spanBuilder("operation B")
    .setParent(parentSpan)
    .startSpan();
  // do stuff
  childSpan.end();
}

OpenTemetry API还提供了一种自动化的方式来传播parentSpan。

void methodA() {
  Span parentSpan = tracer.spanBuilder("operation A").startSpan();
  try (Scope scope = parentSpan.makeCurrent()) {
    methodB();
  } finally {
    parentSpan.end();
  }
}

void methodB() {
  Span childSpan = tracer.spanBuilder("operation B").startSpan();
  // do stuff
  childSpan.end();
}

创建带属性的Span

您可以通过属性在Span上提供特定操作的上下文信息。例如执行结果、关联的其他业务信息等。

Span span = tracer.spanBuilder("GET /resource/catalog").setSpanKind(Span.Kind.CLIENT).startSpan();
span.setAttribute("http.method", "GET");
span.setAttribute("http.url", url.toString());

创建携带事件的Span

您可以通过携带多个事件的方式对Span进行注释。

span.addEvent("start");
// do stuff
// ...
span.addEvent("end");

// 也可以携带属性。
Attributes eventAttributes = Attributes.of(
  "key1", AttributeValue.stringAttributeValue("value1"),
  "key2", AttributeValue.longAttributeValue(111L)
);
span.addEvent("End Computation", eventAttributes);

创建带链接的Span

一个Span可以链接一个或多个因果相关的其他Span。

Link link1 = LinkData.create(parentSpan1.getContext());
Link link2 = LinkData.create(parentSpan2.getContext());
Span child = tracer.spanBuilder("child_with_link")
    .addLink(link1)
    .addLink(link2)
    .addLink(parentSpan3.getContext())
    .startSpan();

从远程进程中读取上下文信息的具体操作,请参见Context Propagation 。

给Span添加状态

Span包含StatusCode.UNSET、StatusCode.OK、StatusCode.ERROR三个状态,分别表示默认状态、成功状态、包含错误。

Span span = tracer.spanBuilder("operation name").startSpan();

try (Scope scope = span.makeCurrent()) {
  // do stuff
} catch (Throwable t) {
  span.setStatus(StatusCode.ERROR, "Something bad happened!");
  throw t;
} finally {
  span.end(); // 调用end()方法调用后,无法设置状态信息。
}

给Span添加异常信息

建议在捕获到异常信息之后,把异常信息添加到关联的Span中。同时,也建议同步更新Span状态。

Span span = tracer.spanBuilder("operation name").startSpan();
try (Scope scope = span.makeCurrent()) {
  // do stuff
} catch (Throwable throwable) {
  span.setStatus(StatusCode.ERROR, "Something bad happened!");
  span.recordException(throwable)
} finally {
  span.end();
}

传播上下文信息

OpenTelemetry提供了一种基于文本的方法,传播上下文信息。以下是使用HttpURLConnection发出HTTP请求的示例。

// 基于HttpURLConnection Header setter
TextMapSetter<HttpURLConnection> setter =
  new TextMapSetter<HttpURLConnection>() {
    @Override
    public void set(HttpURLConnection carrier, String key, String value) {
      // Insert the context as Header
      carrier.setRequestProperty(key, value);
    }
};

URL url = new URL("http://127.0.0.1:8088/resource/catalog");
Span httpSpan = tracer.spanBuilder("GET /resource/catalog").setSpanKind(SpanKind.CLIENT).startSpan();
try (Scope scope = httpSpan.makeCurrent()) {
  // 注入属性信息,记录HTTP请求的相关详情。
  httpSpan.setAttribute(SemanticAttributes.HTTP_METHOD, "GET");
  httpSpan.setAttribute(SemanticAttributes.HTTP_URL, url.toString());
  HttpURLConnection transportLayer = (HttpURLConnection) url.openConnection();
  // 把当前的Context信息注入到HTTP请求中。
  telemetrySdk.getPropagators().getTextMapPropagator().inject(Context.current(), transportLayer, setter);
  // do stuff
} finally {
  httpSpan.end();
}

目前,OpenTelemetry SDK支持按照W3C Trace Context标准传播上下文信息。更多信息,请参见W3CTraceContextPropagator类。

关于OpenTelemetry SDK的更多信息,请参考官方文档。

常见问题

OpenTelemetry Java SDK使用了Java 8+ API特性后,你的设备上可能会出现如下错误信息。

FATAL EXCEPTION: main
Process: xx.xx.xx.xx, PID: 2810
java.lang.NoClassDefFoundError: io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder$$ExternalSyntheticLambda0
	at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporterBuilder.<init>(OtlpGrpcSpanExporterBuilder.java:38)
	at io.opentelemetry.exporter.otlp.trace.OtlpGrpcSpanExporter.builder(OtlpGrpcSpanExporter.java:39)

针对上述问题,如果你的Android应用支持API 26以下的设备,则您需要打开coreLibraryDesugaringEnabled开关。具体操作,请参见 core library desugaring。

打开coreLibraryDesugaringEnabled开关后,你的Android应用最低可以支持到API 21的设备。

说明

目前OpenTelemetry Java SDK不支持API 21以下的设备。

相关文章

通过OpenTelemetry接入Java Trace数据 2025-04-22 10:45

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

通过OpenTelemetry接入Golang Trace数据 2025-04-22 10:45

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

通过OpenTelemetry接入Python Trace数据 2025-04-22 10:45

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

通过OpenTelemetry接入Node.js Trace数据 2025-04-22 10:45

本文介绍通过opentelemetry-js SDK将Node.js应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入C# Trace数据 2025-04-22 10:45

本文介绍通过OpenTelemetry .NET SDK将C#应用的Trace数据接入到日志服务的操作步骤。 前提条件

通过OpenTelemetry接入Rust Trace数据 2025-04-22 10:45

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

目录
Copyright © 2025 your company All Rights Reserved. Powered by 赛尔网络.
京ICP备14022346号-15
gongan beian 京公网安备11010802041014号