crash日志的本地记录

来源:互联网 发布:雪梨淘宝店名叫什么 编辑:程序博客网 时间:2024/06/03 20:37

app大都会crash,而第三方平台截获的崩溃日志,需要文件描述符才能解析。手机上的崩溃日志有时候也定位不到具体行。
我的建议是为了方便,测试版本可以本地记录崩溃日志。线上版本可以使用fir或bugly.
本地记录的好处是实时获取,不需要本地文件描述符。
本地记录崩溃日志的方法是增加如下代码:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {    [self configDDLog];    return YES;}- (void)configDDLog {#ifdef DEBUG    //把崩溃日志写入文件    [GBLogWrite redirectNSLogToDocumentFolder];#endif}

打印本地日志的方法是由以前我的同步日志改进过来的。我的同步日志连续快速打印有性能问题,但是应用崩溃前打印一次不在话下,没有任何问题:
GBLogWrite.h文件

////  GBLogWrite.h//  GreenBusiness////  Created by 郏国上 on 2017/3/31.//  Copyright © 2017年 UXing. All rights reserved.//#import <Foundation/Foundation.h>#define ERR_LOG 1 /* 应用程序无法正常完成操作,比如网络断开,内存分配失败等 */#define WARN_LOG 2 /* 进入一个异常分支,但并不会引起程序错误 */#define INFO_LOG 3 /* 日常运行提示信息,比如登录、退出日志 */#define DEBUG_LOG 4 /* 调试信息,打印比较频繁,打印内容较多的日志 */#ifndef LOGERR#define LOGERR(format,...) WriteLog(ERR_LOG,__FUNCTION__,__LINE__,format,##__VA_ARGS__)#endif#ifndef LOGWARN#define LOGWARN(format,...) WriteLog(WARN_LOG,__FUNCTION__,__LINE__,format,##__VA_ARGS__)#endif#ifndef LOGINFO#define LOGINFO(format,...) WriteLog(INFO_LOG,__FUNCTION__,__LINE__,format,##__VA_ARGS__)#endif#ifndef LOGDEBUG#define LOGDEBUG(format,...) WriteLog(DEBUG_LOG,__FUNCTION__,__LINE__,format,##__VA_ARGS__)#endif@interface GBLogWrite : NSObject+ (void)redirectNSLogToDocumentFolder;@end

GBLogWrite.m文件

////  GBLogWrite.m//  GreenBusiness////  Created by 郏国上 on 2017/3/31.//  Copyright © 2017年 UXing. All rights reserved.//#import "GBLogWrite.h"static const long g_logFilesCount = 3;static const long g_logFileLines = 65535;@implementation GBLogWriteNSString *getTime(void){    NSDateFormatter * formatter = [[NSDateFormatter alloc]init];    [formatter setDateFormat:@"YYYY-MM-dd HH:mm:ss:SSS"];    NSString* dateTime = [formatter stringFromDate:[NSDate date]];    return dateTime;}void WriteFileLog(NSString *format, ...){    va_list args;    va_start(args, format);    NSString *string = [[NSString alloc] initWithFormat:format arguments:args];    va_end(args);    if(!string)    {        return;    }    NSFileManager* fm = [NSFileManager defaultManager];    NSString *str = nil;    BOOL flag = NO;    NSArray* myPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);    NSString* myDocPath = [myPaths objectAtIndex:0];    NSString* path = [myDocPath stringByAppendingPathComponent:@"crash"];    [fm  fileExistsAtPath:path isDirectory:&flag];    NSArray *dirarray = nil;    NSString* filePath = nil;    NSArray *lines = nil;    NSError *error = nil;    NSData* data = nil;    NSInteger n = 0, i = 0, m = 0;    NSMutableArray *filesMutableArr = [NSMutableArray array];    NSDictionary *infoDictionary = [[NSBundle mainBundle] infoDictionary];    NSString *app_Name = [infoDictionary objectForKey:@"CFBundleName"];    if(flag)    {        //        dirarray = [fm contentsOfDirectoryAtPath:filePath];        //        FLDDLogDebug(@"%@ ",dirarray);        dirarray = [fm contentsOfDirectoryAtPath:path error:nil];        NSLog(@"%@ ",dirarray);        n = dirarray.count;        for(i = 0; i < n; i++)        {            filePath = [path stringByAppendingPathComponent:dirarray[i]];            if ([fm fileExistsAtPath:filePath])            {                [filesMutableArr addObject:filePath];            }        }        m = filesMutableArr.count;        if(m > g_logFilesCount)        {            NSMutableArray *newFilesMutableArr = [NSMutableArray array];            for(i =  m - g_logFilesCount ; i < m; i++)            {                filePath = filesMutableArr[i];                [newFilesMutableArr addObject:filePath];            }            //若想删除超过指定日志文件个数的最老的文件            for(i = 0; i < m - g_logFilesCount ; i++)            {                filePath = filesMutableArr[i];                [fm removeItemAtPath:filePath error:nil];            }            filesMutableArr = newFilesMutableArr;            m = filesMutableArr.count;            //            for(i = 0 ; (m - i > 0) && (i  < m - g_logFilesCount); i++)            //            {            //                filePath = filesMutableArr[m - i];            //                [fm removeItemAtPath:filePath error:nil];            //            }        }        if(g_logFilesCount == m)        {            filePath = filesMutableArr[m - 1];            lines = [[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]                     componentsSeparatedByString:@"\n"];            if(lines.count < g_logFileLines)            {                data = [NSData dataWithContentsOfFile:filePath];                str =[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];                str = [NSString stringWithFormat:@"%@\n%@",str,string];                [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];            }            else            {                [fm removeItemAtPath:filePath error:nil];                str = [NSString stringWithFormat:@"%@ %@.text", app_Name, getTime()];                filePath = [path stringByAppendingPathComponent:str];                str = string;                [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];            }        }        else if(m > 0)        {            filePath = filesMutableArr[m - 1];            //            str =[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:&error];            //            str = [NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil];            //            NSLog(@"str :%@", str);            lines = [[NSString stringWithContentsOfFile:filePath encoding:NSUTF8StringEncoding error:nil]                     componentsSeparatedByString:@"\n"];            //            if(lines.count < 65535)            if(lines.count < g_logFileLines)            {                data = [NSData dataWithContentsOfFile:filePath];                str =[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];                str = [NSString stringWithFormat:@"%@\n%@",str,string];                [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];            }            else            {                str = [NSString stringWithFormat:@"%@ %@.text", app_Name, getTime()];                filePath = [path stringByAppendingPathComponent:str];                str = string;                [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];            }        }        else        {            str = [NSString stringWithFormat:@"%@ %@.text", app_Name, getTime()];            filePath = [path stringByAppendingPathComponent:str];            str = string;            [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:nil];        }    }    else    {        BOOL res = [fm createDirectoryAtPath:path withIntermediateDirectories:YES attributes:nil error:nil];        if (res) {            //            NSLog(@"文件夹创建成功");            str = [NSString stringWithFormat:@"%@ %@.text", app_Name, getTime()];            filePath = [path stringByAppendingPathComponent:str];            str = string;            //            NSLog(@"filePath :%@", filePath);            [str writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];            //            NSLog(@"error :%@", error);        }        else        {            NSLog(@"文件夹创建失败");        }    }}void WriteLog(int ulErrorLevel, const char *func, int lineNumber, NSString *format, ...){    va_list args;    va_start(args, format);    NSString *string = [[NSString alloc] initWithFormat:format arguments:args];    va_end(args);    NSString *strFormat = [NSString stringWithFormat:@"%@%s, %@%i, %@%@",@"Function: ",func,@"Line: ",lineNumber, @"Format: ",string];    NSString * strModelName = @"文件日志"; //模块名    NSString *strErrorLevel = [[NSString alloc] init];    switch (ulErrorLevel) {        case ERR_LOG:            strErrorLevel = @"Error";            break;        case WARN_LOG:            strErrorLevel = @"Warning";            break;        case INFO_LOG:            strErrorLevel = @"Notice";            break;        case DEBUG_LOG:            strErrorLevel = @"Debug";            break;        default:            break;    }    NSLog(@"ModalName: %@, ErrorLevel: %@, %@.",strModelName, strErrorLevel, strFormat);    NSString *str = [NSString stringWithFormat:@"ModalName: %@, ErrorLevel: %@, %@.",strModelName, strErrorLevel, strFormat];    NSLog(@"%@", str);    //    WriteLog;    WriteFileLog(str);}void UncaughtExceptionHandler(NSException* exception){    NSString* name = [ exception name ];    NSString* reason = [ exception reason ];    NSArray* symbols = [ exception callStackSymbols ]; // 异常发生时的调用栈    NSMutableString* strSymbols = [ [ NSMutableString alloc ] init ]; //将调用栈拼成输出日志的字符串    for ( NSString* item in symbols )    {        [ strSymbols appendString: item ];        [ strSymbols appendString: @"\r\n" ];    }    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];    [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"zh_CN"]];    [formatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"];    NSString *dateStr = [formatter stringFromDate:[NSDate date]];    LOGERR(@"<- %@ ->[ Uncaught Exception ]\r\nName: %@, Reason: %@\r\n[ Fe Symbols Start ]\r\n%@[ Fe Symbols End ]\r\n\r\n", dateStr, name, reason, strSymbols);}+ (void)redirectNSLogToDocumentFolder{    //未捕获的Objective-C异常日志    NSSetUncaughtExceptionHandler (&UncaughtExceptionHandler);}@end

打印的崩溃日志:

ModalName: 文件日志, ErrorLevel: Error, Function: UncaughtExceptionHandler, Line: 215, Format: <- 2017-03-31 11:02:48 ->[ Uncaught Exception ]Name: NSInvalidArgumentException, Reason: *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0][ Fe Symbols Start ]0   CoreFoundation                      0x000000018894eff0 <redacted> + 1481   libobjc.A.dylib                     0x00000001873b0538 objc_exception_throw + 562   CoreFoundation                      0x00000001888302c8 <redacted> + 3083   CoreFoundation                      0x0000000188942c38 <redacted> + 364   CoreFoundation                      0x0000000188832cbc <redacted> + 365   OutdoorClub                         0x0000000100133d58 -[ODCCurrentPathLocationDataSingleObject saveCoordateWithFileName:lastLocationOperateModel:] + 3086   OutdoorClub                         0x0000000100132c90 -[ODCCurrentPathLocationDataSingleObject readmis] + 16727   OutdoorClub                         0x0000000100132324 __50-[ODCCurrentPathLocationDataSingleObject initData]_block_invoke + 1008   OutdoorClub                         0x00000001003c2a10 +[NSTimer(YYAdd) _yy_ExecBlock:] + 1489   Foundation                          0x0000000189443760 __NSFireTimer + 8810  CoreFoundation                      0x00000001888fda9c <redacted> + 2811  CoreFoundation                      0x00000001888fd7a0 <redacted> + 85612  CoreFoundation                      0x00000001888fd060 <redacted> + 24413  CoreFoundation                      0x00000001888fac84 <redacted> + 148414  CoreFoundation                      0x000000018882ad94 CFRunLoopRunSpecific + 42415  GraphicsServices                    0x000000018a294074 GSEventRunModal + 10016  UIKit                               0x000000018eae3130 UIApplicationMain + 20817  OutdoorClub                         0x000000010014853c main + 12418  libdyld.dylib                       0x000000018783959c <redacted> + 4[ Fe Symbols End ].ModalName: 文件日志, ErrorLevel: Error, Function: UncaughtExceptionHandler, Line: 215, Format: <- 2017-03-31 19:34:33 ->[ Uncaught Exception ]Name: NSInvalidArgumentException, Reason: *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0][ Fe Symbols Start ]0   CoreFoundation                      0x000000018894eff0 <redacted> + 1481   libobjc.A.dylib                     0x00000001873b0538 objc_exception_throw + 562   CoreFoundation                      0x00000001888302c8 <redacted> + 3083   CoreFoundation                      0x0000000188942c38 <redacted> + 364   CoreFoundation                      0x0000000188832cbc <redacted> + 365   OutdoorClub                         0x00000001000c7d38 -[ODCCurrentPathLocationDataSingleObject saveCoordateWithFileName:lastLocationOperateModel:] + 4486   OutdoorClub                         0x00000001000c6be4 -[ODCCurrentPathLocationDataSingleObject readmis] + 16727   OutdoorClub                         0x00000001000c6254 __50-[ODCCurrentPathLocationDataSingleObject initData]_block_invoke + 1008   OutdoorClub                         0x0000000100356a70 +[NSTimer(YYAdd) _yy_ExecBlock:] + 1489   Foundation                          0x0000000189443760 __NSFireTimer + 8810  CoreFoundation                      0x00000001888fda9c <redacted> + 2811  CoreFoundation                      0x00000001888fd7a0 <redacted> + 85612  CoreFoundation                      0x00000001888fd060 <redacted> + 24413  CoreFoundation                      0x00000001888fac84 <redacted> + 148414  CoreFoundation                      0x000000018882ad94 CFRunLoopRunSpecific + 42415  GraphicsServices                    0x000000018a294074 GSEventRunModal + 10016  UIKit                               0x000000018eae3130 UIApplicationMain + 20817  OutdoorClub                         0x00000001000dc52c main + 12418  libdyld.dylib                       0x000000018783959c <redacted> + 4[ Fe Symbols End ].ModalName: 文件日志, ErrorLevel: Error, Function: UncaughtExceptionHandler, Line: 215, Format: <- 2017-04-01 09:35:10 ->[ Uncaught Exception ]Name: NSInvalidArgumentException, Reason: *** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0][ Fe Symbols Start ]0   CoreFoundation                      0x000000018894eff0 <redacted> + 1481   libobjc.A.dylib                     0x00000001873b0538 objc_exception_throw + 562   CoreFoundation                      0x00000001888302c8 <redacted> + 3083   CoreFoundation                      0x0000000188942c38 <redacted> + 364   CoreFoundation                      0x0000000188832cbc <redacted> + 365   OutdoorClub                         0x00000001000a3d38 -[ODCCurrentPathLocationDataSingleObject saveCoordateWithFileName:lastLocationOperateModel:] + 4486   OutdoorClub                         0x00000001000a2be4 -[ODCCurrentPathLocationDataSingleObject readmis] + 16727   OutdoorClub                         0x00000001000a2254 __50-[ODCCurrentPathLocationDataSingleObject initData]_block_invoke + 1008   OutdoorClub                         0x0000000100332a70 +[NSTimer(YYAdd) _yy_ExecBlock:] + 1489   Foundation                          0x0000000189443760 __NSFireTimer + 8810  CoreFoundation                      0x00000001888fda9c <redacted> + 2811  CoreFoundation                      0x00000001888fd7a0 <redacted> + 85612  CoreFoundation                      0x00000001888fd060 <redacted> + 24413  CoreFoundation                      0x00000001888fac84 <redacted> + 148414  CoreFoundation                      0x000000018882ad94 CFRunLoopRunSpecific + 42415  GraphicsServices                    0x000000018a294074 GSEventRunModal + 10016  UIKit                               0x000000018eae3130 UIApplicationMain + 20817  OutdoorClub                         0x00000001000b852c main + 12418  libdyld.dylib                       0x000000018783959c <redacted> + 4[ Fe Symbols End ].

注意:我们的同步日志系统在didFinishLaunchingWithOptions之前的崩溃无能为力,毕竟只有同步日志初始化以后才能记录,估计第三方平台也有这样的问题。

0 0
原创粉丝点击