Firebase Crashlytics-Absturzberichte anpassen


Im Dashboard Crashlytics können Sie auf ein Problem klicken, um einen detaillierten Ereignisbericht aufzurufen. Sie können diese Berichte anpassen, um besser nachvollziehen zu können, was in Ihrer App passiert und welche Umstände zu den bei Crashlytics gemeldeten Ereignissen geführt haben.

  • Sie erhalten automatisch Brotkrummenprotokolle, wenn in Ihrer App das Firebase SDK für Google Analytics verwendet wird. Diese Logs geben Aufschluss über Nutzeraktionen, die zu einem von Crashlytics erfassten Ereignis in Ihrer App geführt haben.

  • Deaktivieren Sie die automatische Absturzberichterstattung und aktivieren Sie die Meldefunktion für Ihre Nutzer. Standardmäßig werden mit Crashlytics automatisch Absturzberichte für alle Nutzer Ihrer App erfasst.

Benutzerdefinierte Schlüssel hinzufügen

Mit benutzerdefinierten Schlüsseln können Sie den spezifischen Status Ihrer App abrufen, der zu einem Absturz führte. Sie können Ihren Absturzberichten beliebige Schlüssel/Wert-Paare zuordnen und dann mithilfe der benutzerdefinierten Schlüssel Absturzberichte in der Firebase-Konsole suchen und filtern.

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

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

Swift

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

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

Objective-C

Wenn Sie Ganzzahlen, Boolesche Werte oder Gleitkommazahlen festlegen, geben Sie den Wert als @(value) ein.

// 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 auch den Wert eines vorhandenen Schlüssels ändern, indem Sie den Schlüssel aufrufen und einen anderen Wert festlegen. Beispiel:

Swift

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

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

Objective-C

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

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

Wenn Sie mehrere Schlüssel/Wert-Paare gleichzeitig hinzufügen möchten, verwenden Sie die Methode setCustomKeysAndValues mit einer NSDictionary als einzigem Parameter:

Swift

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)

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

Benutzerdefinierte Protokollmeldungen hinzufügen

Wenn Sie mehr Kontext zu den Ereignissen erhalten möchten, die zu einem Absturz geführt haben, können Sie Ihrer App benutzerdefinierte Crashlytics-Protokolle hinzufügen. Crashlytics verknüpft die Protokolle mit Ihren Absturzdaten und zeigt sie auf der Crashlytics-Seite der Firebase-Konsole auf dem Tab Protokolle an.

Swift

Mit log() oder log(format:, arguments:) können Sie Probleme leichter eingrenzen. Wenn Sie eine nützliche Protokollausgabe mit Nachrichten erhalten möchten, muss das Objekt, das Sie an log() übergeben, der Eigenschaft CustomStringConvertible entsprechen. log() gibt die Beschreibungseigenschaft zurück, die Sie für das Objekt definieren. Beispiel:

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

.log(format:, arguments:) formatiert Werte, die durch den Aufruf von getVaList() zurückgegeben werden. Beispiel:

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

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

Objective-C

Mit log oder logWithFormat können Sie Probleme leichter eingrenzen. Wenn Sie eine nützliche Protokollausgabe mit Meldungen erhalten möchten, muss das Objekt, das Sie an eine der beiden Methoden übergeben, das Instanzattribut description überschreiben. Beispiel:

[[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 Informationen zur Verwendung von log und logWithFormat finden Sie in der Referenzdokumentation zu Crashlytics.

Nutzerkennungen festlegen

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

Wenn Sie Ihren Berichten User-IDs hinzufügen möchten, weisen Sie jedem Nutzer eine eindeutige Kennung in Form einer ID-Nummer, eines Tokens oder eines Hashwerts zu:

Swift

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

Objective-C

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

Wenn Sie eine Nutzer-ID nach dem Festlegen löschen möchten, setzen Sie den Wert auf einen leeren String zurück. Durch das Löschen einer Nutzer-ID werden vorhandene Crashlytics-Einträge nicht entfernt. Wenn Sie Einträge löschen möchten, die mit einer Nutzer-ID verknüpft sind, wenden Sie sich an den Firebase-Support.

Nicht schwerwiegende Ausnahmen melden

Mit Crashlytics können Sie nicht schwerwiegende Ausnahmen nicht nur automatisch melden, sondern auch bei der nächsten Ausführung Ihrer App an Sie senden.

Sie können nicht fatale Ausnahmen erfassen, indem Sie NSError-Objekte mit der Methode recordError erfassen. recordError erfasst den Aufrufstack des Threads durch Aufrufen von [NSThread callStackReturnAddresses].

Swift

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

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Wenn Sie die recordError-Methode verwenden, ist es wichtig, die NSError-Struktur zu kennen und zu verstehen, wie Crashlytics die Daten zum Gruppieren von Abstürzen verwendet. Eine falsche Verwendung der recordError-Methode kann zu unvorhersehbarem Verhalten führen und dazu, dass Crashlytics die Meldung von protokollierten Fehlern für Ihre App einschränkt.

Ein NSError-Objekt hat drei Argumente:

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

Im Gegensatz zu fatalen Abstürzen, die über die Stack-Trace-Analyse gruppiert werden, werden protokollierte Fehler nach domain und code gruppiert. Dies ist ein wichtiger Unterschied zwischen schwerwiegenden Abstürzen und protokollierten Fehlern. Beispiel:

Swift

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)

Objective-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 oben genannten Fehler erfassen, wird ein neues Problem erstellt, das nach NSSomeErrorDomain und -1001 gruppiert wird. Zusätzliche protokollierte Fehler mit denselben Domain- und Codewerten werden unter demselben Problem zusammengefasst. Die Daten im userInfo-Objekt werden in Schlüssel/Wert-Paare umgewandelt und im Abschnitt „Schlüssel/Protokolle“ einer einzelnen Anfrage angezeigt.

Protokolle und benutzerdefinierte Schlüssel

Wie bei Absturzberichten können Sie Protokolle und benutzerdefinierte Schlüssel einbetten, um dem NSError Kontext hinzuzufügen. Es gibt jedoch einen Unterschied zwischen den Protokollen, die mit Abstürzen und protokollierten Fehlern verknüpft sind. Wenn ein Absturz auftritt und die App neu gestartet wird, sind die Protokolle, die Crashlytics vom Laufwerk abruft, die, die bis zum Absturz geschrieben wurden. Wenn Sie einen NSError erfassen, wird die App nicht sofort beendet. Da Crashlytics den protokollierten Fehlerbericht erst beim nächsten Starten der App sendet und der Speicherplatz für Protokolle auf dem Laufwerk begrenzt werden muss, ist es möglich, nach der Aufzeichnung eines NSError genügend Protokolle zu erfassen, damit alle relevanten Protokolle ausgetauscht werden, bis Crashlytics den Bericht vom Gerät sendet. Berücksichtigen Sie dieses Gleichgewicht, wenn Sie NSErrors protokollieren und Protokolle und benutzerdefinierte Schlüssel in Ihrer App verwenden.

Hinweise zur Leistung

Beachten Sie, dass die Anmeldung für eine NSError recht teuer sein kann. Wenn Sie den Aufruf starten, erfasst Crashlytics den Aufrufstapel des aktuellen Threads mit einem Prozess, der als Stack-Entschachtelung bezeichnet wird. Dieser Vorgang kann CPU- und I/O-intensiv sein, insbesondere auf Architekturen, die DWARF-Entschachtelung unterstützen (arm64 und x86). Nach Abschluss des Aufwickelns werden die Informationen synchron auf die Festplatte geschrieben. So werden Datenverluste verhindert, falls die nächste Zeile abstürzt.

Es ist zwar sicher, diese API in einem Hintergrund-Thread aufzurufen, aber wenn dieser Aufruf an eine andere Warteschlange gesendet wird, geht der Kontext des aktuellen Stack-Traces verloren.

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ßerster Vorsicht sehr schwerwiegende unbeabsichtigte Nebenwirkungen auf Ihren Prozess haben kann. Sie sollten niemals @catch-Anweisungen in Ihrem Code verwenden. Weitere Informationen finden Sie in der Dokumentation von Apple.

Stack-Traces anpassen

Wenn Ihre App in einer nicht nativen Umgebung (z. B. C++ oder Unity) ausgeführt wird, können Sie mit der Exception Model API Absturzmetadaten im nativen Ausnahmeformat Ihrer App melden. Gemeldete Ausnahmen werden als nicht schwerwiegend markiert.

Swift

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)

Objective-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 Stackframes können auch nur mit Adressen initialisiert werden:

Swift

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)

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

Navigationspfad-Logs abrufen

Navigationspfadlogs geben Aufschluss über die Interaktionen eines Nutzers mit Ihrer App, die zu einem Absturz, einem nicht schwerwiegenden Ereignis oder einem ANR-Ereignis geführt haben. Diese Protokolle können hilfreich sein, wenn Sie versuchen, ein Problem zu reproduzieren und zu beheben.

Breadcrumb-Protokolle werden von Google Analytics unterstützt. Wenn Sie also Breadcrumb-Protokolle erhalten möchten, müssen Sie Google Analytics für Ihr Firebase-Projekt aktivieren und Ihrer App das Firebase SDK für Google Analytics hinzufügen. Sobald diese Anforderungen erfüllt sind, werden Breadcrumb-Protokolle automatisch zusammen mit den Daten eines Ereignisses auf dem Tab Protokolle angezeigt, wenn Sie sich die Details eines Problems ansehen.

Das Analytics SDK protokolliert das screen_view-Ereignis automatisch. Dadurch können in den Navigationspfad-Logs eine Liste der Bildschirme angezeigt werden, die vor dem Absturz, dem nicht schwerwiegenden Ereignis oder dem ANR-Ereignis aufgerufen wurden. Ein screen_view-Navigationspfad-Log enthält einen firebase_screen_class-Parameter.

In Breadcrumb-Logs werden auch alle benutzerdefinierten Ereignisse erfasst, die Sie manuell während der Sitzung des Nutzers erfassen, einschließlich der Parameterdaten des Ereignisses. Anhand dieser Daten können Sie eine Reihe von Nutzeraktionen nachvollziehen, die zu einem Absturz, einem nicht schwerwiegenden Fehler oder einem ANR-Ereignis geführt haben.

Sie können die Erhebung und Verwendung von Google Analytics-Daten steuern. Dazu gehören auch die Daten, die in Breadcrumb-Logs eingefügt werden.

Berichte mit Einwilligung aktivieren

Standardmäßig erfasst Crashlytics automatisch Absturzberichte für alle Nutzer Ihrer App. Um Nutzern mehr Kontrolle über die von ihnen gesendeten Daten zu geben, können Sie die Funktion „Opt-in-Berichte“ aktivieren. Dazu deaktivieren Sie die automatische Berichterstellung und senden Daten nur dann an Crashlytics, wenn Sie dies in Ihrem Code angeben:

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

    • Schlüssel: FirebaseCrashlyticsCollectionEnabled
    • Wert: false
  2. Aktivieren Sie die Erhebung für ausgewählte Nutzer, indem Sie die Datenerhebungsüberschreibung Crashlytics zur Laufzeit aufrufen. Der Überschreibungswert bleibt bei jedem Start Ihrer App erhalten, damit Crashlytics Berichte automatisch erfassen kann.

    Wenn Sie die automatische Absturzmeldung deaktivieren möchten, geben Sie false als Überschreibungswert an. Wenn dieser Wert auf false festgelegt ist, wird der neue Wert erst bei der nächsten Ausführung der App angewendet.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Daten zu Absturzinformationen verwalten

Mit Absturzinformationen können Sie Probleme beheben, indem Sie Ihre anonymisierten Stacktraces mit Traces aus anderen Firebase-Apps vergleichen. Außerdem erfahren Sie, ob Ihr Problem Teil eines größeren Trends ist. Bei vielen Problemen finden Sie in Crash Insights sogar Ressourcen, die Ihnen bei der Fehlerbehebung helfen.

In Crash Insights werden aggregierte Absturzdaten verwendet, um häufige Stabilitätstrends zu identifizieren. Wenn Sie die Daten Ihrer App nicht freigeben möchten, können Sie Crash Insights oben in der Liste der Crashlytics-Probleme in der Firebase-Konsole über das Menü Crash Insights deaktivieren.