集成SDK插件到App后,您只需启动App,网络质量分析器就会自动进行网络探测。本文介绍SDK插件的使用说明。
集成操作步骤
上线前测试阶段,请检查以下几项:
在控制台配置的网络探测规则是否成功触发,以控制台中看到的对应探测数据为准。
检查客户端主动发起的探测是否成功上报,以控制台中看到的对应探测数据为准,建议和控制台配置的探测规则的探测目标不同,以便区分。
针对上述步骤1、2分别检查不同平台,如Android、iOS和Windows等。
有条件的话,海外和中国内地不同终端都验证下是否能成功上报数据。
iOS SDK接入
在Podfile文件中添加以下配置。
source 'https://gitee.com/aliyun-sls/Specs.git' pod 'AliyunLogProducer', '4.3.4' # 建议使用最新版本 pod 'AliyunLogNetworkDiagnosis', '4.3.8' # 建议使用最新版本
更多版本信息,请参见aliyun-log-ios-sdk。
在AppDelegate类中引入如下头文件。
#import <AliyunLogNetworkDiagnosis/AliyunLogNetworkDiagnosis.h>
在AppDelegate类的
application: didFinishLaunchingWithOptions:
方法中添加如下SDK初始化代码。重要上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在移动端应用中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务。
SLSCredentials *credentials = [SLSCredentials credentials]; // endpoint和project不支持动态更新,请在初始化SDK时指定 credentials.endpoint = @"<your endpoint>"; credentials.project = @"<your project>"; // AccessKey建议通过STS方式获取,参考文档:采集-搭建移动端日志直传服务 // AccessKey在初始化时可以先不填,后续通过[[SLSCocoa sharedInstance] setCredentials:credentials];方法可以更新,参考后面的updateSDK方法实现 credentials.accessKeyId = @"<your accessKeyId>""; credentials.accessKeySecret = @"<your accessKeySecret>"; credentials.securityToken = @"<your accessKey securityToken>"; // 仅当AccessKey是通过STS服务获取时需要 SLSNetworkDiagnosisCredentials *networkCredentials = [credentials createNetworkDiagnosisCredentials]; //secretKey不支持动态更新,请在初始化时指定 networkCredentials.secretKey = self.secretKey; // (可选)设置业务扩展字段。仅对新产生的探测数据生效。 // 不支持动态更新,请在SDK初始化时设置。 [networkCredentials putExtension:@"custom_value" forKey:@"custom_key"]; // 用户接受隐私协议之前,先调用preInit完成SDK初始化。 [[SLSCocoa sharedInstance] preInit:credentials configuration:^(SLSConfiguration * _Nonnull configuration) { configuration.enableNetworkDiagnosis = YES; }]; // 用户接受隐私协议之后,再调用initialize完成SDK的完整初始化。 [[SLSCocoa sharedInstance] initialize:credentials configuration:^(SLSConfiguration * _Nonnull configuration) { configuration.enableNetworkDiagnosis = YES; }]; // (可选)设置设备ID,可在任何时机调用,仅对新产生的探测数据生效。 [SLSUtdid setUtdid:@"<your device id"]; // (可选)配置用户信息,可在任何时机调用。仅对新产生的探测数据生效。 SLSUserInfo *userInfo = [SLSUserInfo userInfo]; userInfo.uid = @"<your user id>"; userInfo.channel = @"<your user channel"; [userInfo addExt:@"ext_value" key:@"ext_key"]; [[SLSCocoa sharedInstance] setUserInfo:userInfo];
更多SDK使用示例请参考:Demo示例。
重要参数说明如下表所示。
字段
是否必填
说明
secretKey
是
接入端应用的密钥。更多信息,请参见创建接入端应用。
putExtension
否
设置自定义信息,支持设置多个键值对。设置后,探测数据中将附加这些信息。
endpoint
是
日志服务Project所属的Endpoint,必须以https://开头。如何获取,请参见公网。
project
是
您在创建接入端应用时指定的Project。更多信息,请参见创建接入端应用。
Apple的Local Network Privacy(本地网络隐私)政策适配。
适用场景。
从iOS14开始,Apple对访问本地网络的隐私政策进行了升级。如果您的应用使用了我们SDK提供的以下功能,可能会触发Local Network Privacy政策:
使用DNS(域名解析)探测功能:当您使用我们的SDK进行DNS探测,以下两种情形都会触发Local Network Privacy政策。
调用者指定DNS服务器(域名解析服务器):当您指定的DNS服务器为私有IP地址(什么是私有地址)时。
调用者不指定DNS服务器:当设备网络处于WiFi环境下时。
使用
ping
、mtr
、tcpping
、udpping
等其他探测接口时,目标地址为私有IP地址时。
如何适配本地网络隐私政策?
当您的使用场景会触发Local Network Privacy政策时,集成步骤中需要确保执行如下措施以避免在提交App Store时被审核拒绝。
在应用的Info.plist中增加如下键值对:
<key>NSLocalNetworkUsageDescription</key> <string>您的应用需要访问本地网络的目的说明</string>
说明网络本地网络目的需要符合您提供的应用的实际场景,关键要点包括:
说明访问本地网络的目的,列举具体的功能和服务场景,表明对用户有实际价值和意义。
承诺会尊重用户隐私,经授权、在必要时才访问,不获取隐私数据,让审核人员放心。
语气真诚友好,希望得到理解支持,体现对审核的重视,有利于通过。
Apple的Local network privacy政策介绍(官方Local Network Privacy FAQ)。
Apple的Local network privacy(本地网络隐私)是iOS 14、iPadOS 14、tvOS 14和watchOS 7引入的一项新隐私保护功能。其主要目的在于让您了解哪些应用程序正在局域网内与其他设备通信,以防止应用程序在未经用户许可的情况下滥用本地网络。以下是关于这一功能的详细解释:
本地网络访问权限:当应用程序首次尝试在局域网内与其他设备通信时,系统会向用户显示一个弹窗,询问是否允许该应用访问本地网络。您可以选择是或者否。这为您提供了对应用程序网络行为更多的控制和了解。
本地网络应用程序指示器:当应用程序在局域网内与其他设备通信时,状态栏会显示一个指示器(通常是一个带箭头的圆点),以提示您当前有应用程序正在使用本地网络,增加了透明度。
微调隐私设置:您可以在系统设置的隐私部分查看和管理哪些应用程序被授予了访问本地网络的权限。随时撤销或重新授予权限。
影响范围:任何使用Bonjour、mDNS或其他局域网通信技术的应用程序都会受到本地网络隐私的影响。常见的场景包括局域网多人游戏、文件共享、智能家居设备控制等。
开发者适配:为确保应用程序在新的隐私策略下正常工作,开发者需要正确处理本地网络访问权限的请求和结果。未经授权的网络访问可能会导致应用程序无法正常运行。
教育:在系统升级过程中,Apple会向您介绍新功能,而应用程序开发者也有责任向您解释他们需要访问本地网络的原因,以及如何妥善处理您的隐私关切。
Local network privacy提升了用户对应用网络活动的可见性和掌控度,有效阻止恶意应用的数据窃取或网络资源滥用行为。这同时也向开发者提出了更高要求,需在功能实现与用户隐私保护间寻找平衡。
Android SDK接入
在根build.gradle文件中添加以下配置。
repositories { google() jcenter() mavenCentral() maven { url 'https://maven.aliyun.com/repository/public/' } }
添加如下依赖。
implementation 'io.github.aliyun-sls:aliyun-log-android-sdk:2.7.1@aar' // 建议使用最新版本 implementation 'io.github.aliyun-sls:sls-android-core:1.0.10@aar' // 建议使用最新版本 implementation 'io.github.aliyun-sls:sls-android-ot:1.0.8.1@aar' // 建议使用最新版本 implementation 'io.github.aliyun-sls:sls-android-network-diagnosis:2.2.6@aar' // 建议使用最新版本 implementation 'com.squareup.okhttp3:okhttp:3.11.0' // (可选)最低兼容3.10.0版本,HTTP探测时必须
更多版本信息,请参见aliyun-log-android-sdk。
添加如下初始化代码。
Credentials credentials = new Credentials(); // (必填)endpoint和project不支持动态更新,请在初始化SDK时指定 credentials.endpoint = "<your endpoint>"; credentials.project = "<your project>"; // AccessKey建议通过STS方式获取,参考文档:采集-搭建移动端日志直传服务 // AccessKey在初始化时可以先不填,后续通过SLSAndroid.setCredentials(credentials);方法可以更新,参考后面的updateSDK方法实现 credentials.accessKeyId = "<your accessKeyId>"; credentials.accessKeySecret = "<your accessKeySecret>"; //credentials.securityToken = "<your accessKey securityToekn>"; // 仅当AccessKey是通过STS服务获取时需要 NetworkDiagnosisCredentials networkDiagnosisCredentials = credentials.getNetworkDiagnosisCredentials(); // (必填)secretKey不支持动态更新,请在初始化时设置。 networkDiagnosisCredentials.secretKey = secretKey; // (可选)设置业务扩展字段。仅对新产生的探测数据生效。 // 不支持动态更新,请在SDK初始化时设置。 networkDiagnosisCredentials.extension.put("custom_key", "custom_value"); SLSAndroid.initialize( getApplicationContext(), credentials, configuration -> configuration.enableNetworkDiagnosis = true ); // (建议)注册探测数据上报回调 SLSAndroid.registerCredentialsCallback((feature, result) -> { if (LogProducerResult.LOG_PRODUCER_SEND_UNAUTHORIZED == result || LogProducerResult.LOG_PRODUCER_PARAMETERS_INVALID == result) { // 处理AccessKey过期、失效等鉴权问题 Credentials credentials = new Credentials(); credentials.accessKeyId = "<your accessKeyId>"; credentials.accessKeySecret = "<your accessKeySecret>"; credentials.securityToken = "<your accessKey securityToekn>"; SLSAndroid.setCredentials(credentials); } }); // (可选)设置设备ID,可在任何时机调用,仅对新产生的探测数据生效。 SLSAndroid.setUtdid(getApplicationContext(), "<your device id"); // (可选)配置用户信息,可在任何时机调用。仅对新产生的探测数据生效。 UserInfo userInfo = new UserInfo(); userInfo.uid = "<your user id>"; userInfo.channel = "<your user channel>"; userInfo.addExt("ext_key", "ext_value"); SLSAndroid.setUserInfo(userInfo);
更多SDK使用示例请参考:Demo示例。
字段
是否必填
说明
secretKey
是
接入端应用的密钥。更多信息,请参见创建接入端应用。
extension.put
否
设置自定义信息,支持设置多个键值对。设置后,探测数据中将附加这些信息。
endpoint
是
日志服务Project所属的Endpoint,必须以https://开头。如何获取,请参见公网。
project
是
您在创建接入端应用时指定的Project。更多信息,请参见创建接入端应用。
accessKeyId
是
具备访问日志服务Logstore权限的AccessKey ID。
建议您遵循最小化原则,按需授予RAM用户必要的权限。关于授权的具体操作,请参见创建RAM用户及授权、RAM自定义授权示例。
accessKeySecret
是
具备访问日志服务Logstore权限的AccessKey Secret。
AccessKey Secret是用户用于加密签名字符串和日志服务用来验证签名字符串的密钥,必须保密。
securityToken
否
访问密钥的Token。使用STS方式接入时,需要配置。如何获取,请参见AssumeRole - 获取扮演角色的临时身份凭证。
Unity插件接入
下载并导入Unity插件到您的Unity工程。
下载最新版本的Unity插件,双击
.unitypackage
文件,导入插件相关的文件到您的Unity项目中。插件包目录说明:
Assets/Plugins/Unity4SLS: Plugin脚本。
Assets/Plugins/Unity4SLS/Android/libs:Android平台依赖的SDK和NDK。
Assets/Plugins/Unity4SLS/iOS/:iOS平台依赖的Framework和静态库。
Assets/Plugins/Unity4SLS/Windows/:Windows平台依赖的库。
初始化插件。
重要上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在移动端应用中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务。
using AliyunSLS; Credentials credentials = new Credentials(); // (必填)endpoint和project不支持动态更新,请在初始化SDK时指定 credentials.endpoint = "<your endpoint>"; credentials.project = "<your project>"; credentials.secretKey = "<your secretKey>"; // (可选)AccessKey建议通过STS方式获取,参考文档:采集-搭建移动端日志直传服务 // AccessKey在初始化时可以先不填,后续通过SLSAndroid.setCredentials(credentials);方法可以更新,参考后面的updateSDK方法实现 credentials.accessKeyId = accessKeyId; credentials.accessKeySecret = accessKeySecret; //credentials.securityToken = "<your accessKey securityToekn>"; // 仅当AccessKey是通过STS服务获取时需要 // (可选)设置业务扩展字段。仅对新产生的探测数据生效。 credentials.extension = new Dictionary<string, string>(); extensions.Add("key_from_unity", "value_from_unity"); // (可选)设置设备ID credentials.deviceId = "<your device id>"; // 初始化SDK。 Unity4SLS.Initialize(credentials); //(可选)配置用户信息,可在任何时机调用,仅对新产生的探测数据生效。 UserInfo info = new UserInfo(); info.uid = "12312123123123"; info.channel = "dev_debug"; info.ext.Add("u_key1", "u_value1"); Unity4SLS.SetUserInfo(info);
字段
是否必填
说明
secretKey
是
接入端应用的密钥。更多信息,请参见创建接入端应用。
extensions.Add
否
设置自定义信息,支持设置多个键值对。设置后,探测数据中将附加这些信息。
endpoint
是
日志服务Project所属的Endpoint,必须以https://开头。如何获取,请参见公网。
project
是
您在创建接入端应用时指定的Project。更多信息,请参见创建接入端应用。
Windows SDK接入
下载地址
单击Windows SDK,下载Windows SDK包。
MD模式下,发布应用前请检查项目中是否缺少VCRuntime系列dll和Visual C++ Redistributable for Visual Studio相关动态库文件,网络质量分析器 Windows SDK所需的动态库文件参考以下目录:
msvcp140.dll msvcp140_codecvt_ids.dll ucrtbase.dll vcruntime140.dll vcruntime140_1.dll api-ms-win-crt-runtime-l1-1-0.dll api-ms-win-core-localization-l1-2-0.dll api-ms-win-core-processthreads-l1-1-1.dll api-ms-win-core-file-l1-2-0.dll api-ms-win-core-timezone-l1-1-0.dll api-ms-win-core-file-l2-1-0.dll api-ms-win-core-synch-l1-2-0.dll api-ms-win-crt-heap-l1-1-0.dll api-ms-win-core-string-l1-1-0.dll api-ms-win-crt-string-l1-1-0.dll api-ms-win-crt-stdio-l1-1-0.dll api-ms-win-crt-convert-l1-1-0.dll api-ms-win-crt-time-l1-1-0.dll api-ms-win-crt-utility-l1-1-0.dll api-ms-win-crt-filesystem-l1-1-0.dll api-ms-win-crt-environment-l1-1-0.dll api-ms-win-crt-locale-l1-1-0.dll api-ms-win-crt-math-l1-1-0.dll
WindowsSDK支持x64/x86模式下多种集成方式,请根据项目需求选择对应的文件夹:
DLL-MD:动态库,运行时库MD;
DLL-MT:动态库,运行时库MT;
LIB-MD:静态库,运行时库MD;
LIB-MT:静态库,运行时库MT;
上报日志到日志服务时需使用阿里云账号或RAM用户的AccessKey,用于鉴权及防篡改。为避免将AccessKey保存在代码中,造成安全风险,推荐您使用移动端日志直传服务配置AccessKey。具体操作,请参见采集-搭建移动端日志直传服务。
集成方式
隐式加载
SDK集成准备:
将
/lib
目录下的库文件和/include
目录下的头文件添加到项目中。配置附加库目录路径。
在集成动态库的过程中,需要将
alinetworkdiagnosisMD.dll
(根据集成方式的不同,文件后缀可能有所变化)同步到生成目录中。
SDK初始化:
#include "api.h" void logcallback(const char* s) { printf("[demo-logcallback] %s", (char*)s); } void on_token_ex() { printf("[demo-token-expired-callback] ----------------------token expired callback excited----------------\n"); } void on_token_ex_ctx(void* ctx) { printf("[demo-token-expired-callback] ----------------------context : %s ----------------------\n",(char*)ctx); printf("[demo-token-expired-callback] ----------------------token expired callback excited----------------\n"); } void demoInit(){ //开始初始化。 printf("start init sdk\n"); AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig(); //必填,接入端应用的密钥。 config.setSecKey("{your_secret_key}"); //必填,日志上报logstore的AccessKey设置,下述两种方式二选一 config.setSlsCredential("{your_access_key_id}","{your_access_key_secret}"); //或 //对于通过STS方式获取AccessKey,使用如下方式初始化AccessKey并设置token失效回调,支持携带自定义参数。 config.setSlsCredential("{your_access_key_id}","{your_access_key_secret}","your_security_token"); config.setTokenExpiredCallback(on_token_ex); //或 const char* s = "it's user's context"; config.setTokenExpiredCallback(on_token_ex_ctx, (void*)s); //可选,设置设备ID。 config.setDeviceId("{your_device_id}"); //可选,设置用户自定义拓展信息,用于业务自定义标识。 std::map<std::string, std::string> mp; mp.insert(make_pair("key", "value")); config.setExtension(mp); //可选,设置最大并发线程数。 config.setThreadPool(20); //可选,设置日志回调,支持设置日志输出最低等级。 config.setLogback(logcallback);//默认输出log_debug及以上等级的日志 //或 config.setLogCallback(logcallback, Log_Level::log_error); //初始化SDK。 config.init(); //或者预初始化SDK,见“隐私合规” config.preInit(); //初始化完成。 printf("end init sdk\n"); } // 请求AccessKey信息。 void requestAccessKey() { // 推荐您先使用移动端日志直传服务配置AccessKey信息。 // ... // 获取AccessKey信息后,完成更新。 updateAccessKey(accessKeyId, accessKeySecret, securityToken); } // token失效回调,用于更新AccessKey信息。 void updateAccessKey(std::string accessKeyId, std::string accessKeySecret, std::string securityToken) { // 通过STS服务获取的AccessKey包含securitToken,需要使用以下方式更新。 config.setSlsCredential(accessKeyId, accessKeySecret, securityToken); }
显式加载
SDK集成准备:需要将
alinetworkdiagnosisMD.dll
(根据集成方式的不同,文件后缀可能有所变化)同步到生成目录中。SDK初始化:
#include <stdio.h> #include <windows.h> // 其他方法及参数说明,详见"api.h" typedef void (*DLLInit)(const char* secret_key, const char* device_id, const char* accessKeyId, const char* accessKeySecret, const char* securityToken, const char** extensions, int extLength); // 或定义预初始化函数 typedef void (*DLLPreInit)(const char* secret_key, const char* device_id, const char* accessKeyId, const char* accessKeySecret, const char* securityToken, const char** extensions, int extLength); int init() { // 获取动态库句柄,具体后缀视集成方式而定 HINSTANCE hdll = LoadLibrary(L"alinetworkdiagnosisMD.dll"); if (hdll == NULL) { // 加载库失败,返回错误码 fprintf(stderr, "Failed to load library.\n"); return -11; } // 获取函数地址 DLLInit _ipa_init = (DLLInit)GetProcAddress(hdll, "_ipa_init"); if (_ipa_init == NULL) { // 获取函数地址失败,释放库并返回错误码 fprintf(stderr, "Failed to get function address from library.\n"); FreeLibrary(hdll); return -1; } // 定义扩展参数 const char* extensions[] = { "Bigkey1", "value1", "Bigkey2", "value2", "Bigkey3", "value3" }; // 调用初始化函数 _ipa_init("{your_secret_key}", "{your_device_id}", "{your_access_key_id}", "{your_access_key_secret}", "{your_security_token}", extensions, 3); // 成功初始化,返回0 return 0; }
扩展功能
AccessKey自定义策略最佳实践
提供给SDK用于上报日志的凭证:AccessKey或者STS Token,需要分配SLS Logstore的访问策略。按照最小权限原则,我们需要指定凭证的访问策略范围为对应Logstore的只写权限。请参考如下代码:
代码块中your-project
和your-logstore
分别替换为应用详情中的project和原始探测数据Logstore,关于应用详情,请参见查看应用详情。
{
"Effect":"Allow",
"Action":[
"log:PostLogStoreLogs"
],
"Resource":[
"acs:log:*:*:project/your-project/logstore/your-logstore"
]
}
处理AccessKey失效
在初始化SDK配置AccessKey时,如果AccessKey是通过STS方式获取到的,则AccessKey可能会面临失效的问题。在AccessKey失效时,SDK支持通过配置回调的方式来接收AccessKey失效信息。
iOS SDK
[[SLSCocoa sharedInstance] registerCredentialsCallback:^(NSString * _Nonnull feature, NSString * result) {
if ([@"LogProducerSendUnauthorized" isEqualToString:result] ||
[@"LogProducerParametersInvalid" isEqualToString:result]) {
//处理token过期,AccessKey失效等鉴权类型问题。
//获取到新的token后,调用如下代码更新token。
SLSCredentials *credentials = [SLSCredentials credentials];
credentials.accessKeyId = accessKeyId;
credentials.accessKeySecret = accessKeySecret;
credentials.securityToken = securityToken; //可选,STS方式获取的token必须要填。
//更新凭证信息。
[[SLSCocoa sharedInstance] setCredentials:credentials];
}
}];
Android SDK
SLSAndroid.registerCredentialsCallback((feature, result) -> {
if (LogProducerResult.LOG_PRODUCER_SEND_UNAUTHORIZED == result ||
LogProducerResult.LOG_PRODUCER_PARAMETERS_INVALID == result) {
// 处理token过期,AccessKey失效等鉴权类问题。
Credentials credentials = new Credentials();
credentials.accessKeyId = accessKeyId;
credentials.accessKeySecret = accessKeySecret;
credentials.securityToken = securityToken;
SLSAndroid.setCredentials(credentials1);
}
});
Unity
/// <summary>
/// 设置回调。
/// </summary>
public void setCredentialsCallback()
{
callback_delegate callback = new callback_delegate(credentialsCallback);
Unity4SLS.RegisterCredentialsCallback(callback);
}
// 处理AccessKey过期或无效。
public void credentialsCallback(string feature, string result)
{
if ("LogProducerSendUnauthorized" == result ||
"LogProducerParametersInvalid" == result ||
"LOG_PRODUCER_SEND_UNAUTHORIZED" == result ||
"LOG_PRODUCER_PARAMETERS_INVALID" == result)
{
Credentials credentials = new Credentials();
credentials.accessKeyId = accessKeyId;
credentials.accessKeySecret = accessKeySecret;
Unity4SLS.SetCredentials(credentials);
}
}
Windows SDK
void on_token_ex() {
//获取配置类。
AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();
//设置AccessKeyId、AccessKeySecret、Token。
config.setSlsCredential(accessKeyId, accessKeySecret, securityToken);
printf("[token-expired-callback] token expired callback excited\n");
}
主动探测
SDK 支持 PING、TCPPING、HTTP、MTR、DNS等多种探测方式的主动发起。您可以调用以下API发起主动探测。
PING
iOS SDK
SLSPingRequest *request = [[SLSPingRequest alloc] init];
request.domain = @"www.example.com";
//可选参数。
request.context = @"<your ping context id>";
request.parallel = YES;
//可选参数。
request.extention = @{
@"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] ping2:request callback:^(SLSResponse * _Nonnull response) {
NSLog(@"ping result: %@", response.content);
}];
Android SDK
PingRequest request = new PingRequest();
request.domain = "www.example.com";
//可选参数。
request.multiplePortsDetect = true; //启用多网卡探测。
request.context = "<your ping context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
{
put("custom_key", "custom_value");
}
};
NetworkDiagnosis.getInstance().ping(request, response -> {
SLSLog.d(TAG, String.format("ping result: %s", response.content));
});
Unity
PingRequest request = new PingRequest();
request.domain = "www.example.com";
// 可选参数,设置探测上下文
request.context = "your ping request context id";
// 可选参数,设置探测级extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");
// 可选参数,设置探测级回调函数
request.complete_callback = (response) =>
{
Debug.Log("ping->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 发起探测
Unity4SLS.Ping(request);
Windows SDK
//必选,初始化探测参数(任务ID(可为空字符串)、探测目标、DNS解析(0~3分别代表v4优先、v6优先、v4 only、v6 only)、探测端口)。
PingConfig* pingConfig = new PingConfig("0", "www.example.com", 0, 80);
//可选,修改探测目标。
pingConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
pingConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
pingConfig->setInterval(100);
//可选,修改探测超时时间。
pingConfig->setTimeout(2000);
//可选,设置探测结束时的回调
pingConfig->setCallback(demo_ping_callback);
//发起探测。
pingConfig->Detect();
//另:demo_ping_callback 范例:
void demo_ping_callback(void* context, char* json_result) {
std::string* ctx = static_cast<std::string*>(context);
printf("[探测结果回调 demo-ping-callback] %s, context : %s\n", json_result, ctx->c_str());
}
TCPPING
iOS SDK
SLSTcpPingRequest *request = [[SLSTcpPingRequest alloc] init];
request.domain = @"www.example.com";
request.port = 80;
//可选参数。
request.context = @"<your tcpping context id>";
//可选参数。
request.extention = @{
@"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] tcpPing2:request callback:^(SLSResponse * _Nonnull response) {
NSLog(@"ping result: %@", response.content);
}];
Android SDK
TcpPingRequest request = new TcpPingRequest();
request.domain = "www.example.com";
request.port = 80;
//可选参数。
request.context = "<your tcp ping context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
{
put("custom_key", "custom_value");
}
};
NetworkDiagnosis.getInstance().tcpPing(request, response -> {
SLSLog.d(TAG, String.format("tcp ping result: %s", response.content));
});
Unity
TcpPingRequest request = new TcpPingRequest();
request.domain = "www.example.com";
request.port = 80;
// 可选参数,设置探测上下文
request.context = "your tcpping request context id";
// 可选参数,设置探测级extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");
// 可选参数,设置探测级回调函数
request.complete_callback = (response) =>
{
Debug.Log("tcpping->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 发起探测
Unity4SLS.TcpPing(request);
Windows SDK
//必选,初始化探测参数(任务ID(可为空字符串)、探测目标、DNS解析(0~3分别代表v4优先、v6优先、v4 only、v6 only)、探测端口)
TcppingConfig* tcppingConfig = new TcppingConfig("", "www.example.com", 1, 80);
//可选,修改探测目标。
tcppingConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
tcppingConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
tcppingConfig->setInterval(100);
//可选,修改探测超时时间。
tcppingConfig->setTimeout(2000);
//可选,设置探测结束时的回调
tcppingConfig->setCallback(demo_tcpping_callback);
//发起探测。
tcppingConfig->Detect();
//另:demo_tcpping_callback 范例:
void demo_tcpping_callback(void* context, char* json_result) {
std::string* ctx = static_cast<std::string*>(context);
printf("[探测结果回调 demo-tcpping-callback] %s, context : %s\n", json_result, ctx->c_str());
}
HTTP
iOS SDK
SLSHttpRequest *request = [[SLSHttpRequest alloc] init];
request.domain = @"https://demo.ne.aliyuncs.com";
//可选参数。
request.context = @"<your http context id>";
request.headerOnly = YES;
request.downloadBytesLimit = 128 * 1024; // 128KB
//可选参数,证书检验回调。getHttpCredential的配置参考下文。
request.credential = ^NSURLCredential * _Nullable(NSString * _Nonnull url) {
return [self getHttpCredential:url];
};
//可选参数。
request.extention = @{
@"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] http2:request callback:^(SLSResponse * _Nonnull response) {
NSLog(@"ping result: %@", response.content);
}];
Android SDK
HttpRequest request = new HttpRequest();
//可选参数。
request.context = "<your http context id>";
request.headerOnly = true;
request.downloadBytesLimit = 1024;
//可选参数,证书检验回调。getSSLContext的配置参考下文。
request.credential = new HttpCredential(getSSLContext(context), null);
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
{
put("custom_key", "custom_value");
}
};
request.domain = "https://www.example.com";
NetworkDiagnosis.getInstance().http(request, response -> {
SLSLog.d(TAG, String.format("http result: %s", response.content));
});
Unity
HttpRequest request = new HttpRequest();
request.domain = "https://www.example.com";
// 可选参数,设置探测上下文
request.context = "your http request context id";
request.headerOnly = true;
request.downloadBytesLimit = 1024;
// 可选参数,设置探测级extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");
// 可选参数,设置探测级回调函数
request.complete_callback = (response) =>
{
Debug.Log("http->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 发起探测
Unity4SLS.Http(request);
Windows SDK
//必选,初始化探测参数(任务ID,探测目标,DNS解析(0~3分别代表v4优先、v6优先、v4 only、v6 only))
HttpDetectionConfig* httpConfig = new HttpDetectionConfig("", "http://www.example.com", 1);
//可选,修改探测目标。
httpConfig->setTarget("http://www.example.com");
//可选,修改探测任务ID。
httpConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
httpConfig->setInterval(100);
//可选,修改探测超时时间。
httpConfig->setTimeout(2000);
//可选,设置探测结束时的回调
httpConfig->setCallback(demo_http_callback);
//发起探测。
httpConfig->Detect();
//demo_http_callback 范例:
void demo_http_callback(void* context, char* json_result) {
std::string* ctx = static_cast<std::string*>(context);
printf("[探测结果回调 demo-http-callback] %s, context : %s\n", json_result, ctx->c_str());
}
MTR
iOS SDK
SLSMtrRequest *request = [[SLSMtrRequest alloc] init];
request.domain = @"www.example.com";
//可选参数。
request.context = @"<your mtr context id>";
request.parallel = YES;
request.protocol = SLS_MTR_PROROCOL_ALL;
//可选参数。
request.extention = @{
@"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] mtr2:request callback:^(SLSResponse * _Nonnull response) {
NSLog(@"ping result: %@", response.content);
}];
Android SDK
MtrRequest request = new MtrRequest();
request.domain = "www.example.com";
//可选参数。
request.protocol = Protocol.ICMP;
request.context = "<your mtr context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
{
put("custom_key", "custom_value");
}
};
NetworkDiagnosis.getInstance().mtr(request, response -> {
SLSLog.d(TAG, String.format("mtr result: %s", response.content));
});
Unity
MtrRequest request = new MtrRequest();
request.domain = "www.example.com";
// 可选参数,设置探测上下文
request.context = "your mtr request context id";
// 可选参数,设置探测级extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");
// 可选参数,设置探测级回调函数
request.complete_callback = (response) =>
{
Debug.Log("mtr->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 发起探测
Unity4SLS.Mtr(request);
Windows SDK
//必选,初始化探测参数。
MtrDetectionConfig* mtrConfig = new MtrDetectionConfig("", "www.example.com", "ICMP", 1);
//可选,修改探测目标。
mtrConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
mtrConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
mtrConfig->setInterval(100);
//可选,修改探测超时时间。
mtrConfig->setTimeout(2000);
//可选,设置探测结束时的回调
mtrConfig->setCallback(demo_mtr_callback);
//发起探测。
mtrConfig->Detect();
//demo_mtr_callback 范例:
void demo_mtr_callback(void* context, char* json_result) {
std::string* ctx = static_cast<std::string*>(context);
printf("[探测结果回调 demo-mtr-callback] %s, context : %s\n", json_result, ctx->c_str());
}
DNS
iOS SDK
SLSDnsRequest *request = [[SLSDnsRequest alloc] init];
request.domain = @"www.example.com";
//可选参数。
request.context = @"<your dns context id>";
//可选参数。
request.extention = @{
@"custom_key": @"custom_value_ios"
};
[[SLSNetworkDiagnosis sharedInstance] dns2:request callback:^(SLSResponse * _Nonnull response) {
NSLog(@"ping result: %@", response.content);
}];
Android SDK
DnsRequest request = new DnsRequest();
request.domain = "www.example.com";
//可选参数。
request.context = "<your dns context id>";
//可选参数,设置当次网络探测的扩展业务参数。
request.extension = new HashMap<String, String>() {
{
put("custom_key", "custom_value");
}
};
NetworkDiagnosis.getInstance().dns(request, response -> {
SLSLog.d(TAG, String.format("dns result: %s", response.content));
});
Unity
DnsRequest request = new DnsRequest();
request.domain = "www.example.com";
// 可选参数,设置探测上下文
request.context = "your dns request context id";
// 可选参数,设置探测级extension
request.extension = new Dictionary<string, string>();
request.extension.Add("key1", "value1");
request.extension.Add("key2", "value2");
// 可选参数,设置探测级回调函数
request.complete_callback = (response) =>
{
Debug.Log("dns->completeCallback. type: " + response.type + ", context: " + response.context + ", content: " + response.content + ", error: " + response.error);
};
// 发起探测
Unity4SLS.Dns(request);
Windows SDK
//必选,初始化探测参数。
DnsDetectionConfig* dnsConfig = new DnsDetectionConfig("", "www.example.com", 2000, 0, "223.5.5.5", "A");
//可选,修改探测目标。
dnsConfig->setTarget("www.example.com");
//可选,修改探测任务ID。
dnsConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔,单位:ms。
dnsConfig->setInterval(100);
//可选,修改探测超时时间。
dnsConfig->setTimeout(2000);
//可选,修改DNS服务器。
dnsConfig->setServers("30.30.XX.XX");
//可选,修改DNS解析选项。
dnsConfig->setType(1);
//可选,设置探测结束时的回调
dnsConfig->setCallback(demo_dns_callback);
//发起探测。
dnsConfig->Detect();
//demo_mtr_callback 范例:
void demo_dns_callback(void* context, char* json_result) {
std::string* ctx = static_cast<std::string*>(context);
printf("[探测结果回调 demo-dns-callback] %s, context : %s\n", json_result, ctx->c_str());
}
UDP
Windows SDK
//必选,初始化探测参数,"7564"为UDP报文负载,为十六进制字符串(Hex String)格式,
UdpConfig* udpConfig = new UdpConfig("0", "www.example.com", 0, 4000, "7564");
//可选,修改探测目的
udpConfig->setTarget("www.example.com");
//可选,修改探测任务id
udpConfig->setTraceId("fdadf-daa-dadadad-okokok23");
//可选,修改探测时间间隔(ms)
udpConfig->setInterval(100);
//可选,修改探测超时时间
udpConfig->setTimeout(2000);
//可选,设置探测结束时的回调
udpConfig->setCallback(demo_udp_callback);
//发起探测。
udpConfig->Detect();
//demo_udp_callback 范例:
void demo_udp_callback(void* context, char* json_result) {
std::string* ctx = static_cast<std::string*>(context);
printf("[探测结果回调 demo-udp-callback] %s, context : %s\n", json_result, ctx->c_str());
}
设置用户标签
用户将被打上标签,若其标签与控制台配置的探测组标签存在交集,则相应的探测组规则将会生效。
设置标签接口可以在任意时刻调用,每次调用会覆盖原先的设置。
iOS SDK
// 给用户打上两个标签,分别是 "tag_vip", "tag_japan_normal"
NSArray *tags = [[NSArray alloc] initWithObjects:@"tag_vip", @"tag_japan_normal", nil];
[AliNetworkDiagnosis setUserTags:tags];
Android SDK
// 给用户打上两个标签,分别是 "tag_vip", "tag_japan_normal"
String[] tags = {"tag_vip","tag_japan_normal"};
Diagnosis.setUserTags(tags);
更新扩展业务字段
SDK支持在任何时机更新扩展业务字段。更新后的扩展业务字段仅对新产生的探测数据生效。
例如,应用初始化的时候可能未获取到用户ID,可以在用户登录成功后通过此接口更新,传入的key需设置为userId
。
iOS SDK
[[SLSNetworkDiagnosis sharedInstance] updateExtensions:@{
@"key1": @"value1",
@"key2": @"value2"
}];
Android SDK
NetworkDiagnosis.getInstance().updateExtensions(new HashMap<String, String>(){
{
put("key1", "value1");
put("key2", "value2");
}
});
Unity
Dictionary<string, string> extensions = new Dictionary<string, string>();
extensions.Add("key_from_unity", "value_from_unity");
Unity4SLS.UpdateExtensions(extensions);
Windows SDK
//获取配置类。
AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();
//自定义Extension信息。
std::map<std::string, std::string> mp;
mp.insert(make_pair("key1", "value1"));
mp.insert(make_pair("key2", "value2"));
mp.insert(make_pair("key3", "value3"));
//更新扩展信息。
config.updateExtension(mp);
配置策略下发域名
一般情况下无需调用此接口,仅当不希望直连阿里云IP地址时,通过这个接口可以套一层域名。
如果要使用该功能,需在SDK初始化之前完成设置。
iOS SDK
[[SLSNetworkDiagnosis sharedInstance] setPolicyDomain:@"your custom domain"];
Android SDK
NetworkDiagnosis.getInstance().setPolicyDomain("your custom domain");
Unity
Unity4SLS.SetPolicyDomain("your custom domain");
Windows SDK
config.setPolicyDomain("yourpolicydomain");
配置证书校验全局回调
当时HTTP探测,且为控制台下发的策略触发的探测时,支持通过全局回调函数来获取凭证。
iOS SDK
//注册HTTP探测证书校验回调。
[[SLSNetworkDiagnosis sharedInstance] registerHttpCredentialDelegate:^NSURLCredential * _Nullable(NSString * _Nonnull url) {
return [self getHttpCredential:url];
}];
//处理证书校验。
-(NSURLCredential*) getHttpCredential:(NSString*)url {
if (![url containsString:@"demo.ne.aliyuncs.com"]) {
return nil;
}
NSString *p12WithBase64 = @"your p12 infomation";
NSData *p12Data = [[NSData alloc] initWithBase64EncodedString:p12WithBase64 options:0];
CFDataRef inPKCS12Data = (__bridge CFDataRef)p12Data;
SecIdentityRef identity = NULL;
NSString *pass = @"123";
OSStatus status = [self extractIdentity:inPKCS12Data identity:&identity pass:pass];
if(status != 0 || identity == NULL) {
return nil;
}
SecCertificateRef certificate = NULL;
SecIdentityCopyCertificate (identity, &certificate);
const void *certs[] = {certificate};
CFArrayRef arrayOfCerts = CFArrayCreate(kCFAllocatorDefault, certs, 1, NULL);
//NSURLCredentialPersistenceForSession:创建URL证书,在会话期间有效。
NSURLCredential *credential = [NSURLCredential credentialWithIdentity:identity certificates:(__bridge NSArray*)arrayOfCerts persistence:NSURLCredentialPersistenceForSession];
if(certificate) {
CFRelease(certificate);
}
if (arrayOfCerts) {
CFRelease(arrayOfCerts);
}
if (credential) {
return [credential copy];
}
return nil;
}
Android SDK
//注册HTTP探测证书校验回调。
final HttpCredential credential = new HttpCredential(getSSLContext(context), null);
NetworkDiagnosis.getInstance().registerHttpCredentialCallback((url, context) -> credential);
//处理证书校验。
@RequiresApi(api = VERSION_CODES.O)
private SSLContext getSSLContext(Context context) {
try {
//服务器端需要验证的客户端证书。
String KEY_STORE_TYPE_P12 = "PKCS12";
KeyStore keyStore = KeyStore.getInstance(KEY_STORE_TYPE_P12);
String p12Str = "your p12 infomation";
byte[] p12Data = Base64.getDecoder().decode(p12Str);
InputStream ksIn = new ByteArrayInputStream(p12Data);
try {
keyStore.load(ksIn, "your password".toCharArray());
} catch (Exception e) {
Log.e("Exception", e.getMessage(), e);
} finally {
try {
ksIn.close();
} catch (Exception ignore) {
}
}
SSLContext sslContext = SSLContext.getInstance("TLS");
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(
TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null);
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("X509");
keyManagerFactory.init(keyStore, "your password".toCharArray());
sslContext.init(keyManagerFactory.getKeyManagers(), trustManagerFactory.getTrustManagers(), null);
return sslContext;
} catch (Exception e) {
Log.e("tag", e.getMessage(), e);
}
return null;
}
去初始化
该接口用于关闭底层线程,并释放对动态库文件的持有。仅当您在当前进程不需要再使用SDK的功能时,可通过去初始化来合理地释放资源,避免底层线程对主线程的阻塞。
该接口在当前进程仅允许调用一次,调用后SDK提供的相关功能在当前进程不再可用,确保在适当的时间调用该接口,并根据需要进行适当的资源管理。
Windows SDK
void unInitSdk() {
std::cout << "end!" << std::endl;
AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig();
//去初始化SDK。
config.unInit();
}
隐私合规
通过SDK发起网络探测请求后,SDK会采集网络信息、App信息、设备信息等。这些信息中主要包含:
用户设备出口IP、设备私网IP
App版本号信息
系统类型及版本号信息
设备型号
为了保障您的App顺利通过监管机构的合规检测,SDK提供了合规使用方案。
确保您的App有《隐私政策》,并且在用户首次启动App时弹出《隐私政策》取得用户同意。
务必告知用户您选择使用日志服务(SLS)SDK,请在《隐私政策》增加如下参考条款:
使用SDK名称:日志服务(SLS)SDK。
服务类型:网络质量数据分析。
手机个人信息类型:设备出口IP、私网 IP,App版本号信息,系统类型及版本号信息,设备型号信息等。
隐私权政策链接:日志服务(SLS)SDK隐私权政策。
务必做SDK延迟初始化配置,确保用户同意《隐私政策》之后,再初始化SDK。
为保证您在集成SDK之后,能够满足工信部相关合规要求,您应确保在App安装后首次冷启动时按照如下方式进行SDK的初始化。
在合适的位置调用预初始化函数(可参考上文SDK接入章节)。预初始化函数不会采集设备信息。
iOS SDK
// 预初始化,功能可正常使用,但敏感信息不会采集 [[SLSCocoa sharedInstance] preInit:credentials configuration:configuration];
Android SDK
// 预初始化,功能可正常使用,但敏感信息不会采集 SLSAndroid.preInit(this, credentials, optionConfiguration);
Windows SDK
void demoPreInit(){ //开始初始化。 printf("start preInit sdk\n"); AliNetworkDiagConfig& config = AliNetworkDiagConfig::getNetworkDiagConfig(); //设置其他参数... //预初始化SDK,功能可正常使用,但敏感信息不会采集 config.preInit(); //初始化完成。 printf("end preInit sdk\n"); }
确保App首次冷启动时,在用户阅读您的《隐私政策》 并取得用户授权之后,才调用正式初始化函数。正式初始化函数调用后,SDK会采集设备IP、设备型号等相关信息。如果用户不同意《隐私政策》授权,则不能调用正式初始化函数。
iOS SDK
[[SLSCocoa sharedInstance] initialize:credentials configuration:configuration];
Android SDK
SLSAndroid.initialize(context, credentials, optionConfiguration)