Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I redirect all errors, including uncaught exceptions, NSLog calls, and other logs, to a log file on Mac OS X?

I am attempting to find a logging framework for a Cocoa application, written in ObjC.

What I've attempted so far:

  1. Use NSLog, but then realise that it is very hard to configure and redirect. I suppose I could hack it and write a macro that obtains the information I want, such as thread ID, current function, current line, current file, current time, the message, etcetera, and then uses NSLog, however...
  2. NSLog ultimately uses NSLogv, which ultimately uses asl, so I thought "fantastic", I tried using asl instead, with the default client and context (If I was doing this properly, I would've had to create a new client for each thread), however, unless I create a macro, this is also very verbose, and I noticed that the logs sent via asl got broadcast system wide, whereas NSLog only logged to stderr, and I want them to both go to the same log!
  3. I then noticed that errors, are formatted in a different way (different datestamp, etc), so there is now a third logging context.

What l logging framework setup can I use to have ALL messages logged through that framework in a convenient fashion so that if there is a problem with an application, a developer can get the log files, and figure out what went wrong?

I don't want to simply redirect stderr, I want to have a structured log output that contains all of the logs. I don't want some logs going to standard output, I don't want any logs sent to a syslogd, I just want all the logs written to a single file, that reliably identifies all the pertinent information about that log message (such as thread ID, message, the function that called the logger, etcetera), in format that is easy to view and visualise.

What I want is to redirect all current logs to the new destination.

Does anyone have any suggestions?

EDIT:

Effectively, what I want to do, in ObjC terms is:

  1. Do "method swizzling" on the NSLog function. Is this possible? Is it possible to (re)configure the use of the Apple System Logger to override any prior configuration of the service within the same application?
  2. Determine all the places where I have to catch unhandled exceptions. THis includes, but possibly isn't limited to: Unhandled Cocoa Exceptions. Unhandled ObjC exceptions. Unhandled C++ exceptions. Unix Signals.
  3. Catch and log the stack for errors such as those raised by CoreGraphics. (The ones that simply log a message saying "Add a breakpoint using your debugger!!!").
like image 242
Arafangion Avatar asked Dec 02 '10 05:12

Arafangion


2 Answers

You can intercept NSLog() messages (but not ASL in general) using _NSSetLogCStringFunction(). It’s documented here for WebObjects 4 for Windows, but it exists in current Mac OS and iOS releases too. However, it’s a private function that may go away at any time, so you shouldn’t rely on it in released code.

If you want to be able to safely do this for non-debug builds, I suggest duplicating this enhancement request on Radar.

like image 106
Jens Ayton Avatar answered Oct 05 '22 22:10

Jens Ayton


You can use the Foundation function NSSetUncaughtExceptionHandler to set a callback function that will handle all uncaught exceptions:

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

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

NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);

For NSLog, you can use a macro to override it :)

#define NSLog(...) CustomLogger(__VA_ARGS__);
like image 20
Jacob Relkin Avatar answered Oct 06 '22 00:10

Jacob Relkin