iOS 手动实现奔溃信息收集

iOS 手动实现奔溃信息收集

在日常的开发工作中,App 在不同的用户会出现不同的应用场景,为了提高App 的可靠性和稳定性,我们可能需要收集一些用户在使用App 时出现的crash 报告,下面的功能就是收集用户在日常使用中出现crash 的具体措施,你只需要将对应的NSException解析后组装成你所需要的内容上传到服务器后,通过服务器数据结合本地文件即可进行crash 问题的定位。

一、系统crash

对于系统crash 而引起的程序异常退出,我们可以通过UncaughtExceptionHandler机制捕获,使用自定义的函数代替ExceptionHandler

二、处理signal

对于系统无法捕获的信号量异常,我们需要 利用unix标准的signal机制,注册SIGABRT, SIGBUS, SIGSEGV等信号发生时的处理函数。

三、代码实践

void installUncaughtExceptionHandler(void) {
    //设置系统异常捕获函数
    NSSetUncaughtExceptionHandler(&exceptionHandler);
    //设置Signal信息处理
    signal(SIGABRT, signalHandler);
    signal(SIGILL, signalHandler);
    signal(SIGSEGV, signalHandler);
    signal(SIGFPE, signalHandler);
    signal(SIGBUS, signalHandler);
    signal(SIGPIPE, SIG_IGN);
}

在上述代码中,我们将系统能捕获到的如什么数组越界之类的异常抛出来给自定义方法exceptionHandler,在方法中,我们可以获取到系统异常的所有信息,然后将捕获到的异常信息组装成NSException 进行传递

// 可捕获异常在此进行处理
void exceptionHandler(NSException *exception) {
    if (!exception) {
        return;
    }

    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
    if (exceptionCount > UncaughtExceptionMaximum) {
        DEBUGLOG(@"Exception异常数超过最大异常处理数");
        exitApplication();
        return;
    }

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionaryWithDictionary:[exception userInfo]];
    [userInfo setObject:[exception callStackSymbols] forKey:ExceptionCallStacks];

    NSException *exc = [NSException exceptionWithName:[exception name]
                                               reason:[exception reason]
                                             userInfo:userInfo];

    [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
                                                              withObject: exc
                                                           waitUntilDone:YES];
}

// 异常的信号量操作在此处理
void signalHandler(int signal) {
    int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
    if (exceptionCount > UncaughtExceptionMaximum) {
        DEBUGLOG(@"Signal异常数超过最大异常处理数, signal = %d.", signal);
        exitApplication();
        return;
    }

    NSString *reason = [NSString stringWithFormat:@"Signal %d was raised.", signal];

    NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
    [userInfo setObject:[NSNumber numberWithInt:signal] forKey:SignalExceptionKey];
	[userInfo setObject:[[UncaughtExceptionHandler backtrace] copy] forKey:ExceptionCallStacks];
	// 组装成NSException 对象
    NSException *exc = [NSException exceptionWithName:SignalExceptionName
                                               reason:reason
                                             userInfo:userInfo];

    [[[UncaughtExceptionHandler alloc] init] performSelectorOnMainThread:@selector(handleException:)
                                                              withObject:exc
                                                           waitUntilDone:YES];
}

+ (NSArray *)backtrace {
    //设置保存调用堆栈的buffer最大为64,调用backtrace用来获取当前线程的调用堆栈,获取的信息存放在这里的callstack
    void *callstack[64];
    int frames = backtrace(callstack, 64);
    char **strs = backtrace_symbols(callstack, frames);

    NSMutableArray *backtrace = [NSMutableArray arrayWithCapacity:frames];
    for (int i = 0; i < frames; i++) {
        [backtrace addObject:[NSString stringWithUTF8String:strs[i]]];
    }
    free(strs);

    return backtrace;
}

// 异常处理操作,在这里可以将NSException 解析成你所需要上传到云端的分析文件,以便进行用户crash 数据的收集
- (void)handleException:(NSException *)exception {
	
    NSString *name = [exception name];
    NSString *reason = [exception reason];
    NSArray *callStack = [[exception userInfo] objectForKey:ExceptionCallStacks];

    //组合崩溃信息并进行输出及保存
    NSString *exceptionInfo = @"\n=============== Exception Info ===============\n";
    exceptionInfo = [exceptionInfo stringByAppendingFormat:@"Exception Name: %@\n", name];
    exceptionInfo = [exceptionInfo stringByAppendingFormat:@"Exception Reason: %@\n", reason];
    exceptionInfo = [exceptionInfo stringByAppendingFormat:@"Exception Call Stack: %@\n", callStack];
}
发布了17 篇原创文章 · 获赞 2 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Abe_liu/article/details/103944991