2010-12-02 3 views
15

Estoy intentando encontrar un marco de registro para una aplicación Cocoa, escrito en ObjC.¿Cómo puedo redirigir todos los errores, incluidas las excepciones no detectadas, las llamadas NSLog y otros registros, a un archivo de registro en Mac OS X?

Lo he intentado hasta ahora:

  1. Uso NSLog, pero luego se dan cuenta de que es muy difícil de configurar y redirigir. Supongo que podría hackearlo y escribir una macro que obtenga la información que deseo, como ID de hilo, función actual, línea actual, archivo actual, hora actual, el mensaje, etcétera, y luego use NSLog, sin embargo ...
  2. NSLog finalmente usa NSLogv, que finalmente usa asl, así que pensé "fantástico", intenté usar asl en su lugar, con el cliente y el contexto predeterminados (si lo hacía correctamente, tendría que crear un nuevo cliente para cada uno) thread), sin embargo, a menos que yo cree una macro, esto también es muy detallado, y noté que los registros enviados vía asl se transmitieron a todo el sistema, mientras que NSLog solo se conectó a stderr, ¡y quiero que ambos vayan al mismo registro!
  3. Me di cuenta de que los errores están formateados de una manera diferente (diferente fecha, etc.), por lo que ahora hay un tercer contexto de registro.

Qué l configuración marco de registro puedo usar para tener TODOS los mensajes registrados a través de ese marco de una manera conveniente de manera que si hay un problema con una aplicación, un desarrollador puede obtener los archivos de registro y averiguar lo que salió ¿incorrecto?

No quiero simplemente redirigir stderr, quiero tener una salida de registro estructurado que contenga todos los registros. No quiero que algunos registros vayan al resultado estándar, no quiero que se registren registros en un syslogd, solo quiero que todos los registros se escriban en un único archivo, que identifique de forma confiable toda la información pertinente sobre ese mensaje de registro (como ID de hilo, mensaje, la función que llamó al registrador, etcétera), en un formato que es fácil de ver y visualizar.

Lo que quiero es redirigir todos los registros actuales al nuevo destino.

¿Alguien tiene alguna sugerencia?

EDIT:

Efectivamente, lo que quiero hacer, en términos ObjC es:

  1. Do "método swizzling" en la función NSLog. es posible? ¿Es posible (re) configurar el uso del Apple System Logger para anular cualquier configuración previa del servicio dentro de la misma aplicación?
  2. Determine todos los lugares donde tengo que atrapar excepciones no controladas. Esto incluye, pero posiblemente no se limita a: Excepciones de cacao no manejado. Excepciones ObjC no controladas. Excepciones de C++ no controladas. Señales Unix.
  3. Capture y registre la pila para detectar errores como los planteados por CoreGraphics. (Los que simplemente registran un mensaje diciendo "¡Agregue un punto de interrupción usando su depurador!").

Respuesta

9

Puede interceptar mensajes NSLog() (pero no ASL en general) usando _NSSetLogCStringFunction(). Está documentado here para WebObjects 4 para Windows, pero también existe en las versiones actuales de Mac OS e iOS. Sin embargo, es una función privada que puede desaparecer en cualquier momento, por lo que no debes confiar en ella en el código publicado.

Si desea poder hacer esto de forma segura para compilaciones sin errores, sugiero que se duplique this enhancement request en Radar.

+0

Gah, odio este tipo de respuesta, pero si así es, ¡así es! ¡Gracias por eso! – Arafangion

9

Puede utilizar la función Fundación NSSetUncaughtExceptionHandler para establecer una función de devolución de llamada que se encargará de todas las excepciones no capturadas:

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

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

NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); 

Para NSLog, puede utilizar una macro para anularlo :)

#define NSLog(...) CustomLogger(__VA_ARGS__); 
+0

Gracias por el uncaughtExceptionHandler, sin embargo, sigo viendo registros que aparentemente usan asl en algún momento. ¿Cómo puedo redirigir esos, incluidos los enviados a través de un NSLog ordinario? – Arafangion

+0

@Arafangion Bueno, como puede ver, utilizo una macro para decirle al preprocesador que sustituya todas las ocurrencias de 'NSLog' con' CustomLogger', que es donde debería estar haciendo todo el trabajo pesado. –

+0

Eso está bien para el código y las bibliotecas que has escrito, pero ¿y otras bibliotecas? Por ejemplo, la línea siguiente nunca aparece en mis registros, pero aparece en gdb: Jue 2 Dic 17:21:12 mymachine myproject [16215] : kCGErrorIllegalArgument: _CGSFindSharedWindow: WID -1 – Arafangion

6

Puede redirigir la salida de error estándar a un archivo. Este es el método que redirige la salida de la consola a un archivo en la carpeta Documentos de la aplicación. Esto puede ser útil cuando quiera probar su aplicación fuera de su estudio de desarrollo, desenchufada de su 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); 
} 

Después de ejecutar este método, todos los resultados generados por NSLog se reenviarán al archivo especificado. Para que su archivo guardado abra Organizador, explore los archivos de la aplicación y guarde los Datos de la Aplicación en algún lugar de su sistema de archivos, que simplemente vaya a la carpeta Documentos.

+0

¡Este método funcionó muy bien! Usé iExplorer para leer el documento. Aquí hay un enlace de descarga para Mac: http://download.cnet.com/iExplorer/3000-2141_4-10968991.html – funroll

+0

no funciona para mí – Injectios

Cuestiones relacionadas