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.png
2)支持普通日志控制台打印(不参与写文件流)、info/warn/error 多形式打印日志的 便捷宏
image.png
image.png
3)支持设置日志文件的最大存储空间(Mb)
image.png
4)支持设置日志文件的保留天数 (与3相比,具有优先级)
image.png
5)支持随时控制写入文件流的开关
image.png
6)支持强制写入文件流 (应对一些BT场景,如SDK开发等,开发期间真机调试可开启直接看效果)
image.png
7)支持获取当次打印的所有数据,可用于一些图形化日志数据的回显等
image.png
8)核心代码实现(列举下写文件的吧,多了看了也烦😄~~~具体看本文底部,我会附上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;
                    }
                }
            }
        }
    }
}
9)Demo地址

  1. Demo直通车

上一篇下一篇

猜你喜欢

热点阅读