docs: APM 监控部分

This commit is contained in:
杭城小刘
2020-04-06 22:35:27 +08:00
parent fb73c0acf4
commit 32d90b27fc
34 changed files with 2702 additions and 126 deletions

View File

@@ -5,12 +5,90 @@
`NS_BLOCK_ASSERTIONS ` 表明在 Release 状态下过滤 NSAssert只需要这一个条件就可以过滤掉 NSAssert。
方法:在 “Build Settings” 下搜索 **Preprocessor Macros** ,然后在 Release 下面添加 NS_BLOCK_ASSERTIONS
![](/Users/liubinpeng/Desktop/Github/knowledge-kit/assets/WX20180830-100631@2x.png)
![](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WX20180830-100631@2x.png)
### BreakPoint
#### 分类
Breakpoint 分为 Normal Breakpoint、Exception Breakpoint、OpenGL ES Error Breakpoint、Symbolic Breakpoint、Test Failure breakpoint、WatchPoint。可以按照具体的情景使用不同类型的 Breakpoint ,解决问题为根本
Breakpoint 分为 Normal Breakpoint、Exception Breakpoint、OpenGL ES Error Breakpoint、Symbolic Breakpoint、Test Failure breakpoint、WatchPoint。可以按照具体的情景使用不同类型的 Breakpoint
### NSAssert 与 dispatch_once
开发中非常常见 NSAssert尤其是在 SDK 和类库的开发中,使用断言帮助在开发阶段发现问题,督促达到预期的结果。
NSAssert 的本质就是产生一个 ExceptionException 发生触发 `objc_exception_throw` 这个 c 函数。
![NSAssert 断言](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-0311-NSAssert.png)
callback 信息如下
```Objective-c
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23c70ff8 +[NSException raise:format:arguments:] + 88
3 Foundation 0x00007fff256e9b51 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
4 TEst 0x0000000106edfeef -[AppDelegate application:didFinishLaunchingWithOptions:] + 287
5 UIKitCore 0x00007fff48089ad8 -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 232
6 UIKitCore 0x00007fff4808b460 -[UIApplication _callInitializationDelegatesWithActions:forCanvas:payload:fromOriginatingProcess:] + 3980
7 UIKitCore 0x00007fff48090f05 -[UIApplication _runWithMainScene:transitionContext:completion:] + 1226
8 UIKitCore 0x00007fff477c57a6 -[_UISceneLifecycleMultiplexer completeApplicationLaunchWithFBSScene:transitionContext:] + 179
9 UIKitCore 0x00007fff4808d514 -[UIApplication _compellApplicationLaunchToCompleteUnconditionally] + 59
10 UIKitCore 0x00007fff4808d813 -[UIApplication _run] + 754
11 UIKitCore 0x00007fff48092d4d UIApplicationMain + 1621
12 TEst 0x0000000106ee0144 main + 116
13 libdyld.dylib 0x00007fff5227ec25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
```
可以清楚看到当断言失败的时候Xcode 可以精确定位到 NSAssert 有问题的那行代码,这种情况下是有源代码。
其实有些场景下发生异常是定位不到真正产生异常的地方。比如当 App 规模较大,为了提高构建速度,很多人将 Pod 打成静态库,但是这种情况下产生的异常不会被精确定位到产生问题的行。如果断言在 GCD 的 block 中,而且上下文中没有源码,则也定位不到。
输出信息如下:
```Objective-c
*** First throw call stack:
(
0 CoreFoundation 0x00007fff23c7127e __exceptionPreprocess + 350
1 libobjc.A.dylib 0x00007fff513fbb20 objc_exception_throw + 48
2 CoreFoundation 0x00007fff23c70ff8 +[NSException raise:format:arguments:] + 88
3 Foundation 0x00007fff256e9b51 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 191
4 TEst 0x000000010f242e95 __57-[AppDelegate application:didFinishLaunchingWithOptions:]_block_invoke + 229
5 libdispatch.dylib 0x000000010f55fdd4 _dispatch_call_block_and_release + 12
6 libdispatch.dylib 0x000000010f560d48 _dispatch_client_callout + 8
7 libdispatch.dylib 0x000000010f56ede6 _dispatch_main_queue_callback_4CF + 1500
8 CoreFoundation 0x00007fff23bd4049 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
9 CoreFoundation 0x00007fff23bceca9 __CFRunLoopRun + 2329
10 CoreFoundation 0x00007fff23bce066 CFRunLoopRunSpecific + 438
11 GraphicsServices 0x00007fff384c0bb0 GSEventRunModal + 65
12 UIKitCore 0x00007fff48092d4d UIApplicationMain + 1621
13 TEst 0x000000010f243134 main + 116
14 libdyld.dylib 0x00007fff5227ec25 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
```
给 Xcode 添加 **Symbolic Breakpoint** 类型的断点Symbol 为 `objc_exception_throw`,就可以在 Xcode 的左侧堆栈中看到了。
![objc_exception_throw](https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/2020-03-11-objc_exception_throw.png)
其实 GCD 的 方法 **_dispatch_client_callout** 去查看下有没有猫腻,再从这里找到 libdispatch 的代码https://opensource.apple.com/tarballs/libdispatch/。
```Objective-c
// object.m
#undef _dispatch_client_callout
void
_dispatch_client_callout(void *ctxt, dispatch_function_t f)
{
@try {
return f(ctxt);
}
@catch (...) {
objc_terminate();
}
}
```
发现 _dispatch_client_callout 把 GCD block 中的 OC Exception try catch 捕获了,然后调用 objc_terminate导致了 CallStack 断开。
有个情景,工作 Crash 到 dispatch_once 这里了,因为 dispatch_once 中的代码 throw OC 异常。一般大公司初期这种情况经常遇到,后期一般都会针对断言专门开发一些代码用来定位 Owner。