本文介绍通过日志服务SDK接入Android Trace数据的操作步骤。
前提条件
已创建Trace实例。更多信息,请参见创建Trace实例。说明 用于采集Trace的Android SDK后续将停止更新维护,建议通过OpenTelemetry SDK接入Android Trace数据。具体操作,请参见通过OpenTelemetry接入Android Trace数据。
步骤一:集成SDK
您可以通过自动或手动方式集成SDK。
(推荐)自动集成
说明 目前,只支持Maven中央仓库。
- 在Project级别的build.gradle文件中添加以下配置。
buildscript { repositories { google() jcenter() mavenCentral() } } allprojects { repositories { google() jcenter() mavenCentral() } }
- 在app级别的build.gradle文件中添加如下配置。
android { defaultConfig { ndk { // 设置支持的so库架构,不设置时默认支持全部架构。 abiFilters 'armeabi' //, 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } } dependencies { // Gradle 3.0以上版本请使用implementation。 implementation 'com.aliyun.openservices:aliyun-log-android-sdk:2.6.12' implementation 'com.aliyun.openservices:sls-android-core:1.0.7' implementation 'com.aliyun.openservices:sls-android-ot:1.0.7' implementation 'com.aliyun.openservices:sls-android-trace:1.0.6' // 打通移动端与服务端时需添加如下配置,且网络库需使用OkHttp3。 implementation 'com.aliyun.openservices:sls-android-okhttp:1.0.7' }
说明 在打通移动端与服务端的Trace链路时,如果需要使用其他网络库,请提工单申请。
手动集成
从Maven中央仓库下载如下SDK的最新版本。
步骤二:配置权限
在AndroidManifest.xml文件中加上如下权限申明:
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
步骤三:混淆配置
如果您的项目代码进行了打包混淆,则您需要进行混淆配置。在打包混淆规则中,需要保留com.aliyun.sls.android包名下所有的类名和方法名。例如在progaurd.cfg文件中添加如下配置。
-keep class com.aliyun.sls.android.producer.* { *; }
-keep interface com.aliyun.sls.android.producer.* { *; }
-keep class com.aliyun.sls.android.** { *; }
步骤四:接入配置
- 添加Application类,即在$PROJECT/app/src/main/AndroidManifest.xml文件中增加Application类。
例如添加MyApplication类,配置示例如下:
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.aliyun.sls.android.demo"> ... <application android:icon="@mipmap/ic_launcher" ... android:name="com.aliyun.sls.android.demo.SLSDemoApplication" ... android:theme="@style/AppTheme"> ... </application> </manifest>
IDE将根据Android Studio提示,自动创建一个名为MyApplication的类添加到当前项目中。 - 在MyApplication.onCreate方法中,增加如下初始化代码。
public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); Credentials credentials = new Credentials(); credentials.accessKeyId = "your access key id"; credentials.accessKeySecret = "your access key secret"; // 上述AccessKey是通过STS方式获取时,需配置securityToken。 credentials.securityToken = "your access security token"; TracerCredentials tracerCredentials = credentials.createTraceCredentials(); tracerCredentials.endpoint = "your trace endpoint"; tracerCredentials.project = "your trace project"; tracerCredentials.logstore = "your trace logstore"; // 使用Trace功能时,必须先完成SLSAndroid初始化。 SLSAndroid.initialize( this, credentials, configuration -> { // 开启Trace功能。 configuration.enableTracer = true; } ); // 如果需要打通移动端与服务端的Trace链路,还需要配置网络库。具体操作,请参见步骤3。 } }
- CredentialsCredentials类定义了鉴权参数。
字段 示例值 说明 accessKeyId LTAI****eYDw 日志服务Project的AccessKey ID。如何获取,请参见访问密钥。 accessKeySecret lrRq****GOVM 日志服务Project的AccessKey Secret。如何获取,请参见访问密钥。 securityToken 124f****a369 日志服务Project的访问密钥Token。使用STS方式接入时,需要配置。如何获取,请参见AssumeRole。 - TracerCredentials
TracerCredentials类定义了关键的配置字段。
字段 示例值 说明 endpoint https://cn-hangzhou.log.aliyuncs.com 您在创建Trace实例时所绑定的Project的访问域名,此处必须添加 https://
前缀。如何获取,请参见公网服务入口。重要 只支持公网服务入口。project sls-ayasls-demo 您在创建Trace实例时所绑定的Project。更多信息,请参见创建Trace实例。 logstore ayasls-traces 创建Trace实例后,日志服务会自动生成一个名为{instance}-traces的Logstore。其中{instance}为Trace实例ID。更多信息,请参见创建Trace实例。 此处需配置为该Logstore。
- SLSAndroid
SLSAndroid类提供了SDK初始化相关的全部参数配置、用户信息配置等接口。
类型 字段或方法 说明 调试方法 setLogLevel 配置SDK的日志等级。可选值为Log.VERBOSE、Log.DEBUG、Log.INFO、Log.WARN和Log.ERROR。 凭证更新 setCredentials 更新Credentials凭证信息,支持热更新。 registerCredentialsCallback 发送Span数据成功或失败时会回调onCall方法。 配置方法 setUserInfo 更新用户信息。 扩展参数配置 setExtra 新增全局扩展参数,全局生效。 removeExtra 移除全局扩展参数,全局生效。 clearExtra 清空全局扩展参数,全局生效。 - ConfigurationConfiguration类提供了SDK初始化额外参数配置的接口。
类型 字段/方法 说明 配置方法 enableTracer 是否启用Trace功能。 spanProvider 自定义Span的Resource和Attribute信息。 环境配置 env App的环境信息,默认为default。 建议开发环境配置为dev;线上环境配置为prod。
- Credentials
- 可选:配置网络库。如果需要打通移动端与服务端的Trace链路,还需添加OkHttp3网络库。即在您项目中调用OkHttp的位置,将调用方式替换为如下内容。
// client为传入参数。 // callFactory 建议作为单例来使用。 Call.Factory callFactory = OKHttp3Tracer.newCallFactory(client); // 产生一个请求。 Call call = callFactory.newCall(request);
- 可选:通过STS方式更新credentials.accessKeyId、credentials.accessKeySecret和credentials.securityToken。
public class MyApplication extends Application { // 在请求AccessKey等信息后,发起调用。 private void onUpdateSLS() { Credentials credentials = new Credentials(); // (可选)更新AccessKey。 credentials.accessKeyId = "your access key id"; credentials.accessKeySecret = "your access key secret"; credentials.securityToken = "your access security token"; // (可选)更新Project等信息。 TracerCredentials tracerCredentials = credentials.createTraceCredentials(); tracerCredentials.endpoint = "your trace endpoint"; tracerCredentials.project = "your trace project"; tracerCredentials.logstore = "your trace logstore"; SLSAndroid.setCredentials(credentials); } }
步骤五:构造Trace数据
构造单个Span
SDK提供多种方式构造单个Span。
- 通过SpanBuilder构造
- 代码格式
SpanBuilder builder = Tracer.spanBuilder("span name"); builder.setParent(span); // 设置父Span。 builder.setStart(start); // 设置起始时间。 builder.addAttribute(attribute); // 增加属性信息。 builder.addResource(resource); // 增加资源信息。 builder.setActive(true/false); // 是否保持Span活跃。 Span span = builder.build(); // 构造并开启一个Span。 span.end(); // 结束当前Span。
- 配置示例
Span span = Tracer.spanBuilder("span with children (SpanBuilder)") .addAttribute(Attribute.of("attr_key", "attr_value")) .addResource(Resource.of("res_key", "res_value")) .build(); span.end();
- 代码格式
- 通过startSpan构造
- 代码格式
Span span = Tracer.startSpan("span name"); // 调用startSpan方法后,Span处于开始状态。 span.addAttribute(attribute); // 增加属性信息。 span.addResource(resource); // 增加资源信息。 span.setStart(start); // 设置起始时间,一般无需设置。 span.setName("span name"); // 设置Span名称。 span.setStatus(ERROR/OK/UNSET); // 设置Span状态,默认是UNSET。 span.setStatusMessage("span status message"); // 设置Span状态的描述信息。 span.setParentSpanId("parent span id"); // 设置父Span ID。 span.setService("service name"); // 设置服务名称,默认为Android,一般无需设置。 span.setSpanId("span id"); // 自定义Span ID,一般无需设置。 span.setTraceId("trace id"); // 自定义Trace ID,一般无需设置。 span.end(); // 结束当前Span。
- 配置示例
Span span = Tracer.startSpan("span 1"); span.addAttribute(Attribute.of("attr_key", "attr_value")) .addResource(Resource.of("res_key", "res_value")); span.end();
- 代码格式
- 通过withinSpan构造
通过withinSpan方式构造Span,无需关注Span的start和end设置。一般情况下,需要把业务代码放入到Runnable中,并且构造的Span无法设置额外信息。
- 代码格式
Tracer.withinSpan("span name", new Runnable() { @Override public void run() { // 代码块。 } });
- 配置示例
Tracer.withinSpan("span with block", new Runnable() { @Override public void run() { android.util.Log.d("debug", "print log from withinSpan"); } });
- 代码格式
构造一条包含多个Span的Trace数据
一条Trace数据会关联1个或多个Span。SDK提供多种方式,关联不同Span。
- 通过SpanBuilder构造
Span span = Tracer.spanBuilder("span with children (SpanBuilder)") .setActive(true) // 必须设置为true。 .addAttribute(Attribute.of("attr_key", "attr_value")) .addResource(Resource.of("res_key", "res_value")) .build(); Tracer.startSpan("child span 1 (SpanBuilder)").end(); Tracer.startSpan("child span 2 (SpanBuilder)").end(); span.end(); // 结束Trace。
- 通过startSpan构造
Span span = Tracer.startSpan("span with children", true); // 第二个参数必须设置为true。 Tracer.startSpan("child span 1").end(); Tracer.startSpan("child span 2").end(); span.end(); // 结束Trace。
- 通过withinSpan构造
Tracer.withinSpan("span with func block", new Runnable() { @Override public void run() { Tracer.startSpan("span within func block 1").end(); // 子Trace。 Tracer.withinSpan("nested span with func block", new Runnable() { @Override public void run() { Tracer.startSpan("nested span 1").end(); Tracer.startSpan("nested span 2").end(); } }); Tracer.startSpan("span within func block 2").end(); } });
自定义Attribute和Resource
SDK支持通过SpanProvider添加自定义信息。通过SpanProvider创建的Resource和Attribute将添加到所有Span中。您可以根据这个特性为所有Span添加业务关联的Resource和Attribute信息。
// 此处省略Credentials的初始化过程。
// ...
SLSAndroid.initialize(
this,
credentials,
configuration -> {
// 此处省略configuration的其他配置。
// ...
configuration.spanProvider = new ISpanProvider() {
@Override
public Resource provideResource() {
return Resource.of("other_resource_key", "other_resource_value");
}
@Override
public List<Attribute> provideAttribute() {
List<Attribute> attributes = new ArrayList<>();
attributes.add(Attribute.of("other_attribute_key", "other_attribute_value"));
return attributes;
}
};
}
);
// 此处省略其他配置过程。
// ...
参数说明
- Tracer
字段/方法 说明 spanBuilder(name) 构造一个SpanBuider对象。 startSpan(name) 构造一个Span对象。 startSpan(name, active) 构造一个Span对象,根据active的值决定是否设置为活跃Span。 withinSpan(name, runnable) 构造一个Span对象,并设置为活跃Span,自动执行runnable代码块。 withinSpan(name, active, runnable) 构造一个Span对象,根据active的值决定是否设置为活跃Span,并自动执行runnable代码块 withinSpan(name, active, parent, runnable) 构造一个Span对象,根据active的值决定是否设置为活跃Span,并设置该Span对象的父Span为parent,自动执行runnable代码块。 - SpanBuilder
字段/方法 说明 SpanBuilder(name, processor, provider) 构造一个SpanBuilder对象,并指定Span名称,SpanProcessor,SpanProvider。 不建议直接调用方法。
setParent(parent) 设置父Span。 setActive(active) 设置是否为活跃Span。 setKind(SpanKind) 设置Span类型,支持设置为INTERNAL、SERVER、CLIENT、PRODUCER、CONSUMER。默认为CLIENT。 setStart(start) 设置Span的开始时间。 addAttribute(attribute) 增加Attribute属性信息。 addAttribute(attributes) 增加一组Attribute属性信息。 addResource(resource) 增加Resource资源信息。 - Span
字段/方法 说明 setName(name) 设置Span名称。 setKind(SpanKind) 设置Span类型,支持设置为INTERNAL、SERVER、CLIENT、PRODUCER、CONSUMER。默认为CLIENT。 setTraceId(traceId) 设置Trace ID,不建议手动设置。 setSpanId(spanId) 设置Span ID,不建议手动设置。 setParentSpanId(spanId) 设置父Span ID。 setStart(start) 设置Span开始时间,不建议手动设置。 setEnd(end) 设置Span结束时间。 setDuration(duration) 设置Span持续时间,不建议手动设置。 setStatus(StatusCode) 设置Span状态,支持设置为ERROR、UNSET、OK。默认为UNSET。 setStatusMessage(message) 设置Span状态的描述信息。 setHost(host) 设置Host。 setService(service) 设置服务名称,默认为Android。 addAttribute(attribute) 增加Attribute属性信息。 addAttribute(attribute...) 增加Attribute属性信息。 addAttribute(attributes) 增加Attribute属性信息。 addResource(resource) 增加Resource资源信息。 end() 结束当前Span。 isEnd() 判断当前Span是否结束。 toMap() 转换Span数据结构为Map对象。 - Resource
字段/方法 说明 getDefault() 返回默认的Resource对象,包含的默认资源信息,请参见Resource对象信息。 of(String key, Object value) 基于传入的key和value,返回一个Resource对象。 of(Pair<String, Object>... resources) 根据传入的Pair键值对,返回一个Resource对象。 of(List<Attribute> attributes) 根据传入的Attribute List,返回一个Resource对象。 add(String key, Object value) 添加key和value信息到当前Resource对象。 merge(Resource resource) 将传入的Resource对象信息合并到当前Resource中实现。 Resource对象信息
key value sdk.language Android host.name Android device.model.identifier Build.MODEL device.model.name Build.PRODUCT device.manufacturer Build.MANUFACTURER os.type Linux os.description Build.DISPLAY os.name Android os.version Build.VERSION.RELEASE os.sdk Build.VERSION.SDK host.name Build.HOST host.type Build.TYPE host.arch Build.CPU_ABI + (TextUtils.isEmpty(Build.CPU_ABI2) ? "" : (", " + Build.CPU_ABI2)) sls.sdk.version BuildConfig.VERSION_NAME - Attribute
字段/方法 说明 of(String key, boolean value) 返回一个Attribute对象。 of(String key, int value) 返回一个Attribute对象。 of(String key, long value) 返回一个Attribute对象。 of(String key, double value) 返回一个Attribute对象。 of(String key, String value) 返回一个Attribute对象。 of(final String key, final Object value) 返回一个Attribute对象。 of(Pair<String, Object>... kvs) 返回一个Attribute List对象。
其他说明
设置Span为活跃后,在当前上下文环境中新产生的Span都会与活跃Span自动关联。具体表现为
currentSpan.parentSpanID = activeSpan.spanID
、currentSpan.traceID = activeSpan.traceID
。说明 不同的业务代码运行在同一个线程时,上下文环境就是指当前线程。同一个上下文环境只有一个Span处于活跃状态。