在开发过程中,需要收集奔溃日志,那怎么做到奔溃日志上传呢,通常集成第三方工具,什么友盟、蒲公英、腾讯之类的统计软件,但是有的公司有要求,奔溃日志需要存放在服务器上面,本文就介绍下通过FTP搜集日志的方法:
1、实现C语言通过的的方法uncaughtExceptionHandler捕获奔溃日志, 将崩溃信息持久化在本地,下次程序启动时,将崩溃信息作为日志发送给开发者
CatchCrash.h
#import
@interface CatchCrash : NSObject
/**
* 异常处理函数
*
* @param exception 异常对象
*/
void uncaughtExceptionHandler(NSException *exception);
@end
CatchCrash.m
void uncaughtExceptionHandler(NSException *exception){
NSMutableString *exceptionJSON = [[NSMutableString alloc] init];
[exceptionJSON appendString:@"{\n"];
[exceptionJSON appendFormat:@"\t\"异常时间\":\"%@\",\n",[CatchCrash getCurrentTime]];
[exceptionJSON appendFormat:@"\t\"用户名字\":\"%@\",\n",[KKInfoHelper readUserInfo].username];
[exceptionJSON appendFormat:@"\t\"设备型号\":\"%@\",\n",[DeviceInfo getDeviceInfo].deviceModel];
[exceptionJSON appendFormat:@"\t\"系统名称\":\"%@\",\n",[DeviceInfo getDeviceInfo].systemName];
[exceptionJSON appendFormat:@"\t\"设备名称\":\"%@\",\n",[DeviceInfo getDeviceInfo].deviceName];
[exceptionJSON appendFormat:@"\t\"系统版本\":\"%@\",\n",[DeviceInfo getDeviceInfo].systemVersion];
[exceptionJSON appendFormat:@"\t\"应用版本\":\"%@\",\n",[[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleShortVersionString"]];
[exceptionJSON appendFormat:@"\t\"异常名称\":\"%@\",\n",[exception name]];
[exceptionJSON appendFormat:@"\t\"异常原因\":\"%@\",\n",[exception reason]];
[exceptionJSON appendString:@"\t\"异常堆栈\":\n\t\""];
for (NSString* str in [exception callStackSymbols]) {
[exceptionJSON appendFormat:@"[%@]",str];
}
[exceptionJSON appendString:@"\",\n"];
[exceptionJSON appendString:@"}"];
[exceptionJSON writeToFile:[NSString stringWithFormat:@"%@/Documents/CrashError.log",NSHomeDirectory()] atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
2、通过GoldRaccoon这个第三方ftp框架将写入本地的文件上传到服务器,
UploadCrashLog.h文件
#import
@interface UploadCrashLog : NSObject
/**
* 上传崩溃日志实例
*/
+ (UploadCrashLog*)getInstance;
/**
* 开始上传崩溃日志
*/
- (void)startUpload;
@end
UploadCrashLog.m文件
#import "UploadCrashLog.h"
#import "Global.h"
#import "AppDelegate.h"
#import "KKValidate.h"
#import "GRRequestsManager.h"
@interface UploadCrashLog () {
BOOL _connected;
}
@property (nonatomic, strong) GRRequestsManager *requestsManager;
@property (nonatomic, strong) NSString *filePath;
@end
@implementation UploadCrashLog
/**
* 上传崩溃日志实例
*/
+ (UploadCrashLog*)getInstance {
static UploadCrashLog *sharedInstance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
/**
* 开始上传崩溃日志
*/
- (void)startUpload {
//[self performSelectorInBackground:@selector(uploadProcess:) withObject:nil];
[NSThread detachNewThreadSelector:@selector(uploadProcess:) toTarget:self withObject:nil];
}
-(GRRequestsManager *)requestsManager {
if (!_requestsManager) {
NSString* hostName = CrashLogSFTPHostName;
NSInteger port = CrashLogSFTPPort;
NSString* userName = CrashLogSFTPUserName;
NSString* password = CrashLogSFTPPassword;
_requestsManager=[[GRRequestsManager alloc] initWithHostname:hostName user:userName password:password];
self.requestsManager.delegate = self;
}
return _requestsManager;
}
- (void)uploadProcess:(id)sender {
NSString* logRemotePath = CrashLogSFTPLogDir;
NSString* logLocalPath = [NSString stringWithFormat:@"%@/Documents/CrashError.log",NSHomeDirectory()];
//先判断是否有崩溃日志
NSFileManager* fileManager = [NSFileManager defaultManager];
BOOL isDirectory;
BOOL isPathExist = [fileManager fileExistsAtPath:logLocalPath isDirectory:&isDirectory];
if (!isPathExist || isDirectory) {
return;
}
logRemotePath = [logRemotePath stringByAppendingPathComponent:[NSString stringWithFormat:@"/Stomatiology%.f.log",[[NSDate date]timeIntervalSince1970]*1000000]];
[self.requestsManager addRequestForUploadFileAtLocalPath:logLocalPath toRemotePath:logRemotePath];
[self.requestsManager startProcessingRequests];
}
/**
* 获取yyyy-MM-dd HH:mm:ss格式的时间
*/
-(NSString*)getCurrentTime {
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss.SSZ"];
return [dateFormatter stringFromDate:[NSDate date]];
}
- (void)requestsManager:(id)requestsManager didCompleteUploadRequest:(id)request
{
NSLog(@"requestsManager:didCompleteUploadRequest:%@",@"上传崩溃信息成功");
NSFileManager* fileManager = [NSFileManager defaultManager];
//删除本地崩溃日志文件
NSString* logLocalPath = [NSString stringWithFormat:@"%@/Documents/CrashError.log",NSHomeDirectory()];
[fileManager removeItemAtPath:logLocalPath error:nil];
}
- (void)requestsManager:(id)requestsManager didFailWritingFileAtPath:(NSString *)path forRequest:(id)request error:(NSError *)error
{
NSLog(@"requestsManager:didFailWritingFileAtPath:forRequest:error: \n %@", error);
}
- (void)requestsManager:(id)requestsManager didFailRequest:(id)request withError:(NSError *)error
{
NSLog(@"requestsManager:didFailRequest:withError: \n %@", error);
}
@end
当然也可以调用后台提供的接口,当下次开启APP将奔溃日志上传,此外还可以通过发邮件的方式将日志发送到指定邮箱。