Ce guide explique comment personnaliser vos rapports d'erreur à l'aide du SDK Firebase Crashlytics. Par défaut, Crashlytics collecte automatiquement les rapports d'erreur pour tous les utilisateurs de votre application (vous pouvez désactiver les rapports d'erreur automatiques et activer les rapports d'activation pour vos utilisateurs à la place). Crashlytics fournit quatre mécanismes de journalisation prêts à l'emploi : clés personnalisées , journaux personnalisés , identifiants utilisateur et exceptions interceptées .
Ajouter des clés personnalisées
Les clés personnalisées vous aident à obtenir l'état spécifique de votre application menant à un crash. Vous pouvez associer des paires clé/valeur arbitraires à vos rapports d'erreur, puis utiliser les clés personnalisées pour rechercher et filtrer les rapports d'erreur dans la console Firebase.
- Dans le tableau de bord Crashlytics , vous pouvez rechercher les problèmes correspondant à une clé personnalisée.
- Lorsque vous examinez un problème spécifique dans la console, vous pouvez afficher les clés personnalisées associées à chaque événement (sous-onglet Clés ) et même filtrer les événements par clés personnalisées (menu Filtrer en haut de la page).
Utilisez la méthode setCustomValue
pour définir des paires clé/valeur. Par exemple:
Rapide
// Set int_key to 100. Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key") // Set str_key to "hello". Crashlytics.crashlytics().setCustomValue("hello", forKey: "str_key")
Objectif c
Lorsque vous définissez des entiers, des booléens ou des flottants, encadrez la valeur comme @( value )
.
// Set int_key to 100. [[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"]; // Set str_key to "hello". [[FIRCrashlytics crashlytics] setCustomValue:@"hello" forKey:@"str_key"];
Vous pouvez également modifier la valeur d'une clé existante en appelant la clé et en lui attribuant une valeur différente. Par exemple:
Rapide
Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key") // Set int_key to 50 from 100. Crashlytics.crashlytics().setCustomValue(50, forKey: "int_key")
Objectif c
[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"]; // Set int_key to 50 from 100. [[FIRCrashlytics crashlytics] setCustomValue:@(50) forKey:@"int_key"];
Ajoutez des paires clé/valeur en masse en utilisant la méthode setCustomKeysAndValues
avec un NSDictionary comme seul paramètre :
Rapide
let keysAndValues = [ "string key" : "string value", "string key 2" : "string value 2", "boolean key" : true, "boolean key 2" : false, "float key" : 1.01, "float key 2" : 2.02 ] as [String : Any] Crashlytics.crashlytics().setCustomKeysAndValues(keysAndValues)
Objectif c
NSDictionary *keysAndValues = @{@"string key" : @"string value", @"string key 2" : @"string value 2", @"boolean key" : @(YES), @"boolean key 2" : @(NO), @"float key" : @(1.01), @"float key 2" : @(2.02)}; [[FIRCrashlytics crashlytics] setCustomKeysAndValues: keysAndValues];
Ajouter des messages de journal personnalisés
Pour vous donner plus de contexte sur les événements ayant conduit à un crash, vous pouvez ajouter des journaux Crashlytics personnalisés à votre application. Crashlytics associe les journaux à vos données de crash et les affiche sur la page Crashlytics de la console Firebase , sous l'onglet Journaux .
Rapide
Utilisez log()
ou log(format:, arguments:)
pour vous aider à identifier les problèmes. Si vous souhaitez obtenir une sortie de journal utile avec des messages, l'objet que vous transmettez à log()
doit être conforme à la propriété CustomStringConvertible
. log()
renvoie la propriété de description que vous définissez pour l'objet. Par exemple:
Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")
.log(format:, arguments:)
formate les valeurs renvoyées par l'appel getVaList()
. Par exemple:
Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))
Pour plus de détails sur l'utilisation log()
ou log(format:, arguments:)
, reportez-vous à la documentation de référence Crashlytics .
Objectif c
Utilisez log
ou logWithFormat
pour vous aider à identifier les problèmes. Notez que si vous souhaitez obtenir une sortie de journal utile avec des messages, l'objet que vous transmettez à l'une ou l'autre méthode doit remplacer la propriété d'instance description
. Par exemple:
[[FIRCrashlytics crashlytics] log:@"Simple string message"]; [[FIRCrashlytics crashlytics] logWithFormat:@"Higgs-Boson detected! Bailing out... %@", attributesDict]; [[FIRCrashlytics crashlytics] logWithFormat:@"Logging a variable argument list %@" arguments:va_list_arg];
Pour plus de détails sur l'utilisation log
et logWithFormat
, reportez-vous à la documentation de référence Crashlytics.
Définir les identifiants des utilisateurs
Pour diagnostiquer un problème, il est souvent utile de savoir lequel de vos utilisateurs a rencontré un crash donné. Crashlytics inclut un moyen d'identifier de manière anonyme les utilisateurs dans vos rapports d'erreur.
Pour ajouter des ID utilisateur à vos rapports, attribuez à chaque utilisateur un identifiant unique sous la forme d'un numéro d'identification, d'un jeton ou d'une valeur hachée :
Rapide
Crashlytics.crashlytics().setUserID("123456789")
Objectif c
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
Si jamais vous devez effacer un identifiant utilisateur après l'avoir défini, réinitialisez la valeur sur une chaîne vide. La suppression d'un identifiant utilisateur ne supprime pas les enregistrements Crashlytics existants. Si vous devez supprimer des enregistrements associés à un ID utilisateur, contactez l'assistance Firebase .
Signaler les exceptions non fatales
En plus de signaler automatiquement les plantages de votre application, Crashlytics vous permet d'enregistrer des exceptions non fatales et de vous les envoyer au prochain lancement de votre application.
Vous pouvez enregistrer des exceptions non fatales en enregistrant des objets NSError
avec la méthode recordError
. recordError
capture la pile d'appels du thread en appelant [NSThread callStackReturnAddresses]
.
Rapide
Crashlytics.crashlytics().record(error: error)
Objectif c
[[FIRCrashlytics crashlytics] recordError:error];
Lorsque vous utilisez la méthode recordError
, il est important de comprendre la structure NSError
et comment Crashlytics utilise les données pour regrouper les plantages. Une utilisation incorrecte de la méthode recordError
peut entraîner un comportement imprévisible et amener Crashlytics à limiter le signalement des erreurs enregistrées pour votre application.
Un objet NSError
a trois arguments :
-
domain: String
-
code: Int
-
userInfo: [AnyHashable : Any]? = nil
Contrairement aux plantages fatals, qui sont regroupés via l'analyse de trace de pile, les erreurs enregistrées sont regroupées par domain
et code
. Il s'agit d'une distinction importante entre les accidents mortels et les erreurs enregistrées. Par exemple:
Rapide
let userInfo = [ NSLocalizedDescriptionKey: NSLocalizedString("The request failed.", comment: ""), NSLocalizedFailureReasonErrorKey: NSLocalizedString("The response returned a 404.", comment: ""), NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Does this page exist?", comment: ""), "ProductID": "123456", "View": "MainView" ] let error = NSError.init(domain: NSCocoaErrorDomain, code: -1001, userInfo: userInfo)
Objectif c
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", @"View": @"MainView", }; NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain code:-1001 userInfo:userInfo];
Lorsque vous enregistrez l'erreur ci-dessus, cela crée un nouveau problème regroupé par NSSomeErrorDomain
et -1001
. Les erreurs enregistrées supplémentaires qui utilisent les mêmes valeurs de domaine et de code sont regroupées sous le même problème. Les données contenues dans l'objet userInfo
sont converties en paires clé-valeur et affichées dans la section clés/journaux au sein d'un problème individuel.
Journaux et clés personnalisées
Tout comme les rapports d'erreur, vous pouvez intégrer des journaux et des clés personnalisées pour ajouter du contexte au NSError
. Cependant, il existe une différence entre les journaux associés aux plantages et les erreurs enregistrées. Lorsqu'un crash se produit et que l'application est relancée, les journaux récupérés par Crashlytics sur le disque sont ceux qui ont été écrits jusqu'au moment du crash. Lorsque vous enregistrez une NSError
, l'application ne se termine pas immédiatement. Étant donné que Crashlytics n'envoie le rapport d'erreur enregistré qu'au prochain lancement de l'application et doit limiter la quantité d'espace alloué aux journaux sur le disque, il est possible d'enregistrer suffisamment après l'enregistrement d'une NSError
afin que tous les journaux pertinents soient supprimés au moment où Crashlytics envoie le rapport de l'appareil. Gardez cet équilibre à l’esprit lors de la journalisation NSErrors
et de l’utilisation des journaux et des clés personnalisées dans votre application.
Considérations sur les performances
Gardez à l’esprit que la journalisation d’une NSError
peut être assez coûteuse. Au moment où vous effectuez l'appel, Crashlytics capture la pile d'appels du thread actuel à l'aide d'un processus appelé déroulement de la pile. Ce processus peut être gourmand en CPU et en E/S, en particulier sur les architectures prenant en charge le déroulement DWARF (arm64 et x86). Une fois le déroulement terminé, les informations sont écrites sur le disque de manière synchrone. Cela évite la perte de données si la ligne suivante plante.
Bien qu'il soit sûr d'appeler cette API sur un thread d'arrière-plan, n'oubliez pas que l'envoi de cet appel vers une autre file d'attente perd le contexte de la trace de pile actuelle.
Qu'en est-il des NSExceptions ?
Crashlytics n'offre pas de possibilité de journalisation et d'enregistrement direct des instances NSException
. De manière générale, les API Cocoa et Cocoa Touch ne sont pas à l'abri des exceptions. Cela signifie que l'utilisation de @catch
peut avoir des effets secondaires involontaires très graves dans votre processus, même lorsqu'elle est utilisée avec une extrême prudence. Vous ne devez jamais utiliser d'instructions @catch
dans votre code. Veuillez vous référer à la documentation d'Apple sur le sujet.
Personnaliser les traces de pile
Si votre application s'exécute dans un environnement non natif (tel que C++ ou Unity), vous pouvez utiliser l'API Exception Model pour signaler les métadonnées de plantage dans le format d'exception natif de votre application. Les exceptions signalées sont marquées comme non fatales.
Rapide
var ex = ExceptionModel(name:"FooException", reason:"There was a foo.") ex.stackTrace = [ StackFrame(symbol:"makeError", file:"handler.js", line:495), StackFrame(symbol:"then", file:"routes.js", line:102), StackFrame(symbol:"main", file:"app.js", line:12), ] crashlytics.record(exceptionModel:ex)
Objectif c
FIRExceptionModel *model = [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."]; model.stackTrace = @[ [FIRStackFrame stackFrameWithSymbol:@"makeError" file:@"handler.js" line:495], [FIRStackFrame stackFrameWithSymbol:@"then" file:@"routes.js" line:102], [FIRStackFrame stackFrameWithSymbol:@"main" file:@"app.js" line:12], ]; [[FIRCrashlytics crashlytics] recordExceptionModel:model];
Les cadres de pile personnalisés peuvent également être initialisés avec uniquement des adresses :
Rapide
var ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.") ex.stackTrace = [ StackFrame(address:0xfa12123), StackFrame(address:12412412), StackFrame(address:194129124), ] crashlytics.record(exceptionModel:ex)
Objectif c
FIRExceptionModel *model = [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."]; model.stackTrace = @[ [FIRStackFrame stackFrameWithAddress:0xfa12123], [FIRStackFrame stackFrameWithAddress:12412412], [FIRStackFrame stackFrameWithAddress:194129124], ]; [[FIRCrashlytics crashlytics] recordExceptionModel:model];
Activer les rapports d'adhésion
Par défaut, Crashlytics collecte automatiquement les rapports d'erreur pour tous les utilisateurs de votre application. Pour donner aux utilisateurs plus de contrôle sur les données qu'ils envoient, vous pouvez activer les rapports opt-in en désactivant les rapports automatiques et en envoyant les données à Crashlytics uniquement lorsque vous le souhaitez dans votre code :
Désactivez la collecte automatique en ajoutant une nouvelle clé à votre fichier
Info.plist
:- Clé :
FirebaseCrashlyticsCollectionEnabled
- Valeur :
false
- Clé :
Activez la collecte pour certains utilisateurs en appelant le remplacement de la collecte de données Crashlytics au moment de l'exécution. La valeur de remplacement persiste lors des lancements de votre application afin que Crashlytics puisse collecter automatiquement des rapports.
Pour désactiver le rapport automatique d'incidents, transmettez
false
comme valeur de remplacement. Lorsqu'elle est définie surfalse
, la nouvelle valeur ne s'applique pas jusqu'à la prochaine exécution de l'application.Rapide
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Objectif c
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
Gérer les données Crash Insights
Crash Insights vous aide à résoudre les problèmes en comparant vos traces de pile anonymisées aux traces d'autres applications Firebase et en vous indiquant si votre problème fait partie d'une tendance plus large. Pour de nombreux problèmes, Crash Insights fournit même des ressources pour vous aider à déboguer le crash.
Crash Insights utilise des données d'accident agrégées pour identifier les tendances courantes en matière de stabilité. Si vous préférez ne pas partager les données de votre application, vous pouvez désactiver Crash Insights dans le menu Crash Insights en haut de votre liste de problèmes Crashlytics dans la console Firebase .