iOS 开发 日志写入文件_日志捕捉_日志上传
2022-07-27 本文已影响0人
iOS_PM_WEB_尛鹏
【作者前言】:13年入圈,分享些本人工作中遇到的点点滴滴那些事儿,17年刚开始写博客,高手勿喷!以分享交流为主,欢迎各路豪杰点评改进!
1.应用场景:
很多时候,需要我们将项目的日志留存到文件中,或通过手机分享、Xcode调试、上传服务器 等形式,对日志进行分析;
这里也是应公司项目需要,写了一个小工具类,没那么长时间去写-直接一个类处理了(不喜勿喷~~~😄),有需要的盆友可以参考、使用
如有帮助,欢迎点赞/收藏/留言🤝
2.实现目标:
通过自定义宏实现多形式的日志打印,debug环境下同步输出控制台,便于调试;可开启是否写入文件等
懒得看???demo直通车[1]
使用效果图示:
Debug模式下,控制台同步:
image.png
对应的日志文件效果:
image.png
3.代码说明:
主要通过自写小工具类YPLogTool实现日志打印、同步文件写入、crash捕捉、日志上传等
1)支持多用户日志存取,数据文件存储结构说明:
image.png2)支持普通日志控制台打印(不参与写文件流)、info/warn/error 多形式打印日志的 便捷宏
image.pngimage.png
3)支持设置日志文件的最大存储空间(Mb)
image.png4)支持设置日志文件的保留天数 (与3相比,具有优先级)
image.png5)支持随时控制写入文件流的开关
image.png6)支持强制写入文件流 (应对一些BT场景,如SDK开发等,开发期间真机调试可开启直接看效果)
image.png7)支持获取当次打印的所有数据,可用于一些图形化日志数据的回显等
image.png8)核心代码实现(列举下写文件的吧,多了看了也烦😄~~~具体看本文底部,我会附上demo地址)
YPLogTool.m
//MARK: - writeLogWithTime: file: line: function: format:
+ (void)writeLogWithTime:(NSString *)timeStr file:(NSString *)file line:(NSUInteger)line function:(NSString *)function format:(NSString *)format {
NSString *logStr = [YPLogTool getFmtLogStrWithTime:timeStr file:file line:line function:function format:format];
NSString *dayStr = [[timeStr componentsSeparatedByString:@" "][0] stringByReplacingOccurrencesOfString:@"-" withString:@""];
NSError *error = nil;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSString *filePath = [_curUserDirectoryPath stringByAppendingPathComponent:[NSString stringWithFormat:@"YPLog_%@_%@.text", _curUserId, dayStr]];
if(![fileManager fileExistsAtPath:filePath]) {
[logStr writeToFile:filePath atomically:YES encoding:NSUTF8StringEncoding error:&error];
if (error) {
YPWLogError(@"write to file error ->%@", error.domain);
}
}else {
NSFileHandle *fileHandle = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
[fileHandle seekToEndOfFile];
NSData* stringData = [logStr dataUsingEncoding:NSUTF8StringEncoding];
[fileHandle writeData:stringData];
[fileHandle synchronizeFile];
[fileHandle closeFile];
}
#if DEBUG
if (_curLogType == YP_LOG_LEVEL_INFO) {
fprintf(stderr,"❄️『INFO』[%s] [%s:%lu] %s ●:%s\n",[timeStr UTF8String], [file UTF8String], (unsigned long)line, [function UTF8String], [format UTF8String]);
}else if (_curLogType == YP_LOG_LEVEL_WARN) {
fprintf(stderr,"⚠️『WARN』[%s] [%s:%lu] %s ●:%s\n",[timeStr UTF8String], [file UTF8String], (unsigned long)line, [function UTF8String], [format UTF8String]);
}else if (_curLogType == YP_LOG_LEVEL_ERROR) {
fprintf(stderr,"❌『ERROR』[%s] [%s:%lu] %s ●:%s\n",[timeStr UTF8String], [file UTF8String], (unsigned long)line, [function UTF8String], [format UTF8String]);
}else if (_curLogType == YP_LOG_LEVEL_ONLY_DEBUG_PRINT_NSLOG) {
fprintf(stderr,"🐭『DEBUG』[%s] [%s:%lu] %s ●:%s\n",[timeStr UTF8String], [file UTF8String], (unsigned long)line, [function UTF8String], [format UTF8String]);
}
#else
#endif
_logTimes ++;
if (!(_logTimes % 5000)) {// ≈ [0.5Mb-1Mb] to check once filesize => better
FILE_SIZE_CHECK_LOOP: {
float curFileSize = [YPLogTool getTotalLogsSizeMb];
if (curFileSize >= yp_maxFoldSize) {
FILE_EARLIEST_LOOP: {
NSString *earliestFilePath = [YPLogTool getEarliestLogFilePath];
if ([earliestFilePath isEqualToString:@"NoFilePath"]) {
return;
}
NSMutableArray *temp = [NSMutableArray arrayWithArray:[earliestFilePath componentsSeparatedByString:@"/"]];
[temp removeLastObject];
NSString *earliestUserPath = [temp componentsJoinedByString:@"/"];
NSInteger userLogsCount = [YPLogTool getUserPathLogsCount:earliestUserPath];
if (userLogsCount > yp_forceSaveDays) {
if ([fileManager fileExistsAtPath:earliestFilePath]) {
[fileManager removeItemAtPath:earliestFilePath error:nil];
YPWLogInfo(@"find cleanable file:%@ -> cleared", [earliestFilePath componentsSeparatedByString:@"/"].lastObject);
goto FILE_SIZE_CHECK_LOOP;
}
}else {
NSString *userDirectoryName = temp.lastObject;
[_tempNoClearUserDirectoryNames addObject:userDirectoryName];
goto FILE_EARLIEST_LOOP;
}
}
}
}
}
}