Metrickit 是什么

MetricKit 是 苹果在 iOS13系统开始引入的用来汇总和分析有关异常和崩溃诊断以及电源和性能指标的每个设备的报告。

为什么要用 MetricKit 收集崩溃日志

当前市面上的开源框架,如 KSCrash,PLCrashReport 等框架都有一些崩溃不能抓取;比如PLCrashReport 不能抓取栈溢出的崩溃,不能抓取SIGKILL, SIGQUIT等信号量的崩溃。KSCrash 对SIGKILL的崩溃抓取也只能抓取一部分

Metrickit 缺陷

1.目前只支持 iOS14 以后的崩溃日志收集

2.崩溃日志没有返回具体的崩溃时间和启动时间,崩溃场景信息除了堆栈外没有其余信息

3.如果使用了段迁移编译技术,主程序 macho 的地址和 uuid 无法匹配。

iOS14的崩溃日志是24小时会回调通知一次,时效性低;iOS15 之后,崩溃日志会在下次启动之后就返回,但经验证,有的会立即回调,有的则不然,规律不可琢磨

开始接入

1.添加 MetricKit


2.添加 MetricKit 监听者

if (@available(iOS 14.0, *)) {

        MXMetricManager *manager = [MXMetricManager sharedManager];

        if (self && manager && [manager respondsToSelector:@selector(addSubscriber:)]) {

            [manager addSubscriber:self];

        }

    }

3. 监听者实现 MXMetricManagerSubscriber 协议方法, payloadDic 里面包含着上次本应用发生的崩溃日志堆栈和信息

// 苹果如果有数据数据,注册监听之后就会回调

- (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总格式

key

值类型

解释

demo值

crashDiagnostics

Array

记录的崩溃

见下面详情

hangDiagnostics

Array

记录的卡顿信息

见下面详情

cpuExceptionDiagnostics

Array

记录的cpu异常信息

见下面详情

diskWriteExceptionDiagnostics

Array

记录的磁盘写入异常信息

见下面详情

timeStampBegin

Date

记录事件开始间隔

2021-12-01 09:06:57 +0000

timeStampEnd

Date

记录事件结束间隔

2021-12-01 09:06:57 +0000

crashDiagnostics 详情

每一个崩溃为一个字典,具体内容为下

key

值类型

解释

demo值

version

String

Metrkit 框架版本

1.0.0

diagnosticMetaData

字典

崩溃的一些核心信息(含App信息)

见二级详情

callStackTree

字典

堆栈相关信息

见二级详情

diagnosticMetaData 字典详情

key

值类型

解释

demo值

appBuildVersion

String

build

12.29.0.1

appVersion

String

app 版本

12.29.0

regionFormat

String

区域代码

CN

exceptionType

String

异常类型

1

osVersion

String

iOS 操作系统

iPhone OS 15.1 (19B74)

deviceType

String

Model

iPhone13,1

bundleIdentifier

String

bundle

com.xxx.xxxxx

exceptionCode

String

exception Code

1

signal

String

信号量符号

11

platformArchitecture

String

cpu 架构

arm64e

virtualMemoryRegionInfo

String

虚拟内存信息

0x10 is not in any region. Bytes before following region: 433969560 REGION TYPE         START- END   [ VSIZE] PRT/MAX SHRMOD REGION DETAIL UNUSED SPACE AT START--->  __**TEXT          102aa8000-11012c000 [214.5M] r-x/r-x SM=COW ...p/xxxxx

|terminationReason|String|崩溃原因| RBSTerminateContext domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: application<com.xxx.xxxx> :6308 exhausted real (wall clock) time allowance of 10.00 seconds|

callStackTree 字典详情

key

值类型

解释

demo值

callStacks

Array

每个线程详细堆栈

见三级详情

callStackPerThread

BOOL

是否只收集单线程

见二级详情

callStacks 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

threadAttributed

BOOL

是否是崩溃线程

true

callStackRootFrames

Array

单线程堆栈详细信息

见下一级级详情

callStackRootFrames 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

binaryUUID

String

uuid

DC6B1885-FB91-34C4-A9FC-A539C17A08A7

offsetIntoBinaryTextSegment

int

基于二进制macho的偏移,十进制

4339695616

sampleCount

int

未知

1

binaryName

String

二进制macho的名称

xxx

address

int

二进制macho的基址

4446737180

subFrames

Array

诱发此次崩溃的上一级线程

有可能循环递归callStackRootFrames内容

diskWriteExceptionDiagnostics 详情

每一个崩溃为一个字典,具体内容为下

key

值类型

解释

demo值

version

String

Metrkit 框架版本

1.0.0

diagnosticMetaData

字典

崩溃的一些核心信息(含App信息)

见二级详情

callStackTree

字典

堆栈相关信息

见二级详情

diagnosticMetaData 字典详情

key

值类型

解释

demo值

appBuildVersion

String

build

12.29.0.1

appVersion

String

app 版本

12.29.0

regionFormat

String

区域代码

CN

osVersion

String

iOS 操作系统

iPhone OS 15.1 (19B74)

deviceType

String

Model

iPhone13,1

bundleIdentifier

String

bundle

com.xxx

writesCaused

String

写原因

2,000字节

platformArchitecture

String

cpu 架构

arm64e

callStackTree 字典详情

key

值类型

解释

demo值

callStacks

Array

每个线程详细堆栈

见三级详情

callStackPerThread

BOOL

是否只收集单线程

见二级详情

callStacks 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

threadAttributed

BOOL

是否是触发线程

true

callStackRootFrames

Array

单线程堆栈详细信息

见下一级级详情

callStackRootFrames 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

binaryUUID

String

uuid

DC6B1885-FB91-34C4-A9FC-A539C17A08A7

offsetIntoBinaryTextSegment

int

基于二进制macho的偏移,十进制

4339695616

sampleCount

int

未知

1

binaryName

String

二进制macho的名称

xxxxx

address

int

二进制macho的基址

4446737180

subFrames

Array

诱发此次崩溃的上一级线程

有可能循环递归callStackRootFrames内容

cpuExceptionDiagnostics 详情

每一个崩溃为一个字典,具体内容为下

key

值类型

解释

demo值

version

String

Metrkit 框架版本

1.0.0

diagnosticMetaData

字典

崩溃的一些核心信息(含App信息)

见二级详情

callStackTree

字典

堆栈相关信息

见二级详情

diagnosticMetaData 字典详情

key

值类型

解释

demo值

appBuildVersion

String

build

12.29.0.1

appVersion

String

app 版本

12.29.0

regionFormat

String

区域代码

CN

osVersion

String

iOS 操作系统

iPhone OS 15.1 (19B74)

deviceType

String

Model

iPhone13,1

bundleIdentifier

String

bundle

com.xxx

totalCPUTime

String

cpu时间

20s

totalSampledTime

String

CPU总采样时间

20s

platformArchitecture

String

cpu 架构

arm64e

callStackTree 字典详情

key

值类型

解释

demo值

callStacks

Array

每个线程详细堆栈

见三级详情

callStackPerThread

BOOL

是否只收集单线程

见二级详情

callStacks 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

threadAttributed

BOOL

是否是触发线程

true

callStackRootFrames

Array

单线程堆栈详细信息

见下一级级详情

callStackRootFrames 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

binaryUUID

String

uuid

DC6B1885-FB91-34C4-A9FC-A539C17A08A7

offsetIntoBinaryTextSegment

int

基于二进制macho的偏移,十进制

4339695616

sampleCount

int

未知

1

binaryName

String

二进制macho的名称

xxxxx

address

int

二进制macho的基址

4446737180

subFrames

Array

诱发此次崩溃的上一级线程

有可能循环递归callStackRootFrames内容

hangDiagnostics 详情

每一个崩溃为一个字典,具体内容为下

key

值类型

解释

demo值

version

String

Metrkit 框架版本

1.0.0

diagnosticMetaData

字典

崩溃的一些核心信息(含App信息)

见二级详情

callStackTree

字典

堆栈相关信息

见二级详情

diagnosticMetaData 字典详情

key

值类型

解释

demo值

appBuildVersion

String

build

12.29.0.1

appVersion

String

app 版本

12.29.0

regionFormat

String

区域代码

CN

osVersion

String

iOS 操作系统

iPhone OS 15.1 (19B74)

deviceType

String

Model

iPhone13,1

bundleIdentifier

String

bundle

com.xxx

hangDuration

String

卡顿时间

20s

platformArchitecture

String

cpu 架构

arm64e

callStackTree 字典详情

key

值类型

解释

demo值

callStacks

Array

每个线程详细堆栈

见三级详情

callStackPerThread

BOOL

是否只收集单线程

见二级详情

callStacks 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

threadAttributed

BOOL

是否是触发线程

true

callStackRootFrames

Array

单线程堆栈详细信息

见下一级级详情

callStackRootFrames 数组详情

数组中元素为字典,详情如下

key

值类型

解释

demo值

binaryUUID

String

uuid

DC6B1885-FB91-34C4-A9FC-A539C17A08A7

offsetIntoBinaryTextSegment

int

基于二进制macho的偏移,十进制

4339695616

sampleCount

int

未知

1

binaryName

String

二进制macho的名称

xxxxx

address

int

二进制macho的基址

4446737180

subFrames

Array

诱发此次崩溃的上一级线程

有可能循环递归callStackRootFrames内容

-End-