除了崩溃分析、错误分析、卡顿分析等常用的功能外,SDK还支持一些增强功能。您可以根据业务需求,引入相应子库后使用这些功能。
某些事件发生时,SDK会发出通知,您可以监听这些通知,来做一些自定义的应对措施。
以卡顿场景为例,您可以通过如下方式注册通知,如果引入了LAG子库,在卡顿场景发生时,SDK会发出通知,从而触发lagHandler。
#import <RangersAPMNotifications.h> [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(lagHandler) name:APMLagTimeOutNotification object:nil];
说明
RangersAPMNotifications.h
。启动分析默认监控四个启动阶段:
各阶段时间节点说明:
时间节点 | 说明 |
---|---|
exec | APP进程启动的时间 |
load | RangersAPM的+load调用时间 |
didFinishLaunching | 初始化RangersAPM的时间 |
first_render_time | 第一次CoreAnimation提交的时间 |
vc_loadView | 第一个ViewController,loadView的时间 |
didAppear | 第一个ViewController,viewDidAppear的时间 |
如果需要额外记录启动过程的某些节点,请参考如下两种埋点方案。
注意
以下两个埋点方法,只能在App启动阶段进行埋点,APP启动完成后调用是无效的。
在节点开始和结束分别埋点
#import <RangersAPM+PerformanceAPI.h> RangersAPMConfig *config = [RangersAPMConfig configWithAppID:@"{{app_id}}" appToken:@"{{app_token}}"]; [RangersAPM startWithConfig:config]; [RangersAPM beginLaunchSpan:@"business" callback:^(NSError * _Nullable error) { if (error.code == RangersAPMStartDetectorErrorTypeDuplicateSpanName) { //do something } }]; //business [RangersAPM endLaunchSpan:@"business" callback:^(NSError * _Nullable error) { if (error.code == RangersAPMStartDetectorErrorTypeDuplicateSpanName) { //do something } }];
记录节点开始时间和结束时间,在节点结束时埋点
#import <RangersAPM+PerformanceAPI.h> RangersAPMConfig *config = [RangersAPMConfig configWithAppID:@"{{app_id}}" appToken:@"{{app_token}}"]; [RangersAPM startWithConfig:config]; NSTimeInterval startTime = [[NSDate date] timeIntervalSince1970] * 1000; //business NSTimeInterval endTime = [[NSDate date] timeIntervalSince1970] * 1000; [RangersAPM addSpan:@"business" startTimeMs:startTime endTimeMs:endTime callback:^(NSError * _Nullable error) { if (error.code == RangersAPMStartDetectorErrorTypeDuplicateSpanName) { //do something } }];
如果您想要自定义启动链路的终点,需要配置RangersAPMConfig的customFinishStartTrace
参数为YES
,并在SDK初始化之后,即[RangersAPM startWithConfig:]
之后,在一个合适的时机调用[RangersAPM finishLaunchTrace]
方法结束启动链路。
示例代码:
#import <RangersAPM.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RangersAPMConfig *apmConfig = [RangersAPMConfig configWithAppID:@"{{app_id}}" appToken:@"{{app_token}}"]; apmConfig.customFinishStartTrace = YES; apmConfig.channel = @"App Store"; [RangersAPM startWithConfig:apmConfig]; [RangersAPM finishLaunchTrace]; return YES; }
iOS 15以上的系统中存在Prewarm策略,使得应用的一部分启动流程提前,导致平台统计到的启动时间偏大。
对于这种情况,平台采取方案:如果触发了Prewarm,那么平台统计到的启动时长会进行校准,即忽略一部分启动时间,因此统计到的启动时间会略小于真实时间,且上报的启动Trace可能会缺少execToLoad或者loadToDidFinishLaunching时间。
如果您希望获取更加精准的启动时间,请把SDK升级到2.11.1或更高版本,并执行以下操作:在main方法中调用[RangersAPM prewarmCheckStart]
,同时在application:willFinishLaunchingWithOptions:
方法中调用[RangersAPM prewarmCheckEnd]
。如果您的main方法或者application:willFinishLaunchingWithOptions:
方法中包含复杂逻辑,则不建议此操作。
注意
该方法用于获取应用启动阶段关键点的时间戳,不涉及个人信息,如果需要在用户确认隐私弹窗之前调用此方法,请您结合自身应用的合规要求确认是否允许SDK在初始化之前执行代码逻辑。
我们建议在application:didFinishLaunchingWithOptions:
最开始启动 SDK,以获取较为准确的启动时间。如果由于特殊原因无法太早启动,请首先在application:didFinishLaunchingWithOptions:
调用[RangersAPM applicationDidFinishLaunching]
。
使用如下接口,您可以添加一些自定义环境或业务信息,如用户email、定位信息、业务场景等,这些信息会随着SDK的日志一起上报,帮助您排查一些问题。
[RangersAPM setCustomContextValue:@"customKeyDemoTest" forKey:@"customValueDemoTest"];
添加成功后,您可以在控制台日志详情页面查看这些自定义数据。
使用如下接口,您可以添加一些自定义维度,作为自定义的的筛选项,用来筛选某些特定情况下的日志。
[RangersAPM setCustomFilterValue:@"filterValueDemooTest" forKey:@"filterKeyDemoTest"];
添加成功后,您可以在筛选列表中的自定义维度下查看这些自定义维度。
注意
在没有日志详情,只有统计数据的模块,无法看到这些自定义数据和自定义维度,如流畅性、HTTP等。
无需额外嵌码,引入UITrackers子库,就可以在崩溃详情页面现场数据页签下查看页面追踪,查看崩溃发生前用户的页面访问路径。卡顿详情也同样支持页面追踪。
连续崩溃保护可以在应用发生连续的崩溃时进行一些本地的处理,例如清理缓存、删除文件等。连续崩溃保护需要接入SDK的BootingProtect模块。
#import <RangersAPM+BootingProtect.h> [RangersAPM 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"); } if (info.OOMTimes >= 1) { NSLog(@"⚠️Consecutive oom 1 time"); } }];
业务接入APMPlus服务端监控后,客户端进行如下配置,开启全链路监控。更多信息,请参见全链路监控。
//需要引入如下头文件 #import <RangersAPMConfig+NetworkPro.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RangersAPMConfig *apmConfig = [RangersAPMConfig configWithAppID:@"{{app_id}}" appToken:@"{{app_token}}"]; apmConfig.channel = @"App Store"; //配置 enableTracing 为 YES 以开启全链路监控功能 apmConfig.enableTracing = YES; [RangersAPM startWithConfig:apmConfig]; return YES; }
应用性能监控全链路版SDK内部默认使用自身服务生成的DeviceID来标识一台设备和用户。
如果您不想使用SDK自身服务生成的DeviceID,可以参考下文的其他方案。如果您选择使用其他方案,SDK内部就不会再次请求自身服务生成DeviceID。
如果您想要或者已经接入了RangersAppLog,请执行以下步骤获取设备数。
在Podfile中声明RangersAppLog依赖,RangersAppLog版本需要大于6.0.1。
pod 'RangersAppLog', '>=6.0.1', :subspecs => [ 'Core', 'Host/CN' ]
初始化RangersAppLog SDK。
#import <BDAutoTrack.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { BDAutoTrackConfig *config = [BDAutoTrackConfig configWithAppID:@"{{app_id}}" launchOptions:launchOptions]; config.channel = @"App Store"; [BDAutoTrack startTrackWithConfig:config]; //初始化APMPlus SDK return YES; }
配置SDK初始化config的deviceIDSource,应用性能监控全链路版会自动从RangersAppLog获取deviceID。
#import <RangersAPM.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //初始化RangersAppLog RangersAPMConfig *apmConfig = [RangersAPMConfig configWithAppID:@"{{app_id}}" appToken:@"{{app_token}}"]; apmConfig.channel = @"App Store"; apmConfig.deviceIDSource = RAPMDeviceIDSourceFromRAppLog; [RangersAPM startWithConfig:apmConfig]; return YES; }
如果您想使用自己的deviceID,请严格执行以下步骤获取设备数。
#import <RangersAPM.h> - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { RangersAPMConfig *apmConfig = [RangersAPMConfig configWithAppID:@"{{app_id}}" appToken:@"{{app_token}}"]; apmConfig.channel = @"App Store"; apmConfig.deviceIDSource = RAPMDeviceIDSourceFromUser; [RangersAPM startWithConfig:apmConfig]; [RangersAPM setDeviceID:@"MYDEVICEID"]; return YES; }
注册崩溃后回调,可以在异常发生时进行回调,记录异常发生时的关键信息。
// RangersAPM+CrashCallback.h /** RangersAPM 内部处理完 Crash 后,回调业务方,自定义数据,会在 APMInsight平台 自定义数据中展示 ⚠️⚠️⚠️ Warning ⚠️⚠️⚠️ ⚠️⚠️⚠️ Crash后App运行环境比较脆弱,容易造成二次Crash或死锁,除非非常必要,否则不建议使用该方法 ⚠️⚠️⚠️ 业务方收到回调时,表明App已发生Crash,运行在异常环境,所以存在使用限制,应该遵守下面约定: 1. 回调方法内部应该越简单越好,只用于记录关键信息,尽快结束 (Crash期间用户端表现为界面卡死状态) 2. 这时除了当前线程,其他线程都被挂起,所以不要开启其他线程 3. 不要调用OC方法,容易造成死锁 4. 尽量不要在堆上malloc分配内存 */ @interface RangersAPM (CrashCallback) + (void)registerCallback:(apm_crash_callback)callback; + (void)removeCallback:(apm_crash_callback)callback;
回捞自定义日志受限于用户行为,当收到用户反馈或者用户发生异常时,开发者可能无法及时获取到日志进行问题排查。
配置方法:
/** 手动上报用户主动打点产生的自定义日志 @param fetchStartTime 需要上报的自定义日志的起始时间 @param fetchEndTime 需要上报的自定义日志的结束时间 @param callback 上传状态回调,isSuccess == YES 代表上传成功,fileCount 表示本次上报文件个数 */ + (void)reportALogWithFetchStartTime:(NSTimeInterval)fetchStartTime fetchEndTime:(NSTimeInterval)fetchEndTime callback:(void(^)(BOOL isSuccess, NSInteger fileCount))callback;
查看日志:主动上报的这部分数据,可以在自定义日志页面,输入DID进行查询,事件类型选择主动上报。
注意
自定义日志主动上报的量级不可控,且事件量消耗较大,建议修改自定义文件 > 主动上报自定义日志采样率。详情请参见SDK上报配置。
考虑到成本和性能,APMPlus的一些功能的上报策略是采样上报,这样一来,当需要单点排查某个用户发生的问题时,由于没有全部的功能日志,会对问题的排查造成不便。为了解决这种问题,SDK支持把部分功能日志以自定义日志的形式写入,但不上报单独的功能日志,便于需要排查问题时进行回捞或者主动上报。
说明
如果希望同时上报用户自定义日志和APMPlus日志,logType参数可以这样传递:[RangersAPM reportALogOfType:(RangersAPMALogTypeCustom | RangersAPMALogTypeMonitor) ...]
配置方法:
typedef NS_OPTIONS(NSUInteger, RangersAPMALogType) { RangersAPMALogTypeCustom = 1<<0, //用户主动打点 RangersAPMALogTypeMonitor = 1<<1 //SDK 内置打点 }; /** 手动上报多类型自定义日志 @param logType 需要上报的日志类型,同时上报多种类型示例:RangersAPMALogTypeCustom | RangersAPMALogTypeMonitor @param fetchStartTime 需要上报的自定义日志的起始时间 @param fetchEndTime 需要上报的自定义日志的结束时间 @param callback 上传状态回调,isSuccess == YES 代表上传成功,fileCount 表示本次上报文件个数 */ + (void)reportALogOfType:(RangersAPMALogType)logType fetchStartTime:(NSTimeInterval)fetchStartTime fetchEndTime:(NSTimeInterval)fetchEndTime callback:(void(^)(BOOL isSuccess, NSInteger fileCount))callback;
查看日志:主动上报的这部分数据,可以在自定义日志页面,输入DID进行查询,事件类型选择主动上报。
在 5.1.2 版本以前,页面体验支持如下阶段:
当控制器的创建和展示分散时,就会造成数据异常,尤其是 methodsTotalTime 数据会异常巨大,对整体指标产生影响。
为了兼容这个问题,我们在 5.1.2 版本中,兼容如下逻辑:
同时,为了防止控制器的创建和展示分散的情况,对上述时间增加阈值限定。这个阈值对上述三个时间单独生效,哪个时间超过阈值,就会抛弃哪一个时间值。另外,调整 methodsTotalTime 的计算公式为上述字段值的总和。
说明
阈值的默认值为 20 秒,如果想修改的话,可以参考SDK上报配置。