Captura de registro de locking de iOS, información de depuración … Captura y envía por correo electrónico al equipo de Dev

Recientemente nos encontramos con una situación en la que queríamos ver la información de depuración de la aplicación que un usuario tiene en su dispositivo. Entonces, lo que estoy buscando es una forma de encontrar el inicio de sesión en el dispositivo, pegarlo como texto en línea en un correo y permitir que el usuario lo envíe.

¿Algunas ideas? Aquí están las preguntas de nuevo … 1) Encuentre un registro de depuración en el dispositivo 2) abra el archivo y adjunte el contenido del archivo como texto en línea al correo. 3) Permitir que el usuario lo envíe por correo electrónico la próxima vez que se inicie la aplicación.

Gracias,

Gracias por todas las aportaciones chicos. Apunté sus soluciones en una que resolvería mi problema. Esto es lo que hice. Seguramente no compilé el código, es un código medio horneado … pero lo haré. plancharlo pronto una vez cuando lo implemente en mi código …

NSLog en el archivo Cómo iniciar NSLog en un archivo LOG2FILE

#if TARGET_IPHONE_SIMULATOR == 0 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"]; freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding],"a+",stderr); #endif 

Catch the Crash y registrarlos también en un archivo

Primero, cree una función que manejará el error y lo enviará a la consola (así como a cualquier otra cosa que quiera hacer con él):

 void uncaughtExceptionHandler(NSException *exception) { NSLog(@"CRASH: %@", exception); NSLog(@"Stack Trace: %@", [exception callStackSymbols]); // Internal error reporting } 

A continuación, agregue el manejador de excepciones al delegado de su aplicación:

 -(BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions: (NSDictionary*)launchOptions { NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); // Normal launch stuff } 

Establezca una variable en info.plist llamada Crashed y luego léala / escríbala de esta manera

 - (void)readPlist { NSString *localizedPath = [[NSBundle mainBundle] pathForResource:fileName ofType:@"plist"]; NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:localizedPath]; NSString *crashed; crashed = [plistDict objectForKey:@"Crashed"]; } - (void)writeToPlist { NSMutableDictionary* plistDict = [[NSMutableDictionary alloc] initWithContentsOfFile:filePath]; [plistDict setValue:@"YES" forKey:@"Crashed"]; [plistDict writeToFile:filePath atomically: YES]; } 

Una vez que se inicia la aplicación, lea el archivo info.plist y solicite al usuario que envíe los registros de locking.

 { MFMailComposeViewController *mailComposer = [[MFMailComposeViewController alloc] init]; mailComposer.mailComposeDelegate = self;[mailComposer setSubject:@"Crash Log"]; // Set up recipients NSArray *toRecipients = [NSArray arrayWithObject:@"first@example.com"]; [mailComposer setToRecipients:toRecipients]; // Attach the Crash Log.. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *documentsDirectory = [paths objectAtIndex:0]; NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console.log"]; NSData *myData = [NSData dataWithContentsOfFile:logPath]; [mailComposer addAttachmentData:myData mimeType:@"Text/XML" fileName:@"Console.log"]; // Fill out the email body text NSString *emailBody = @"Crash Log"; [mailComposer setMessageBody:emailBody isHTML:NO]; [self presentModalViewController:mailComposer animated:YES]; } 
  1. Para registrar sus propios datos, use Cocoalumberjack . Es mucho más rápido que NSLog y se puede activar / desactivar de forma dinámica. También proporciona opciones para guardar los datos en un archivo. NSLog reducirá la velocidad de su aplicación y llena el registro de la consola. Además, no desea registrar demasiado en general. No puede realizar el registro de forma segura cuando ocurre el locking. Entonces, más bien una vez que descubrió dónde está el área problemática, agregue un poco más de registro allí e intente reproducirlo, por ejemplo, utilizando marcos de prueba automatizados como KIF .

  2. Para capturar el informe de fallos, no debe hacer otra cosa que una solución basada en el marco de código abierto PLCrashReporter , que puede detectar lockings de forma segura , ¡incluso cuando su aplicación ya se encuentra en la tienda de aplicaciones! No se recomienda la captura de excepciones sugerida por otros, consulte este artículo para ver por qué.

    iTunes Connect también le permite ver algunos informes de fallos, pero demora hasta 2 semanas para ver algunos, pero de lejos no todos, por ejemplo, lo señalan los desarrolladores de Camera + . Entonces es mejor que uses tu propia solución.

    PLCrashReporter le enviará informes de fallos formateados Apple estándar, listos para la simbolización, para que sepa dónde ocurre el locking en su código, incluidos los números de línea.

    Algunas soluciones basadas en PLCrashReporter son:

    • QuincyKit : cliente de código abierto + servidor php, agrupación básica de fallos , la simbolización se puede automatizar desde su mac (yo soy el desarrollador de esto)
    • HockeyApp : servicio pagado, utiliza el cliente QuincyKit, agrupación avanzada de locking, simbolización completamente realizada en el servidor (soy uno de los desarrolladores de esto)
    • Bugsense : servicio gratuito, sin simbolización
    • AppBlade : servicio GRATUITO si se usa con 25 dispositivos o menos, sin simbolización
    • Crashlytics : beta privada, características desconocidas, su solución parece estar basada en PLCrashReporter
  3. Las soluciones propuestas permiten enviar los datos automáticamente en la próxima puesta en marcha o al preguntar al usuario si acepta enviarlos.

Para el registro y el análisis en Swift puede usar SwiftyBeaver , es una plataforma de registro con todas las funciones que incluye Swift 2 y Objective-C Framework de código abierto, almacenamiento en la nube encriptado y la aplicación Mac.

Sitio web: https://swiftybeaver.com

Marco (de apoyo): https://github.com/SwiftyBeaver/SwiftyBeaver

Descargo de responsabilidad: soy un fundador.

Esta es una solución que detecta lockings a medida que ocurren, le dará más información de código legible que un registro de locking. Le faltará parte del registro de locking, pero como dice Till, debería poder acceder a ellos de todos modos.

De otra pregunta SO sobre el Xcode 4.2 siempre volviendo a la principal al estrellarse. La respuesta allí utiliza este método y puede ampliarlo para realizar un seguimiento de los lockings.

implementa tu propio manejador de excepciones en AppDelegate

 // on load NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler); void uncaughtExceptionHandler(NSException *exception) { NSLog(@"CRASH: %@", exception); NSLog(@"Stack Trace: %@", [exception callStackSymbols]); // Internal error reporting } 

ACTUALIZACIÓN Hice algo de retroceso y esta solución fue ofrecida por Zane Claes a la pregunta: la depuración de Xcode 4.2 no simboliza la llamada a la stack

Él ofrece una solución general en su segundo comentario. “Me parece útil escribir el registro de locking en un archivo y solicitar al usuario que lo envíe en el siguiente lanzamiento (solo en modo de lanzamiento, para no impedir la depuración). Esto me permite obtener excelentes informes de errores. .. y los usuarios saben que su problema está siendo atendido “Entiendo que no todos quisieran preguntarle esto al usuario, pero hay superusuarios que estarían encantados de ayudar.

Por supuesto, podría incluir un mensaje que nunca me muestre este botón nuevamente para que las personas no se sientan frustradas al informar el mecanismo.

Alternativamente, puedes comunicarte con un servidor con la información (no estoy seguro de si funcionará, ya que está fallando, pero guárdalo y ocasionalmente intenta enviarlo a un servidor con los detalles)

He estado usando Crittercism para automatizar esto para mí. Funciona para pruebas y en producción también.

BugSense proporciona servicios de informes de fallas para iOS. Además de proporcionar un seguimiento de stack completamente simbolizado, BugSense proporciona análisis de sus fallas en todas sus aplicaciones.

Creo que es mejor que el correo electrónico, porque cuando su aplicación se vuelva popular, tendrá que administrar todos estos correos electrónicos manualmente, mientras que BugSense hace esto automáticamente. Sin embargo, BugSense también es de código abierto, por lo que puede modificar sus aspectos internos de la forma que desee y agregar cualquier funcionalidad adicional.

Además de eso, nos pones a trabajar para ti de forma gratuita: si tienes una idea sobre una función nueva y atractiva que quieres que tengamos, lo haremos, siempre que consideremos que también es genial.

Descargo de responsabilidad: escribo el código para BugSense-iOS.framework.

Si usa TestFlight con su SDK, esto es automático. Es un sistema realmente bueno. Para comstackciones de prueba solamente, sin embargo.

https://testflightapp.com/sdk/

Consulte la respuesta de Ryan en Cómo ver la statement NSLog del archivo .app de iphone para obtener una utilidad gratuita proporcionada por Apple.

Pero esto todavía no es una solución conveniente. Si puede pagar una nueva comstackción, debe cambiar su registro dentro de la aplicación. Jano tiene algunas ideas muy buenas sobre esto en Cómo iniciar NSLog en un archivo . Especialmente la opción 2 debería funcionar sin demasiado esfuerzo.

En general, recomendaría ocultar las instalaciones de registro nativas detrás de una fachada o un diseño similar justo al comienzo del proyecto, independientemente del lenguaje de progtwigción que se utilice.

He usado el código a continuación para capturar registros de depuración – Swift 4.1

 var paths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) let documentsDirectory = paths[0] let fileName = "Logfile.txt" let logFilePath = (documentsDirectory as NSString).appendingPathComponent(fileName) freopen(logFilePath.cString(using: String.Encoding.ascii)!, "a+", stderr)