Ir a la consola

Personaliza los informes de fallas de Firebase Crashlytics

Firebase Crashlytics puede funcionar con una configuración mínima de tu parte. Apenas agregas el SDK, Crashlytics comienza a enviar informes de fallas a Firebase console.

Para brindarte más estadísticas sobre los informes de fallas, Firebase Crashlytics incluye cuatro mecanismos de registro desde el primer momento: claves personalizadas, registros personalizados, identificadores de usuarios y excepciones capturadas.

Agrega claves personalizadas

Las claves personalizadas te ayudan a obtener el estado específico de la app hasta el momento de la falla. Puedes asociar pares clave-valor arbitrarios con tus informes de fallas y verlos en Firebase console.

Comienza con [CrashlyticsKit setObjectValue:forKey:] o uno de los métodos relacionados:

- (void)setObjectValue:(id)value forKey:(NSString *)key;

// calls -description on value, perfect for NSStrings!
- (void)setIntValue:(int)value forKey:(NSString *)key;

- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;

- (void)setFloatValue:(float)value forKey:(NSString *)key;

En algunos casos, debes cambiar el valor de clave existente. Llama a la misma clave, pero reemplaza el valor. Por ejemplo:

Objective-C
[CrashlyticsKit setIntValue:3 forKey:@"current_level"];
[CrashlyticsKit setObjectValue:@"logged_in" forKey:@"last_UI_action"];
Swift
Crashlytics.sharedInstance().setIntValue(42, forKey: "MeaningOfLife")
Crashlytics.sharedInstance().setObjectValue("Test value", forKey: "last_UI_action")

Agrega mensajes de registro personalizados

Para darte más contexto sobre los eventos que se produjeron antes de una falla, puedes agregar registros personalizados de Crashlytics a la app. Crashlytics asocia los registros con los datos de fallas y los hace visibles en Firebase console.

Objective-C

En Objective-C, usa CLS_LOG para detectar problemas. Automáticamente, incluye información sobre la clase de Objective-C, el método y el número de línea asociado con el registro.

El comportamiento de CLS_LOG cambia si el registro es de una compilación de depuración o de actualización:

  • Compilaciones de depuración: CLS_LOG pasa por NSLog para que puedas ver el resultado en Xcode y en el dispositivo o simulador.
  • Compilaciones de actualización: Para mejorar el rendimiento, CLS_LOG silencia todos los demás resultados y no pasa por NSLog.

Usa CLS_LOG(format, ...) para registrar con CLS_LOG. Por ejemplo:

CLS_LOG(@"Higgs-Boson detected! Bailing out... %@", attributesDict);

Examina el archivo de encabezado Crashlytics/Crashlytics.h para ver más detalles sobre cómo usar CLS_LOG.

Swift

En Swift, usa CLSLogv o CLSNSLogv para detectar problemas.

Hay dos aspectos que debes considerar cuando generes registros con CLSLogv y CLSNSLogv:

  • Tu argumento de formato debe ser una string constante de tiempo de compilación. El compilador aplica esto en Objective-C, pero actualmente esa protección no se encuentra disponible en la transición a Swift.
  • Almacena los valores del registro en un arreglo y llama a getVaList en ese arreglo para recuperarlos.

Por ejemplo:

func write(string: String) {
    CLSLogv("%@", getVaList([string]))
}
La interpolación de strings de Swift no dará como resultado una string constante de tiempo de compilación. De la misma manera que con printf y NSLog, usar una string no constante con CLSLog puede dar como resultado una falla.

Opciones avanzadas

Para obtener más control, puedes aprovechar CLSLog(format, ...) y CLSNSLog(format, ...) directamente. Este último pasa por NSLog y te permite ver el resultado en Xcode o en el dispositivo o simulador. CLSLog(format, ...) y CLSNSLog(format, ...) son seguros para los subprocesos. CLSLog está diseñado para registrar información importante a fin de solucionar fallas. No se debe usar para seguir eventos en la app.

Configura identificadores de usuarios

Para diagnosticar un problema, resulta útil saber cuáles de tus usuarios sufrieron una falla. Crashlytics incluye una manera de identificar usuarios de forma anónima en tus informes de fallas.

Para agregar los ID de usuario a tus informes, asigna a cada usuario un identificador único con el formato de un número de ID, un token o un valor con hash:

Objective-C
[CrashlyticsKit setUserIdentifier:@"123456789"];
Swift
Crashlytics.sharedInstance().setUserIdentifier("123456789")

Si en algún momento necesitas borrar un identificador de usuario después de configurarlo, restablece el valor a una string en blanco. Borrar un identificador de usuario no quita los registros de Crashlytics existentes. Si necesitas borrar los registros asociados con un ID de usuario, comunícate con el equipo de Asistencia de Firebase.

Registra excepciones no fatales

Además de informar las fallas de tu app automáticamente, Crashlytics te permite registrar excepciones no fatales.

Para hacer esto en iOS, debes registrar objetos NSError, que Crashlytics informa y agrupa de la misma manera que las fallas:

Objective-C
[CrashlyticsKit recordError:error];
Swift
Crashlytics.sharedInstance().recordError(error)

Cuando usas el método recordError, es importante comprender la estructura de NSError y la manera en que Crashlytics usa los datos para agrupar las fallas. El uso incorrecto del método recordError puede provocar un comportamiento impredecible y es posible que Crashlytics deba limitar la creación de informes de errores registrados en la app.

Un objeto NSError tiene tres argumentos: domain: String, code: Int y userInfo: [AnyHashable : Any]? = nil.

A diferencia de las fallas fatales, que se agrupan mediante el análisis de seguimiento de pila, los errores registrados se agrupan por domain y code de NSError. Esta es una distinción importante entre las fallas fatales y los errores registrados. Por ejemplo, registrar un error como el siguiente:

NSDictionary *userInfo = @{
    NSLocalizedDescriptionKey: NSLocalizedString(@"The request failed.", nil),
    NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The response returned a 404.", nil),
    NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Does this page exist?", nil),
    ProductID: @"123456";
    UserID: @"Jane Smith"
};

NSError *error = [NSError domain:NSSomeErrorDomain
                          code:-1001
                          userInfo:userInfo];

Crea un problema nuevo y se agrupa por NSSomeErrorDomain y -1001. Los errores registrados adicionales que tengan los mismos valores de dominio y código se agruparán bajo este problema.

Evita usar valores únicos, como ID de usuario, ID de producto y marcas de tiempo en los campos de dominio y código. El uso de valores únicos en estos campos provoca una gran cardinalidad de problemas y es posible que Crashlytics necesite limitar la generación de informes de errores registrados en la app. En su lugar, se deben agregar valores únicos al objeto de diccionario userInfo.

Los datos incluidos en el objeto userInfo se convierten en pares clave-valor y se muestran en la sección claves/registros dentro de un problema individual.

Crashlytics solo almacena las 8 excepciones más recientes en la sesión de una app determinada. Si tu app arroja más de 8 excepciones en una sesión, se perderán las excepciones más antiguas.

Registros y claves personalizadas

Al igual que los informes de fallas, puedes incorporar registros y claves personalizadas para agregar contexto a NSError. Sin embargo, existe una diferencia entre los registros que se adjuntan a las fallas y los errores registrados. Cuando ocurre una falla y la app se reinicia, los registros que Crashlytics recupera del disco son aquellos que se escribieron hasta el momento en que se produjo la falla. Cuando registras un NSError, la app no se finaliza de inmediato. Dado que Crashlytics solo envía el informe del error registrado en el siguiente inicio de la app, y dado que Crashlytics debe limitar la cantidad de espacio asignada a los registros en el disco, es posible registrar lo suficiente antes de que un NSError se registre, de forma que todos los registros importantes rotan antes de que Crashlytics envíe el informe desde el dispositivo. Ten en cuenta este equilibrio cuando registres NSErrors y uses CLSLog y claves personalizadas en tu app.

Consideraciones de rendimiento

Ten en cuenta que registrar un NSError puede ser bastante costoso. Cuando haces la llamada, Crashlytics captura la pila de llamadas del subproceso actual con un proceso llamado "liberación de pila". Este proceso puede consumir una gran cantidad de recursos de CPU y E/S, en particular en arquitecturas que admiten la liberación de DWARF (arm64 y x86). Cuando se completa la liberación, la información se escribe en el disco de manera síncrona. Esto evita perder los datos si se produce una falla en la línea siguiente.

Si bien es seguro llamar a esta API en un subproceso en segundo plano, recuerda que si despachas esta llamada a otra fila se perderá el contexto del seguimiento de pila actual.

¿Qué ocurre con NSExceptions?

Crashlytics no ofrece una instalación para el registro de instancias de NSException directamente. En términos generales, las API de Cocoa y Cocoa Touch no cuentan con seguridad para las excepciones. Esto significa que el uso de @catch puede tener efectos secundarios inesperados muy graves en tu proceso, incluso cuando se usa con un cuidado extremo. Nunca deberías usar declaraciones de @catch en tu código. Consulta la documentación de Apple sobre este tema.

Habilita los informes de aceptación

Según la configuración predeterminada, Firebase Crashlytics recopila informes de fallas de todos los usuarios de tu app automáticamente. Para dar a los usuarios más control sobre los datos que envían, puedes habilitar los informes de aceptación en su lugar.

Con este fin, debes inhabilitar la recopilación automática y, luego, inicializar Crashlytics solo para los usuarios que aceptaron.

  1. Agrega una clave nueva al archivo Info.plist para desactivar la recopilación automática, como se indica a continuación:
    • Clave: firebase_crashlytics_collection_enabled
    • Valor: false
  2. Habilita la recopilación para los usuarios seleccionados mediante la inicialización de Crashlytics en el tiempo de ejecución:
    Objective-C
    [Fabric with:@[[Crashlytics class]]];
    Swift
    Fabric.with([Crashlytics.self])

Administra los datos de Crash Insights

Crash Insights te ayuda a resolver problemas a través de la comparación de tus seguimientos de pila anonimizados con seguimientos de otras apps de Firebase y te permite saber si tu problema es parte de una tendencia mayor. En muchos casos, Crash Insights incluso proporciona recursos para ayudarte a depurar el error.

Crash Insights usa datos de errores globales para identificar las tendencias de estabilidad comunes. Si prefieres no compartir los datos de la app, puedes inhabilitar esta función en el menú Crash Insights ubicado en la parte superior de la lista de problemas de Crashlytics de Firebase console.