Как перенаправить все ошибки, в том числе неотображаемые исключения, вызовы NSLog и другие журналы, в файл журнала в Mac OS X?
Я пытаюсь найти структуру ведения журнала для приложения Cocoa, написанного в ObjC.
Что я пытался сделать до сих пор:
- Используйте NSLog, но затем понимайте, что его очень сложно настроить и перенаправить. Я полагаю, я мог взломать его и написать макрос, который получает информацию, которую я хочу, например, идентификатор потока, текущую функцию, текущую строку, текущий файл, текущее время, сообщение и т.д., А затем использует NSLog, однако...
- NSLog в конечном счете использует NSLogv, который в конечном счете использует asl, поэтому я подумал "фантастически", я попробовал использовать asl вместо этого с клиентом и контекстом по умолчанию (если бы я делал это правильно, мне пришлось бы создать новый клиент для каждого потока), однако, если я не создаю макрос, это также очень многословно, и я заметил, что журналы, отправленные через asl, получили широковещательную широковещательную систему, тогда как NSLog только регистрировался в stderr, и я хочу, чтобы они оба переходили к одному и тому же войти!
- Затем я заметил, что ошибки отформатированы по-другому (разные datestamp и т.д.), поэтому теперь есть третий контекст ведения журнала.
Какую настройку фреймворка lging можно использовать для того, чтобы ВСЕ сообщения регистрировались в этой структуре удобным образом, чтобы при возникновении проблемы с приложением разработчик мог получить файлы журнала и выяснить, что пошло не так?
Я не хочу просто перенаправлять stderr, я хочу иметь структурированный вывод журнала, содержащий все журналы. Я не хочу, чтобы некоторые журналы поступали на стандартный вывод, я не хочу, чтобы какие-либо журналы отправлялись в syslogd, я просто хочу, чтобы все журналы записывались в один файл, что надежно идентифицирует всю соответствующую информацию об этом сообщении журнала (например, идентификатор потока, сообщение, функция, называемая регистратором, и т.д.), в формате, который легко просматривать и визуализировать.
Я хочу перенаправить все текущие журналы в новый пункт назначения.
Есть ли у кого-нибудь предложения?
EDIT:
Фактически, то, что я хочу сделать, в терминах ObjC:
- Сделайте "метод swizzling" в функции NSLog. Это возможно? Возможно ли (повторно) настроить использование системного регистратора Apple для переопределения любой предыдущей конфигурации службы в одном приложении?
- Определите все места, где я должен поймать необработанные исключения. Это включает, но, возможно, не ограничивается: Необработанными Cocoa Исключениями. Необработанные исключения ObjC. Необработанные исключения С++. Сигналы Unix.
- Поймать и зарегистрировать стек для ошибок, например, поднятых CoreGraphics. (Те, которые просто регистрируют сообщение "Добавить точку останова с помощью вашего отладчика!!!" ).
Ответы
Ответ 1
Вы можете перехватить сообщения NSLog()
(но не ASL в целом) с помощью _NSSetLogCStringFunction()
. Его документированный здесь для WebObjects 4 для Windows, но он существует и в текущих выпусках для Mac OS и iOS. Тем не менее, это частная функция, которая может исчезнуть в любое время, поэтому вы не должны полагаться на нее в выпущенном коде.
Если вы хотите быть в состоянии безопасно сделать это для не-отладочных сборников, я предлагаю дублировать этот запрос расширения на Радар.
Ответ 2
Вы можете использовать функцию 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);
Для NSLog
вы можете использовать макрос, чтобы переопределить его:)
#define NSLog(...) CustomLogger(__VA_ARGS__);
Ответ 3
Вы можете перенаправить стандартный вывод ошибки в файл. Вот метод, который перенаправляет вывод консоли в файл в папке Documents 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);
}
После выполнения этого метода весь вывод, сгенерированный NSLog, будет перенаправлен в указанный файл. Чтобы открыть сохраненный файл, откройте "Органайзер", просмотрите файлы приложений и сохраните данные приложения где-нибудь в вашей файловой системе, а не просто перейдите в папку "Документы".