iOS 使用 Metrickit 收集崩潰日志
Metrickit 是什么
MetricKit 是 蘋果在 iOS13系統(tǒng)開始引入的用來匯總和分析有關異常和崩潰診斷以及電源和性能指標的每個設備的報告。
為什么要用 MetricKit 收集崩潰日志
當前市面上的開源框架,如 KSCrash,PLCrashReport 等框架都有一些崩潰不能抓取;比如PLCrashReport 不能抓取棧溢出的崩潰,不能抓取SIGKILL, SIGQUIT等信號量的崩潰。KSCrash 對SIGKILL的崩潰抓取也只能抓取一部分
Metrickit 缺陷
- 目前只支持 iOS14 以后的崩潰日志收集
- 崩潰日志沒有返回具體的崩潰時間和啟動時間,崩潰場景信息除了堆棧外沒有其余信息
- 如果使用了段遷移編譯技術,主程序 macho 的地址和 uuid 無法匹配。
iOS14的崩潰日志是24小時會回調(diào)通知一次,時效性低;iOS15 之后,崩潰日志會在下次啟動之后就返回,但經(jīng)驗證,有的會立即回調(diào),有的則不然,規(guī)律不可琢磨
開始接入
1.添加 MetricKit
2.添加 MetricKit 監(jiān)聽者
if (@available(iOS 14.0, *)) {
MXMetricManager *manager = [MXMetricManager sharedManager];
if (self && manager && [manager respondsToSelector:@selector(addSubscriber:)]) {
[manager addSubscriber:self];
}
}
3. 監(jiān)聽者實現(xiàn) MXMetricManagerSubscriber 協(xié)議方法, payloadDic 里面包含著上次本應用發(fā)生的崩潰日志堆棧和信息
// 蘋果如果有數(shù)據(jù)數(shù)據(jù),注冊監(jiān)聽之后就會回調(diào)
- (void)didReceiveDiagnosticPayloads:(NSArray<MXDiagnosticPayload *> * _Nonnull)payloads API_AVAILABLE(ios(14.0)){
if (@available(iOS 14.0, *)) {
for (MXDiagnosticPayload *payload in payloads) {
NSDictionary *payloadDic = [payload dictionaryRepresentation];
});
}
}
}
4.日志組裝關鍵代碼示例
NSArray *callStackRootFrames = [dicFrame ArrayValueForKey:kMetrkitCallStackRootFramesKey];
if (callStackRootFrames.count <= 0) {
continue;
}
NSDictionary *dicZero = [callStackRootFrames ObjectAtIndex:0];
int rootIndex = 0;
while (dicZero && dicZero.count > 0) {
NSString *binaryUUID = [dicZero stringValueForKey:kMetrkitBinaryUUIDKey];
NSString *binaryName = [dicZero stringValueForKey:kMetrkitBinaryNameKey];
long long baseAdd = [[dicZero NumberValueForKey:kMetrkitOffsetIntoBinaryTextSegmentKey] longLongValue];
long long address = [[dicZero numberValueForKey:kMetrkitAddressKey] longLongValue];
NSArray *subFrames = [dicZero arrayValueForKey:kMetrkitSubFramesKey];
[strStack appendFormat:@"%d %@ 0x%llx 0x%llx + %lld\n", rootIndex, binaryName, baseAdd, address, address - model.baseAddress];
rootIndex++;
if (subFrames && subFrames.count >= 0) {
dicZero = [subFrames ObjectAtIndex:0];
} else {
dicZero = nil;
}
MetricKit 返回字段含義及詳情
JSON總格式
crashDiagnostics 詳情
每一個崩潰為一個字典,具體內(nèi)容為下
diagnosticMetaData 字典詳情
|terminationReason|String|崩潰原因| RBSTerminateContext domain:10 code:0x8BADF00D
explanation:scene-update watchdog transgression: application :6308
exhausted real (wall clock) time allowance of 10.00 seconds|
callStackTree 字典詳情
callStacks 數(shù)組詳情
數(shù)組中元素為字典,詳情如下
callStackRootFrames 數(shù)組詳情
數(shù)組中元素為字典,詳情如下
diskWriteExceptionDiagnostics 詳情
每一個崩潰為一個字典,具體內(nèi)容為下
diagnosticMetaData 字典詳情
callStackTree 字典詳情
callStacks 數(shù)組詳情
數(shù)組中元素為字典,詳情如下
callStackRootFrames 數(shù)組詳情
數(shù)組中元素為字典,詳情如下
cpuExceptionDiagnostics 詳情
每一個崩潰為一個字典,具體內(nèi)容為下
diagnosticMetaData 字典詳情
callStackTree 字典詳情
callStacks 數(shù)組詳情
數(shù)組中元素為字典,詳情如下
callStackRootFrames 數(shù)組詳情
數(shù)組中元素為字典,詳情如下