Passen Sie Ihre Firebase Crashlytics-Absturzberichte an

In dieser Anleitung wird beschrieben, wie Sie Ihre Absturzberichte mit dem Firebase Crashlytics SDK anpassen. Standardmäßig sammelt Crashlytics automatisch Absturzberichte für alle Benutzer Ihrer App (Sie können die automatischen Absturzberichte deaktivieren und stattdessen die Opt-in-Berichte für Ihre Benutzer aktivieren ). Crashlytics bietet standardmäßig vier Protokollierungsmechanismen: benutzerdefinierte Schlüssel , benutzerdefinierte Protokolle , Benutzerkennungen und abgefangene Ausnahmen .

Fügen Sie benutzerdefinierte Schlüssel hinzu

Benutzerdefinierte Schlüssel helfen Ihnen dabei, den spezifischen Zustand Ihrer App zu ermitteln, der zu einem Absturz geführt hat. Sie können Ihren Absturzberichten beliebige Schlüssel/Wert-Paare zuordnen und dann die benutzerdefinierten Schlüssel verwenden, um Absturzberichte in der Firebase-Konsole zu suchen und zu filtern.

  • Im Crashlytics-Dashboard können Sie nach Problemen suchen, die mit einem benutzerdefinierten Schlüssel übereinstimmen.
  • Wenn Sie ein bestimmtes Problem in der Konsole überprüfen, können Sie die zugehörigen benutzerdefinierten Schlüssel für jedes Ereignis anzeigen (Unterregisterkarte „ Schlüssel “) und die Ereignisse sogar nach benutzerdefinierten Schlüsseln filtern (Menü „ Filter “ oben auf der Seite).

Verwenden Sie die setCustomValue Methode, um Schlüssel/Wert-Paare festzulegen. Beispielsweise:

Schnell

// Set int_key to 100.
Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

// Set str_key to "hello".
Crashlytics.crashlytics().setCustomValue("hello", forKey: "str_key")

Ziel c

Wenn Sie Ganzzahlen, boolesche Werte oder Gleitkommazahlen festlegen, verpacken Sie den Wert als @( 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"];

Sie können den Wert eines vorhandenen Schlüssels auch ändern, indem Sie den Schlüssel aufrufen und auf einen anderen Wert setzen. Beispielsweise:

Schnell

Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key")

// Set int_key to 50 from 100.
Crashlytics.crashlytics().setCustomValue(50, forKey: "int_key")

Ziel c

[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"];

// Set int_key to 50 from 100.
[[FIRCrashlytics crashlytics] setCustomValue:@(50) forKey:@"int_key"];

Fügen Sie Schlüssel/Wert-Paare in großen Mengen hinzu, indem Sie die Methode setCustomKeysAndValues mit einem NSDictionary als einzigem Parameter verwenden:

Schnell

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)

Ziel 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];

Fügen Sie benutzerdefinierte Protokollmeldungen hinzu

Um sich mehr Kontext für die Ereignisse zu verschaffen, die zu einem Absturz geführt haben, können Sie Ihrer App benutzerdefinierte Crashlytics-Protokolle hinzufügen. Crashlytics ordnet die Protokolle Ihren Absturzdaten zu und zeigt sie auf der Crashlytics-Seite der Firebase-Konsole auf der Registerkarte Protokolle an.

Schnell

Verwenden Sie log() oder log(format:, arguments:) , um Probleme zu lokalisieren. Wenn Sie eine nützliche Protokollausgabe mit Meldungen erhalten möchten, muss das Objekt, das Sie an log() übergeben, der CustomStringConvertible Eigenschaft entsprechen. log() gibt die Beschreibungseigenschaft zurück, die Sie für das Objekt definieren. Beispielsweise:

Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")

.log(format:, arguments:) formatiert Werte, die vom Aufruf von getVaList() zurückgegeben werden. Beispielsweise:

Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))

Weitere Einzelheiten zur Verwendung von log() oder log(format:, arguments:) finden Sie in der Crashlytics- Referenzdokumentation .

Ziel c

Verwenden Sie log oder logWithFormat , um Probleme zu lokalisieren. Beachten Sie, dass das Objekt, das Sie an eine der beiden Methoden übergeben, die description überschreiben muss, wenn Sie eine nützliche Protokollausgabe mit Meldungen erhalten möchten. Beispielsweise:

[[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];

Weitere Einzelheiten zur Verwendung von log und logWithFormat finden Sie in der Crashlytics- Referenzdokumentation .

Benutzer-IDs festlegen

Um ein Problem zu diagnostizieren, ist es oft hilfreich zu wissen, bei welchen Ihrer Benutzer ein bestimmter Absturz aufgetreten ist. Crashlytics bietet eine Möglichkeit, Benutzer in Ihren Absturzberichten anonym zu identifizieren.

Um Benutzer-IDs zu Ihren Berichten hinzuzufügen, weisen Sie jedem Benutzer eine eindeutige Kennung in Form einer ID-Nummer, eines Tokens oder eines Hash-Werts zu:

Schnell

Crashlytics.crashlytics().setUserID("123456789")

Ziel c

[[FIRCrashlytics crashlytics] setUserID:@"123456789"];

Wenn Sie jemals eine Benutzerkennung löschen müssen, nachdem Sie sie festgelegt haben, setzen Sie den Wert auf eine leere Zeichenfolge zurück. Durch das Löschen einer Benutzerkennung werden vorhandene Crashlytics-Datensätze nicht entfernt. Wenn Sie mit einer Benutzer-ID verknüpfte Datensätze löschen müssen, wenden Sie sich an den Firebase-Support .

Melden Sie nicht schwerwiegende Ausnahmen

Zusätzlich zum automatischen Melden der Abstürze Ihrer App können Sie mit Crashlytics nicht schwerwiegende Ausnahmen aufzeichnen und Ihnen diese beim nächsten Start Ihrer App zusenden.

Sie können nicht schwerwiegende Ausnahmen aufzeichnen, indem Sie NSError -Objekte mit der recordError Methode aufzeichnen. recordError erfasst die Aufrufliste des Threads durch Aufrufen von [NSThread callStackReturnAddresses] .

Schnell

Crashlytics.crashlytics().record(error: error)

Ziel c

[[FIRCrashlytics crashlytics] recordError:error];

Bei der Verwendung der recordError -Methode ist es wichtig, die NSError Struktur zu verstehen und wie Crashlytics die Daten verwendet, um Abstürze zu gruppieren. Die falsche Verwendung der recordError Methode kann zu unvorhersehbarem Verhalten führen und dazu führen, dass Crashlytics die Berichterstattung über protokollierte Fehler für Ihre App einschränkt.

Ein NSError Objekt hat drei Argumente:

  • domain: String
  • code: Int
  • userInfo: [AnyHashable : Any]? = nil

Im Gegensatz zu schwerwiegenden Abstürzen, die über die Stack-Trace-Analyse gruppiert werden, werden protokollierte Fehler nach domain und code gruppiert. Dies ist eine wichtige Unterscheidung zwischen schwerwiegenden Abstürzen und protokollierten Fehlern. Beispielsweise:

Schnell

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)

Ziel 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];

Wenn Sie den obigen Fehler protokollieren, wird ein neues Problem erstellt, das nach NSSomeErrorDomain und -1001 gruppiert ist. Zusätzliche protokollierte Fehler, die dieselbe Domäne und dieselben Codewerte verwenden, werden unter demselben Problem gruppiert. Die im userInfo -Objekt enthaltenen Daten werden in Schlüssel-Wert-Paare konvertiert und im Abschnitt „Schlüssel/Protokolle“ innerhalb eines einzelnen Problems angezeigt.

Protokolle und benutzerdefinierte Schlüssel

Genau wie bei Absturzberichten können Sie Protokolle und benutzerdefinierte Schlüssel einbetten, um Kontext zu NSError . Es gibt jedoch einen Unterschied darin, welche Protokolle an Abstürze und protokollierte Fehler angehängt werden. Wenn ein Absturz auftritt und die App neu gestartet wird, sind die Protokolle, die Crashlytics von der Festplatte abruft, diejenigen, die bis zum Zeitpunkt des Absturzes geschrieben wurden. Wenn Sie einen NSError , wird die App nicht sofort beendet. Da Crashlytics den protokollierten Fehlerbericht nur beim nächsten App-Start sendet und den für Protokolle auf der Festplatte zugewiesenen Speicherplatz begrenzen muss, ist es möglich, nach der Aufzeichnung eines NSError genügend Protokolle zu erstellen, sodass alle relevanten Protokolle zum Zeitpunkt des Sendens durch Crashlytics rotiert werden der Bericht vom Gerät. Denken Sie an dieses Gleichgewicht, wenn NSErrors protokollieren und Protokolle und benutzerdefinierte Schlüssel in Ihrer App verwenden.

Leistungsüberlegungen

Denken Sie daran, dass das Protokollieren eines NSError ziemlich teuer sein kann. Zum Zeitpunkt des Aufrufs erfasst Crashlytics den Call-Stack des aktuellen Threads mithilfe eines Prozesses namens Stack Unwinding. Dieser Prozess kann CPU- und I/O-intensiv sein, insbesondere auf Architekturen, die DWARF-Unwinding unterstützen (arm64 und x86). Nachdem das Entladen abgeschlossen ist, werden die Informationen synchron auf die Festplatte geschrieben. Dies verhindert einen Datenverlust, falls die nächste Zeile abstürzen sollte.

Obwohl es sicher ist, diese API in einem Hintergrund-Thread aufzurufen, denken Sie daran, dass durch das Weiterleiten dieses Aufrufs an eine andere Warteschlange der Kontext des aktuellen Stack-Trace verloren geht.

Was ist mit NSExceptions?

Crashlytics bietet keine Möglichkeit, NSException Instanzen direkt zu protokollieren und aufzuzeichnen. Im Allgemeinen sind die Cocoa- und Cocoa Touch-APIs nicht ausnahmesicher. Das bedeutet, dass die Verwendung von @catch selbst bei äußerst vorsichtiger Verwendung sehr schwerwiegende unbeabsichtigte Nebenwirkungen in Ihrem Prozess haben kann. Sie sollten niemals @catch Anweisungen in Ihrem Code verwenden. Bitte lesen Sie die Dokumentation von Apple zu diesem Thema.

Stack-Traces anpassen

Wenn Ihre App in einer nicht nativen Umgebung (z. B. C++ oder Unity) ausgeführt wird, können Sie die Ausnahmemodell-API verwenden, um Absturzmetadaten im nativen Ausnahmeformat Ihrer App zu melden. Gemeldete Ausnahmen werden als nicht tödlich gekennzeichnet.

Schnell

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)

Ziel 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];

Benutzerdefinierte Stapelrahmen können auch nur mit Adressen initialisiert werden:

Schnell

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)

Ziel 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];

Opt-in-Berichterstellung aktivieren

Standardmäßig sammelt Crashlytics automatisch Absturzberichte für alle Benutzer Ihrer App. Um Benutzern mehr Kontrolle über die von ihnen gesendeten Daten zu geben, können Sie die Opt-in-Berichterstellung aktivieren, indem Sie die automatische Berichterstellung deaktivieren und nur dann Daten an Crashlytics senden, wenn Sie dies in Ihrem Code wünschen:

  1. Deaktivieren Sie die automatische Erfassung, indem Sie Ihrer Info.plist -Datei einen neuen Schlüssel hinzufügen:

    • Schlüssel: FirebaseCrashlyticsCollectionEnabled
    • Wert: false
  2. Aktivieren Sie die Erfassung für ausgewählte Benutzer, indem Sie zur Laufzeit die Außerkraftsetzung der Crashlytics-Datenerfassung aufrufen. Der Überschreibungswert bleibt beim Start Ihrer App bestehen, sodass Crashlytics automatisch Berichte sammeln kann.

    Um die automatische Absturzmeldung zu deaktivieren, übergeben Sie als Überschreibungswert false . Bei Festlegung auf false gilt der neue Wert erst bei der nächsten Ausführung der App.

    Schnell

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Ziel c

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Crash Insights-Daten verwalten

Crash Insights hilft Ihnen bei der Lösung von Problemen, indem es Ihre anonymisierten Stack-Traces mit Traces aus anderen Firebase-Apps vergleicht und Sie darüber informiert, ob Ihr Problem Teil eines größeren Trends ist. Bei vielen Problemen stellt Crash Insights sogar Ressourcen bereit, die Ihnen beim Debuggen des Absturzes helfen.

Crash Insights verwendet aggregierte Absturzdaten, um allgemeine Stabilitätstrends zu identifizieren. Wenn Sie die Daten Ihrer App lieber nicht teilen möchten, können Sie Crash Insights über das Crash Insights -Menü oben in Ihrer Crashlytics-Problemliste in der Firebase-Konsole deaktivieren.