You need to enable JavaScript to run this app.
导航

iOS组件监控SDK接入

最近更新时间2023.09.13 14:29:46

首次发布时间2022.04.29 16:02:51

应用性能监控全链路版的iOS SDK基本为无侵入式。本文介绍产品形态为SDK的详细的接入步骤。

注意

  • 目前iOS SDK仅限中国大陆应用使用(不包括港澳台地区)。
  • 组件监控能力并不完全对标APP监控能力,目前仅支持崩溃监控、自定义错误、事件埋点。
  • 调用SDK初始化接口不会采集用户信息,调用SDK启动接口会开始采集用户信息,请确保采集用户信息之前已经获得用户授权SDK隐私政策

Demo说明

APMPlus_iOS
Demo中提供了各功能模块的子库,子库和模块的对应关系如下表所示:

子库

说明

对应平台模块

开始支持版本

Crash

崩溃监控:捕获CPP Exception、Mach Exception、NSException Exception 和 Signal Exception

崩溃分析

2.8.1

WatchDog

卡死监控:监控主线程长时间卡住被系统 watchdog 给强杀的情况

崩溃分析

2.8.1

UserException

自定义错误,需要业务方手动打点

错误分析-自定义错误

2.8.1

EventMonitor

事件分析,记录自定义事件,需要手动埋点

事件分析

2.8.1

SessionTracker

PV/UV统计,接入后会自动上报数据

各模块异常率、异常用户比例等

2.8.1

BootingProtectLite

连续崩溃保护

-

2.10.0

APMLog

APM日志库,可以手动打点记录SDK运行日志

单点追查-回捞
崩溃分析-崩溃详情-自定义日志

3.5.3

CloudCommand

回捞

单点追查-回捞

3.5.3

步骤一:获取SDK包

接入组件视角的监控能力,有两种方式:宿主直接依赖和组件依赖。

  • 宿主直接依赖
    1. 在宿主Podfile中添加如下代码。

      source 'https://github.com/volcengine/volcengine-specs.git'
      
        pod 'RangersAPM', '3.6.4', :subspecs => [
            'Crash',
            'WatchDog',
            'UserException',
            'EventMonitor',
            'SessionTracker',
            'CN'  #必须引入
        ]
      
    2. 执行pod install或者pod update,安装SDK。

  • 组件依赖
    1. 在组件的podspec中添加如下代码。

      Pod::Spec.new do |s|
        s.name             = 'xxx'
        s.version          = '0.0.1'
        s.summary          = 'xxx'
        s.source_files = 'Classes/**/*'
        ...
        s.dependency 'RangersAPM/Crash', '3.3.2'
        s.dependency 'RangersAPM/WatchDog', '3.3.2'
        s.dependency 'RangersAPM/UserException', '3.3.2'
        s.dependency 'RangersAPM/EventMonitor', '3.3.2'
        s.dependency 'RangersAPM/SessionTracker', '3.3.2'
        s.dependency 'RangersAPM/CN', '3.3.2'
      end
      
    2. 按需引入子库,具体请参见Demo说明

步骤二:初始化

在组件的初始化代码中(或者在用户同意隐私政策之后的合适时机)添加如下代码。
{{sdk_id}}{{app_token}}须替换为您创建的应用对应的AppID和AppToken,具体请参见如何查询AppID和AppToken?

#import <RangersAPMForSDK.h>

- (void)init {
    RangersAPMForSDKConfig *sdkConfig = [RangersAPMForSDKConfig configWithSDKID:@"{{sdk_id}}" appToken:@"{{app_token}}"];
    sdkConfig.channel = @"Cocoapods";   //SDK发布渠道,非必填
    sdkConfig.hostAppID = @"host_app_id"; //宿主APP标识,非必填
    sdkConfig.sdkVersion = @"1.0.0";   //SDK版本,必填
}

步骤三:启动SDK,开启数据采集

在组件的初始化代码中(或者在用户同意隐私政策之后的合适时机)添加如下代码,sdkConfig为初始化时生成的配置。

#import <RangersAPMForSDK.h>

- (void)start {
    RangersAPMForSDK *sdkMonitor = [[RangersAPMForSDK alloc] initWithConfig:sdkConfig];
}

说明

建议启动代码调用时机应尽量靠前,上述代码调用之前发生的崩溃等数据无法捕获。

步骤四:上传符号表

注意

组件监控的崩溃日志需要上传了符号表才能解析。如果您的SDK是静态库,符号表是接入宿主APP后,宿主APP打包产生的符号表。

手动上传

  1. 请确保您的符号表满足如下格式。
    图片

  2. 把符号表压缩为zip文件。
    Mac下zip需要执行以下命令,去除默认生成DS_Store \__MACOSX文件。

    zip -r test.app.dSYM.zip test.app.dSYM -x "*.DS_Store" -x "__MACOSX"
    

    test.app.dSYM.ziptest.app.dSYM替换为您的符号表名称。

  3. 上传符号表。

    • 符号表管理模块上传符号表。

    • 使用curl命令上传。

      curl https://console.volcengine.com/apmplus_api/eue/guest/app/mapping/upload -F "file=@dSYMZipName" -F "type=Dwarf" -F "os=iOS" -F "aid=APMPlusID" -H "Content-Type: multipart/form-data" -w %{http_code}
      
      • 注意需要将命令参数值用 ' " ' 包起来,否则参数中的空格可能导致命令解析错误。
      • 将上述命令中的dSYMZipName替换为您的符号表文件路径,APMPlusID替换为您的AppID。
        执行完成后,返回如下即说明上传成功。
        图片

自动上传

在Xcode中对应Target下配置Build Phases、添加Run Script,可以实现APP打包时自动上传符号表。

说明

默认Debug模式和模拟器编译不会上传符号表。如果需要在这两种情况下上传符号表,请参见手动上传

  1. 选择Build Settings > Debug Infomation Format下,检查工程配置是生成符号表。
    图片
  2. 选择Build Phases > New Run Script Phase,添加Run Script。
    图片
  3. 将添加的Run Script置于最后,避免脚本执行时符号表还没有生成。
    图片
  4. 修改脚本内容。
    • 如果您接入的SDK版本大于1.5.0(包含),仅需要在脚本中添加如下代码 ,并将命令中的APMPlusID替换为您的应用ID即可,这种方式在Debug模式和模拟器编译时不会上传符号表。

      /bin/sh ${PODS_ROOT}/RangersAPM/RangersAPM/APMPlus_DSYMUploader.sh "APMPlusID"
      

      图片

    • 如果您接入的SDK为较低版本且不想升级为更高版本,或者需要Debug模式和模拟器编译才能自动上传符号表。

      1. 下载脚本文件。
        APMPlus_DSYMUploaderV2.0.sh
        未知大小
      2. 将下载的脚本文件内容复制到Run Script中,并修改APMPlus_APP_ID为您的应用ID。
      3. 根据需要,修改脚本中的UPLOAD_DEBUG_SYMBOLSUPLOAD_SIMULATOR_SYMBOLS字段。
        图片

步骤五:验证数据上报

您可以根据需要,按照以下各模块说明,检查对应模块是否接入成功。

debug日志说明

前提条件
在SDK启动方法之前配置以下代码,否则一些同步事件可能无法输出日志。

#if DEBUG
 [RangersAPM allowDebugLogUsingLogger:^(NSString * _Nonnull log) {
     NSLog(@"APMPlus : %@", log);
 }];
 #endif

 RangersAPMForSDK *sdkMonitor = [[RangersAPMForSDK alloc] initWithConfig:sdkConfig];

开启Debug日志
开启Debug输出功能后,SDK在关键事件发生(初始化成功,上报成功等)时会向Xcode控制台输出日志,帮助您对SDK的接入和上报进行验证。
示例代码:

#import <RangersAPM+DebugLog.h>

[RangersAPM allowDebugLogUsingLogger:^(NSString * _Nonnull log) {
    NSLog(@"APMPlus : %@", log);
}];

支持通过修改block自定义日志输出格式。
如果传入nil,SDK会使用内部默认的格式输出日志:

[RangersAPM allowDebugLogUsingLogger:nil];

测试用例说明

通过测试用例可以验证SDK功能是否已正确开启,您可以在代码中添加测试用例。
如果您不了解如何添加测试用例,可以下载Example工程,或者参考下面各模块给出的样例代码。

通用

debug日志

日志内容

说明

Setup APMPlus - version :

SDK 初始化开始,准备启动各功能模块,同时输出当前版本

崩溃分析

完整的崩溃分析功能需要引入如下子库:Crash、WatchDog,支持单独引入各个子库。

获取组件的地址区间

监控组件内部发生的崩溃,首先需要获取组件的地址区间,我们提供三种方案。
方案1:添加标记函数
这种方案接入方式简单,不需要宿主APP做额外配置,但是对组件有一定的侵入性,且二进制重排后地址区间的准确性无法保证。

  1. 在组件中添加如下两个源文件,并定义两个函数,把一个函数的地址作为组件的起始地址,另一个函数的地址作为组件的结束地址。

    注意

    不要直接用示例的文件名和函数名,需要添加前缀,避免冲突。

    //SDKBegin.c
    #include "SDKBegin.h"
    extern void * SDKBeginAddress(void) {
        return &SDKBeginAddress;
    }
    
    //SDKEnd.c
    #include "SDKEnd.h"
    extern void * SDKEndAddress(void) {
        return &SDKEndAddress;
    }
    
  2. 在Xcode Build Phases - Compile Sources里面调整编译顺序。
    如下所示,SDKBegin.c为第一个编译,SDKEnd.c为最后一个编译。
    图片

    • 也可以把标识SDK符号起始的文件,添加AAA前缀,把标识SDK符号结束的文件,添加ZZZ前缀。
    • 对于有多个subspecs的SDK,可以添加两个subspecs,一个为AAA***,一个为ZZZ***,让其他的subspec都依赖这两个subspec,这样不管用户引入的是哪些subspecs,都可以正确获取SDK地址区间。
  3. 在RangersAPM SDK初始化时配置config的addressConfig参数,addressConfig支持传入多个地址区间,监控多段地址。

    #import <RangersAPMForSDK.h>
    
    extern void * SDKBeginAddress;
    extern void * SDKEndAddress;
    
    -(void)init {
        NSArray * addressRanges = @[[RangersAddressRange addressRangeWithStartAddress:(int64_t)&SDKBeginAddress endAddress:(int64_t)&SDKEndAddress]];
        RangersAPMAddressConfig * addressConfig = [RangersAPMAddressConfig configWithAddressRanges:addressRanges];
        RangersAPMForSDKConfig *sdkConfig = [RangersAPMForSDKConfig configWithSDKID:@"{{app_id}}" appToken:@"{{app_token}}"];
        sdkConfig.addressConfig = addressConfig;
        sdkConfig.channel = @"Cocoapods";
        sdkConfig.hostAppID = @"host_app_id"; //宿主APP标识
        sdkConfig.sdkVersion = @"1.0.0";
    }
    

方案2:添加编译脚本
这种方案不需要在RangersAPM SDK初始化时做其他的配置,准确度比方案1更高,但是需要宿主配合在Xcode中添加脚本。

注意

添加的脚本是在宿主的Project中添加,而不是在组件的Project中。

  1. 下载脚本。

    APMPlus_AddressRange.sh
    未知大小

  2. 修改脚本内容。

    SDKAid="123456"
    SDKName="RangersAPM"
    writeAddressRangeFile $SDKName $SDKAid
    

    参数说明:

    参数

    说明

    SDKAid

    • 不可为空。
    • APMPlus平台上面申请的AppID。

    SDKName

    • 不可为空。
    • 如果SDK是通过Cocoapods引入的,则填写Pod名称。
    • 如果SDK是通过下载获取的,则填写SDK包最外层的文件夹名称。

    同时监控多个SDK时,需要注意:

    • 如果这些SDK需要汇总到一个看板,即数据上报到APMPlus同一个AppID下面,则需要修改SDKName,并使用'|'把这些SDK name分隔开,即SDKName="SDK1|SDK2|SDK3"。

      SDKAid="123456"
      SDKName="RangersAPM|RangersAppLog"
      writeAddressRangeFile $SDKName $SDKAid
      
    • 如果这些SDK是相对独立的,即数据上报到各自的AppID下面,此时会有多个AppID,对每一个SDK进行上述调用。

      SDKAid1="123456"
      SDKName1="RangersAPM"
      writeAddressRangeFile $SDKName1 $SDKAid1
      
      SDKAid2="4567890"
      SDKName2="RangersAppLog"
      writeAddressRangeFile $SDKName2 $SDKAid2
      
  3. 在Xcode - Build Settings中把Write Link Map File置为YES,允许生成Link Map文件。
    图片
    由于脚本执行有一定耗时,为了避免影响开发体验,建议仅在Release环境下修改Write Link Map File为YES。

  4. 把修改后的脚本粘贴到Run Script里面,完成脚本接入工作。
    图片
    添加的Run Script需要位于Copy Pods Resources之前,Compile Sources之后。您可以通过拖动来移动Run Script的位置。
    图片

方案3:配置库名(仅适用于动态库)
在初始化应用性能监控全链路版SDK时,配置RangersAPMForSDKConfig的libNames属性,传入您的SDK包名。

#import <RangersAPMForSDK.h>

-(void)init {
    RangersAPMForSDKConfig *sdkConfig = [RangersAPMForSDKConfig configWithSDKID:@"{{app_id}}" appToken:@"{{app_token}}"];
    sdkConfig.libNames = @[@"SDK1", @"SDK2"];
    sdkConfig.channel = @"Cocoapods";
    sdkConfig.hostAppID = @"host_app_id"; //宿主APP标识
    sdkConfig.sdkVersion = @"1.0.0";
}

测试用例

下面的代码会触发NSException类型的Crash,更多类型的case,可以下载Example工程。

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    NSArray *array = [NSArray array];
    [array objectAtIndex:10];
});
  1. 将上述代码嵌入您的APP代码中。
  2. 在Xcode中,修改Build Configuration为Release,然后通过Run把APP安装到模拟器或者真机。
  3. 在模拟器或者真机中打开APP,然后等待崩溃代码执行,APP闪退。

    注意

    不要直接通过Xcode Run启动APP,这样触发的崩溃无法捕获。

  4. 重新启动APP,SDK会立即上报上一次启动期间发生的崩溃。您可以通过Xcode Run启动APP,而且您可以在控制台看到上报成功的日志。

debug日志

日志内容

说明

Crash-Monitor start successfully!

崩溃监控模块启动成功

WatchDog-Monitor start successfully!

卡死监控模块启动成功

Crash log is uploaded successfully!

崩溃日志上报成功

Watchdog log is uploading...

开始上传卡死日志

自定义错误

自定义错误模块需要引入子库UserException,自定义错误为自埋点功能,需要手动调用接口来记录APP发生的错误,并上报到火山引擎应用性能监控全链路版平台,统一查看。

测试用例

下面的代码会记录一条自定义错误日志,SDK每记录5条日志会触发一次上报。网络错误日志可以通过发送一次会发生错误的网络请求来自动记录,可以参考Example工程。

#import <RangersAPMForSDK+UserException.h>
//获取之前初始化的实例,需要先参考 初始化 章节初始化一个实例
RangersAPMForSDK *sdkMonitor = [RangersAPMForSDK monitorWithSDKID:@"{{sdk_id}}"];

[sdkMonitor trackAllThreadsLogExceptionType:@"testUserException" skippedDepth:0 customParams:@{@"testCustomKey":@"testCustomValue"} filters:@{@"testFilterKey":@"testFilterValue"} callback:^(NSError * _Nullable error){
    NSLog(@"%@",error);
}];

debug日志

日志内容

说明

UserException-Monitor start successfully!

自定义错误监控模块启动成功

事件分析

事件分析模块是一个自埋点功能,需要您手动调用接口来进行事件的记录,使用该功能需要引入EventMonitor模块。

测试用例

可以通过如下代码记录一个事件,相关参数可以查看头文件介绍。

#import "RangersAPMForSDK+EventMonitor.h"

//获取之前初始化的实例,需要先参考 初始化 章节初始化一个实例
RangersAPMForSDK *sdkMonitor = [RangersAPMForSDK monitorWithSDKID:@"{{app_id}}"];

[sdkMonitor trackEvent:@"event_name1"
            metrics:@{@"metric1":@(0)}
            dimension:@{@"dimension1":@"test"}
            extraValue:@{@"extra1":@"extravalue"}];
  1. 只有在应用性能监控全链路版上创建过,且事件状态为开启或验证中,且客户端命中事件采样规则,才会记录并上报该事件。
  2. Metrics 参数只支持Key为NSString类型,Value为NSNumber类型的NSDictionary对象;dimension只支持Key和Value都为NSString类型的NSDictionary对象;同时两个参数均不支持嵌套结构。
  3. 事件记录后不会立即上报,客户端上报规则如下:APP启动之后触发一次上报,每经过120s触发一次上报,当APP状态切换到background时触发一次上报。

debug日志

日志内容

说明

Record an event-log successfully, name:

成功记录一条事件日志,并输出事件名称

日志回捞

日志回捞模块需要引入子库APMLog。通过使用SDK提供的接口进行打点,可以记录一些APP运行期间产生的日志。此模块是一种基于mmap的高效率的日志打点框架,日志压缩率高达25倍,结合云控可以做到线上用户日志的实时定向回捞,帮您高效率,精准的定位、解决问题。
日志不会全部上报,获取这些日志的方式如下:

  • 崩溃发生后自动上报崩溃发生前一段时间产生的日志。
    上报的日志在崩溃详情页的自定义日志里查看。
  • 通过下发云控命令获取指定设备/用户、指定时间内产生的日志。更多信息请参见回捞

测试用例

测试用例是通过在项目中添加样例代码并在合适的时机触发,来验证SDK能否捕获对应事件的日志。您可以参见各模块给出的样例代码和说明,或者参见Example工程
对于C/C++、Objective-C、Swift,APMPlus提供了三类日志打点的接口,每一类有四个接口,分别为Debug、Info、Warn、Error,代表日志严重程度的四个等级,可以在平台查看日志时进行筛选。

//无论使用哪类接口,首先都需要先调用如下接口开启Alog功能
//注意:仅在APP启动时调用一次即可
#import "RangersAPMForSDK+ALog.h"

RangersAPMForSDK *sdkMonitor = [[RangersAPMForSDK alloc] initWithConfig:sdkConfig];

[sdkMonitor setALogEnabled];  //启用Alog
[sdkMonitor enableConsoleLog];  //同时在控制台输出日志



//Objective-C 可以使用如下接口进行日志打点
#import "RangersAPMForSDK+ALog.h"

//第一个参数为初始化时使用的 SDKID
//第二个参数标识当前日志的业务、场景等信息;
//第三个参数为日志具体信息,可以使用format类型,如果使用format,需要继续传入对应的参数
 RANGERSAPM_FORSDK_ALOG_DEBUG(sdkConfig.sdkID, @"Business", @"version : %@", [self version]);  //Debug类日志
 RANGERSAPM_FORSDK_ALOG_INFO(sdkConfig.sdkID, @"Business", @"version : %@", [self version]);   // Info类日志
 RANGERSAPM_FORSDK_ALOG_WARN(sdkConfig.sdkID, @"Business", @"version : %@", [self version]);   //Warn类日志
 RANGERSAPM_FORSDK_ALOG_ERROR(sdkConfig.sdkID, @"Business", @"version : %@", [self version]);   //Error类日志
  
  
  
//C/C++ 可以使用如下接口进行日志打点
#import "RangersAPM_ForSDK_ALog.h"
 
//第一个参数为初始化时使用的 SDKID
//第二个参数标识当前日志的业务、场景等信息;
//第三个参数为日志具体信息,可以使用format类型,如果使用format,需要继续传入对应的参数
 RANGERSAPM_FORSDK_ALOG_DEBUG_C([sdkConfig.sdkID UTF8String], "Business", "version : %s", version());
 RANGERSAPM_FORSDK_ALOG_INFO_C([sdkConfig.sdkID UTF8String], "Business", "version : %s", version());
 RANGERSAPM_FORSDK_ALOG_WARN_C([sdkConfig.sdkID UTF8String], "Business", "version : %s", version());
 RANGERSAPM_FORSDK_ALOG_ERROR_C([sdkConfig.sdkID UTF8String], "Business", "version : %s", version());
 
 
 
//Swift 可以使用如下接口进行日志打点
#import "RangersAPMForSDK+ALog.h"

//第一个参数为日志具体信息
//tag 标识当前日志的业务、场景等信息;
//fileName 为当前所在文件名,可以参考示例传入 #file
//funcName 为当前所在方法名,可以参考示例传入 #function
//line 为当前所在文件的行号,可以参考示例传入 #line
sdkMonitor.debugALog("alogtest", tag: "Business", fileName: #file, funcName: #function, line: #line)
sdkMonitor.infoALog("alogtest", tag: "Business", fileName: #file, funcName: #function, line: #line)
sdkMonitor.warnALog("alogtest", tag: "Business", fileName: #file, funcName: #function, line: #line)
sdkMonitor.errorALog("alogtest", tag: "Business", fileName: #file, funcName: #function, line: #line)

日志说明

完成开启Debug日志后,根据输出日志验证模块是否接入成功。

日志内容

说明

ALog is uploaded successfully!

(回捞)自定义日志上报成功

Upload ALog failed, reason :

(回捞)自定义日志上报失败,并输出原因

ALog is uploaded manually!

手动上报自定义日志成功

Manually upload ALog failed

手动上报自定义日志失败

CloudCommand start successfully!

回捞功能启动成功

CloudCommand is being executed ...

回捞指令正在执行

ALog start successfully!

自定义日志功能启动成功

(可选)步骤六:接入其他功能

除了崩溃分析、错误分析、卡死分析等常用的功能外,SDK还支持一些增强功能。您可以根据业务需求,引入相应子库后使用这些功能。

自定义数据

使用如下接口,您可以添加一些自定义的环境或业务信息,如用户email、定位信息、业务场景等,这些信息会随着SDK的日志一同上报,帮助您排查一些问题,您可以在日志详情页查看这些信息。

#import <RangersAPMForSDK.h>

//获取之前初始化的实例,需要先参考 初始化 章节初始化一个实例
RangersAPMForSDK *sdkMonitor = [RangersAPMForSDK monitorWithSDKID:@"{{app_id}}"];

//自定义key-value
[sdkMonitor setCustomContextValue:@"sdk1context1value" forKey:@"sdk1context1key"];

图片

自定义维度

除了上报自定义数据外,您也可以在需要的时候添加一些自定义维度,作为自定义的的筛选项,用来筛选某些特定情况下的日志。

#import <RangersAPMForSDK.h>

//获取之前初始化的实例,需要先参考 初始化 章节初始化一个实例
RangersAPMForSDK *sdkMonitor = [RangersAPMForSDK monitorWithSDKID:@"{{app_id}}"];

//自定义筛选项
[sdkMonitor setCustomFilterValue:@"sdk1filter1value" forKey:@"sdk1filter1key"];

连续崩溃保护

连续崩溃保护需要接入SDK的BootingProtectLite模块,具体请参见Demo说明。使用此功能,您可以在应用发生连续的崩溃时进行一些本地的处理,例如清理缓存、删除文件等。

#import <RangersAPMForSDK+BootingProtect.h>

    //获取之前初始化的实例,需要先参考 初始化 章节初始化一个实例
    RangersAPMForSDK *sdkMonitor = [RangersAPMForSDK monitorWithSDKID:@"{{app_id}}"];
    [sdkMonitor startProtectWithBootingThreshold:10 bootingCrashHandler:^(RangersAPMBootingInfo * _Nonnull info) {
        /**
        对连续异常的场景进行防护策略,这里的demo只输出了一些log,您可以在自己的应用中做一些本地缓存清理或其他策略。可以针对不同的异常发生次数制定不同的策略。
        */
        if (info.consecutiveExceptionTimes >= 1) {
            NSLog(@"⚠️Consecutive exception 1 time");
        } else if (info.consecutiveExceptionTimes >= 3) {
            NSAssert(NO, @"⚠️Consecutive exception 3 times !!!");
        }
        
        /**
         除了对连续异常进行防护,您也可以针对不同的异常类型执行不同的防护策略。
         */
        if (info.crashTimes >= 1) {
            NSLog(@"⚠️Consecutive crash 1 time");
        }
        if (info.watchdogTimes >= 1) {
            NSLog(@"⚠️Consecutive watchdog 1 time");
        }
    }];

获取设备数与用户数

  • 使用应用性能监控全链路版SDK自身服务
    应用性能监控全链路版SDK内部默认使用自身服务生成的deviceID用以标识一台设备和用户。
  • 使用自己的DeviceID

    说明

    如果您要使用自己的deviceID,则SDK内部不会再次请求自身服务生成deviceID。

    1. 配置应用性能监控全链路版SDK初始化config的deviceIDSource。
    2. 在应用性能监控全链路版SDK初始化方法之后,设置deviceID。
      #import <RangersAPMForSDK.h>
      
      - (void)init {
          
          RangersAPMForSDKConfig *sdkConfig = [RangersAPMForSDKConfig configWithSDKID:@"{{app_id}}" appToken:@"{{app_token}}"];
          sdkConfig.channel = @"Cocoapods";
          sdkConfig.hostAppID = @"host_app_id"; //宿主APP标识
          sdkConfig.sdkVersion = @"1.0.0";
          sdkConfig.deviceIDSource = RAPMDeviceIDSourceFromUser;
         
          RangersAPMForSDK *sdkMonitor = [[RangersAPMForSDK alloc] initWithConfig:sdkConfig];
          
          [sdkMonitor setDeviceID:@"MYDEVICEID"];
      }