如何将所有错误(包括未捕获的异常,NSLog调用和其他日志)重定向到Mac OS X上的日志文件?

Ara*_*ion 15 macos logging cocoa objective-c

我试图找到一个用ObjC编写的Cocoa应用程序的日志框架.

到目前为止我的尝试:

  1. 使用NSLog,但后来意识到配置和重定向非常困难.我想我可以破解它并编写一个获取我想要的信息的宏,比如线程ID,当前函数,当前行,当前文件,当前时间,消息等等,然后使用NSLog,但是......
  2. NSLog最终使用NSLogv,最终使用asl,所以我觉得"太棒了",我尝试使用asl代替,使用默认的客户端和上下文(如果我这样做,我将不得不为每个线程创建一个新的客户端但是,除非我创建一个宏,这也非常冗长,我注意到通过asl发送的日志得到广播系统,而NSLog只登录到stderr,我希望它们都转到同一个日志!
  3. 然后我注意到错误,以不同的方式(不同的日期戳等)格式化,因此现在有第三个日志记录上下文.

我可以使用哪种日志框架设置以方便的方式通过该框架记录所有消息,以便在应用程序出现问题时,开发人员可以获取日志文件,并找出问题所在?

我不想简单地重定向stderr,我希望有一个包含所有日志的结构化日志输出.我不希望某些日志转到标准输出,我不希望任何日志发送到syslogd,我只想将所有日志写入单个文件,可靠地识别有关该日志消息的所有相关信息(例如线程ID,消息,调用记录器的函数,等等,格式易于查看和可视化.

我想要的是将所有当前日志重定向到新目标.

有没有人有什么建议?

编辑:

实际上,我想用ObjC术语做的是:

  1. 在NSLog函数上执行"方法调配".这可能吗?是否可以(重新)配置Apple System Logger的使用,以覆盖同一应用程序中任何先前的服务配置?
  2. 确定我必须捕获未处理异常的所有位置.这包括但不限于:未处理的Cocoa异常.未处理的ObjC异常.未处理的C++异常.Unix信号.
  3. 捕获并记录堆栈中的错误,例如CoreGraphics引发的错误.(那些只是简单地记录消息"使用调试器添加断点!!!").

Jac*_*kin 9

您可以使用Foundation函数NSSetUncaughtExceptionHandler设置一个回调函数,该函数将处理所有未捕获的异常:

void CustomLogger(NSString *format, ...) {
   //do other awesome logging stuff here...
}

void uncaughtExceptionHandler(NSException *exception) {
   //do something useful, like this:
   CustomLogger(@"%@", [exception reason]);
}

NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
Run Code Online (Sandbox Code Playgroud)

对于NSLog,您可以使用宏来覆盖它:)

#define NSLog(...) CustomLogger(__VA_ARGS__);
Run Code Online (Sandbox Code Playgroud)


Jen*_*ton 9

您可以使用拦截NSLog()消息(但不包括ASL)_NSSetLogCStringFunction().这里有针对Windows的WebObjects 4 记录,但它也存在于当前的Mac OS和iOS版本中.但是,它是一个私有函数,可能随时消失,所以你不应该在发布的代码中依赖它.

如果您希望能够安全地为非调试版本执行此操作,我建议在Radar上复制此增强请求.


Raf*_*fAl 6

您可以将标准错误输出重定向到文件.以下是将控制台输出重定向到应用程序的Documents文件夹中的文件的方法.当您想要在开发工作室之外测试应用程序时,这非常有用,可以从Mac上拔下.

-(void) redirectNSLogToDocuments {
 NSArray *allPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *documentsDirectory = [allPaths objectAtIndex:0];
 NSString *pathForLog = [documentsDirectory stringByAppendingPathComponent:@"yourFile.txt"];
 freopen([pathForLog cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr);
}
Run Code Online (Sandbox Code Playgroud)

执行此方法后,NSLog生成的所有输出都将转发到指定的文件.要使您保存的文件打开管理器,浏览应用程序的文件并将应用程序数据保存在文件系统中的某个位置,而不是简单地浏览到文档文件夹.