前言

鉴于项目中呈现的一些问题,不好排查,光靠服务器的日志记载不太能精确的定位问题,本地日志的记载无疑是辅助性比较强的。

封装一个日志搜集的类,完成日志信息文件保存本地,日志保存天数设置、过期日志主动删去,日志信息文件可紧缩(提供紧缩文件保存路径,可根据上传服务器方式独自装备)简略记载一下。

完成逻辑

1、日志记载保存在本地

首要明确一个问题,记载日志需求将字符串转成数据(NSData)保存在本地,NSData写入本地会对本地的文件进行覆盖,所以只有当文件不存在第一次写入的时分用这种方式,如果要将日志内容追加到日志文件里面,运用NSFleHandle来处理。

#pragma mark - 获取参数
NSMutableString* parmaStr = [NSMutableString string];
// 声明一个参数指针 va_list paramList;
// 获取参数地址,将paramList指向logStr
va_start(paramList, logStr);
id arg = logStr;
@try {
    // 遍历参数列表
    while (arg) {
    [parmaStr appendString:arg];
    // 指向下一个参数,后面是参数类似
    arg = va_arg(paramList, NSString*);
    }
} @catch (NSException *exception) {
    [parmaStr appendString:@"【记载日志反常】"];
} @finally {
    // 将参数列表指针置空
    va_end(paramList);
}
#pragma mark - 写入日志
// 异步执行
dispatch_async(dispatch_queue_create("writeLog", nil), ^{
    // 获取当时日期做为文件名
    NSString* fileName = [self.dateFormatter stringFromDate:[NSDate date]];
    NSString* filePath = [NSString stringWithFormat:@"%@%@",self.basePath,fileName];
    // [时刻]-[模块]-日志内容,时刻格式自定义
    NSString* timeStr = [self.timeFormatter stringFromDate:[LogManager getCurrDate]];
    NSString* writeStr = [NSString stringWithFormat:@"[%@]-[%@]-%@\n",timeStr,module,parmaStr];
    // 写入数据
    [self writeFile:filePath stringData:writeStr];
    NSLog(@"写入日志:%@",filePath);
});
/**
* 写入字符串到指定文件,默认追加内容
*
* **@param** filePath  文件路径
* **@param** stringData 待写入的字符串
*/
- (**void**)writeFile:(NSString*)filePath stringData:(NSString*)stringData{
  // 待写入的数据
  NSData* writeData = [stringData dataUsingEncoding:NSUTF8StringEncoding];
  NSData *ungzipData = [writeData gunzippedData];
  // NSFileManager 用于处理文件
  BOOL createPathOk = YES;
  if (![[NSFileManager defaultManager] fileExistsAtPath:[filePath stringByDeletingLastPathComponent] isDirectory:&createPathOk]) {
    // 目录不存先创立
    [[NSFileManager defaultManager] createDirectoryAtPath:[filePath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
  }
  if(![[NSFileManager defaultManager] fileExistsAtPath:filePath]){
    // 文件不存在,直接创立文件并写入
    [writeData writeToFile:filePath atomically:NO];
  }else{
    // NSFileHandle 用于处理文件内容
    // 读取文件到上下文,并且是更新形式
    NSFileHandle* fileHandler = [NSFileHandle fileHandleForUpdatingAtPath:filePath];
    // 跳到文件末尾
    [fileHandler seekToEndOfFile];
    // 追加数据
    [fileHandler writeData:ungzipData];
    // 关闭文件
    [fileHandler closeFile];
  }
}

2、日志记载保存时刻约束

下面方法只是删去了未紧缩前的文件,紧缩后的文件过期同样需求删去,逻辑相同,此处不再赘述。


// 获取日志目录下的一切文件
NSArray* files = [[NSFileManager defaultManager] contentsOfDirectoryAtPath: self.basePath error: nil];
  for (NSString* file in files) {
    NSDate* date = [self.dateFormatter dateFromString:file];
    if (date) {
     NSTimeInterval oldTime = [date timeIntervalSince1970];
     NSTimeInterval currTime = [[LogManager getCurrDate] timeIntervalSince1970];
     NSTimeInterval second = currTime - oldTime;
     int day = (int)second / (24 * 3600);
     if (day >= LogMaxSaveDay) {
        // 删去该文件
        [[NSFileManager defaultManager] removeItemAtPath:[NSString stringWithFormat:@"%@/%@",self.basePath,file] error: nil];
        NSLog(@"[%@]日志文件已被删去!",file);
        }
      }
    }

3、日志文件紧缩

一般的紧缩功用采用zip紧缩即可,本文运用ZipArchive。项目地址:github.com/ZipArchive/…

此处留意一个点:被紧缩文件最好与紧缩文件同名,否则会导致生成不了紧缩文件。

主张:未紧缩文件和紧缩文件存放在不同的目录下,或许更方便办理

// 紧缩包文件路径
  NSString *dateStr = [**self**.dateFormatter stringFromDate:[NSDate date]];
  NSString * zipFile = [NSString stringWithFormat:@"%@%@.zip",**self**.zipBasePath, dateStr];
  NSString* filePath = [**self** getLogPathWithDate:**nil**];
  BOOL createPathOk = **YES**;
  if (![[NSFileManager defaultManager] fileExistsAtPath:[zipFile stringByDeletingLastPathComponent] isDirectory:&createPathOk]) {
    // 目录不存先创立
    [[NSFileManager defaultManager] createDirectoryAtPath:[zipFile stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
  }
  // 创立一个zip包
  BOOL created = [SSZipArchive createZipFileAtPath:zipFile withFilesAtPaths:@[filePath]];
  if ([[NSFileManager defaultManager] fileExistsAtPath:zipFile]) {
//    NSLog(@"有文件");
  } else {
//    NSLog(@"没有文件");
  }
  return created;

4、写在最后

调用方式能够根据事务需求适当调整,所以在这里只放了中心代码。逻辑很简略,主要看事务想要搜集哪些日志信息。