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
- crash日志的本地记录
- Android的Crash日志记录
- iOS 记录crash日志
- android开发技巧-记录未捕获的crash异常日志
- crash日志的分析
- IOS 本地保存Crash日志信息
- 友盟Crash的记录
- iOS运用fabric记录crash日志过程
- iOS Crash 日志的获取
- iOS crash日志的处理
- 多线程记录本地数据库日志
- Android实现将日志、异常记录到本地的方法
- Android全局捕获crash并保存日志到本地
- ios crash的原因与抓取crash日志的方法
- 如何记录并分析CRASH日志方法一
- 如何记录并分析CRASH日志方法二
- 上传程序crash的日志------bugly
- 安卓应用crash日志的获取
- iOS应用支持IPV6,就那点事儿
- HDU 2594 Simpsons’ Hidden Talents KMP
- React Native之TextInput自定义
- 个人记录-LeetCode 96. Unique Binary Search Trees
- org.apache.jasper.runtime.ELContextImpl cannot be cast to org.apache.jasper.el.ELContextImpl
- crash日志的本地记录
- 通用并发对象池的实现
- css如何清除浮动(五)
- Eclipse插件之Skpet变量名自动提示设置
- Language Guide (proto3)
- linux学习之shell命令:
- Parallel 收集器
- 蓝桥杯JAVA语言B组_武功秘籍
- 谈谈C语言