Absturzberichte für Apple-Plattformen anpassen

Plattform auswählen: iOS+ Android Flutter Unity


Sie können auf ein Problem klicken, um einen detaillierten Ereignisbericht im Dashboard DevOps & Engagement > Crashlytics der Firebase-Konsole aufzurufen. Sie können diese Berichte anpassen, um besser zu verstehen, was in Ihrer App passiert und welche Umstände zu den an Crashlytics gemeldeten Ereignissen geführt haben.

Benutzerdefinierte Schlüssel hinzufügen

Mit benutzerdefinierten Schlüsseln können Sie den spezifischen Status Ihrer App, der zu einem Absturz führte, abrufen. Sie können Ihren Absturzberichten beliebige Schlüssel/Wert-Paare zuordnen und dann die benutzerdefinierten Schlüssel verwenden, um Absturzberichte im Dashboard DevOps & Engagement > Crashlytics der Firebase-Konsole zu suchen und zu filtern.

  • Sie können nach Problemen suchen, die mit einem benutzerdefinierten Schlüssel übereinstimmen.

  • Wenn Sie sich ein bestimmtes Problem in der Console ansehen, können Sie die zugehörigen benutzerdefinierten Schlüssel für jedes Ereignis aufrufen (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, 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 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 auf einmal hinzufügen möchten, verwenden Sie die Methode setCustomKeysAndValues mit einem 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 Logeinträge hinzufügen

Wenn Sie mehr Kontext zu den Ereignissen vor einem Absturz benötigen, können Sie Ihrer App benutzerdefinierte Crashlytics-Logs hinzufügen. Crashlytics verknüpft die Logs mit Ihren Absturzdaten und zeigt sie auf dem Tab Logs an, wenn Sie die Details eines Problems aufrufen. Alle Probleme finden Sie in der Firebase Console im Dashboard DevOps & Engagement > Crashlytics.

Swift

Verwenden Sie log() oder log(format:, arguments:), um Probleme einzugrenzen. Wenn Sie eine nützliche Logausgabe mit Nachrichten erhalten möchten, muss das Objekt, das Sie an log() übergeben, dem Attribut CustomStringConvertible entsprechen. log() gibt das Beschreibungsobjekt zurück, das Sie für das Objekt definieren. Beispiel:

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

.log(format:, arguments:) formatiert Werte, die beim 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 Crashlytics-Referenzdokumentation.

Objective-C

Verwenden Sie log oder logWithFormat, um Probleme einzugrenzen. Wenn Sie eine nützliche Logausgabe mit Nachrichten erhalten möchten, muss das Objekt, das Sie an eine der beiden Methoden übergeben, die Instanz-Property 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.

Nutzer-IDs festlegen

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

Wenn Sie Ihren Berichten Nutzer-IDs hinzufügen möchten, weisen Sie jedem Nutzer eine eindeutige Kennung in Form einer ID-Nummer, eines Tokens oder eines Hash-Werts 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 Datensätze löschen müssen, die mit einer Nutzer-ID verknüpft sind, wenden Sie sich an den Firebase-Support.

Nicht schwerwiegende Ausnahmen melden

Crashlytics meldet nicht nur automatisch Abstürze Ihrer App, sondern ermöglicht Ihnen auch, nicht schwerwiegende Ausnahmen aufzuzeichnen und sie beim nächsten Start Ihrer App an Sie zu senden.

Sie können nicht schwerwiegende Ausnahmen aufzeichnen, indem Sie NSError-Objekte mit der Methode recordError aufzeichnen. 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 Methode recordError verwenden, ist es wichtig, die Struktur von NSError zu verstehen und zu wissen, wie Crashlytics die Daten zum Gruppieren von Abstürzen verwendet. Eine falsche Verwendung der Methode recordError kann zu unvorhersehbarem Verhalten führen und dazu, dass Crashlytics die Berichterstellung für 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 eine Stacktrace-Analyse gruppiert werden, werden protokollierte Fehler nach domain und code gruppiert. Das 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 obigen Fehler protokollieren, wird ein neues Problem erstellt, das nach NSSomeErrorDomain und -1001 gruppiert wird. Zusätzliche protokollierte Fehler, die dieselben Domain- und Codewerte verwenden, werden unter demselben Problem gruppiert. Die im userInfo-Objekt enthaltenen Daten werden in Schlüssel/Wert-Paare umgewandelt und im Abschnitt „Schlüssel/Logs“ eines einzelnen Problems angezeigt.

Logs und benutzerdefinierte Schlüssel

Genau wie bei Absturzberichten können Sie Logs und benutzerdefinierte Schlüssel einbetten, um dem NSError Kontext hinzuzufügen. Es gibt jedoch einen Unterschied zwischen den Logs, die an Abstürze angehängt werden, und den Logs, die an protokollierte Fehler angehängt werden. Wenn ein Absturz auftritt und die App neu gestartet wird, werden die Logs, die Crashlytics vom Laufwerk abruft, bis zum Zeitpunkt des Absturzes geschrieben. Wenn Sie einen NSError protokollieren, wird die App nicht sofort beendet. Da Crashlytics den protokollierten Fehlerbericht erst beim nächsten App-Start sendet und der für Protokolle auf dem Laufwerk zugewiesene Speicherplatz begrenzt werden muss, ist es möglich, dass nach der Aufzeichnung eines NSError so viele Protokolle erstellt werden, dass alle relevanten Protokolle bereits rotiert wurden, wenn Crashlytics den Bericht vom Gerät sendet. Beachten Sie dieses Gleichgewicht, wenn Sie NSErrors protokollieren und Logs und benutzerdefinierte Schlüssel in Ihrer App verwenden.

Hinweise zur Leistung

Beachten Sie, dass das Logging eines NSError ziemlich teuer sein kann. Zum Zeitpunkt des Aufrufs erfasst Crashlytics den Aufrufstapel des aktuellen Threads mithilfe eines Prozesses, der als Stack Unwinding bezeichnet wird. Dieser Prozess kann CPU- und E/A-intensiv sein, insbesondere bei Architekturen, die DWARF-Unwinding unterstützen (arm64 und x86). Nach Abschluss des Unwinds werden die Informationen synchron auf das Laufwerk geschrieben. So wird ein Datenverlust verhindert, falls die nächste Zeile abstürzt.

Es ist zwar sicher, diese API in einem Hintergrundthread aufzurufen, aber wenn Sie diesen Aufruf an eine andere Warteschlange weiterleiten, geht der Kontext des aktuellen Stacktrace 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 auch bei äußerster Vorsicht sehr schwerwiegende unbeabsichtigte Nebenwirkungen in Ihrem Prozess haben kann. Sie sollten in Ihrem Code niemals @catch-Anweisungen verwenden. Weitere Informationen finden Sie in der Dokumentation von Apple zu diesem Thema.

Stacktraces anpassen

Wenn Ihre App in einer nicht nativen Umgebung wie C++ oder Unity ausgeführt wird, können Sie die Exception Model API verwenden, um Absturzmetadaten im nativen Ausnahmeformat Ihrer App zu 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

Mit Navigationspfad-Logs können Sie die Interaktionen eines Nutzers mit Ihrer App vor einem Absturz, einem nicht schwerwiegenden Ereignis oder einem ANR-Ereignis besser nachvollziehen. Diese Logs können hilfreich sein, wenn Sie versuchen, ein Problem zu reproduzieren und zu beheben.

Navigationspfad-Logs werden von Google Analytics unterstützt. Wenn Sie Navigationspfad-Logs erhalten möchten, müssen Sie Google Analytics für Ihr Firebase-Projekt aktivieren und das Firebase SDK für Google Analytics zu Ihrer App hinzufügen. Sobald diese Anforderungen erfüllt sind, werden Navigationspfad-Logs automatisch in die Daten eines Ereignisses auf dem Tab Logs aufgenommen, wenn Sie die Details eines Problems aufrufen. Alle Probleme finden Sie im Dashboard DevOps & Engagement > Crashlytics der Firebase-Konsole.

Das Analytics SDK protokolliert automatisch das Ereignis screen_view, sodass in den Navigationspfad-Logs eine Liste der Bildschirme angezeigt werden kann, 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.

Navigationspfad-Logs werden auch mit allen benutzerdefinierten Ereignissen gefüllt, die Sie manuell in der Sitzung des Nutzers protokollieren, einschließlich der Parameterdaten des Ereignisses. Anhand dieser Daten lässt sich eine Reihe von Nutzeraktionen nachvollziehen, die zu einem Absturz, einem nicht schwerwiegenden Ereignis oder einem ANR-Ereignis geführt haben.

Sie können die Erhebung und Verwendung von Google Analytics-Daten steuern, einschließlich der Daten, die in Navigationspfad-Logs eingetragen werden.

Opt-in-Berichterstellung aktivieren

Standardmäßig erfasst Crashlytics automatisch Absturzberichte für alle Nutzer Ihrer App. Wenn Sie Nutzern mehr Kontrolle über die von ihnen gesendeten Daten geben möchten, können Sie die Berichterstellung per Opt-in aktivieren. Deaktivieren Sie dazu die automatische Berichterstellung und senden Sie Daten nur dann an Crashlytics, wenn Sie dies in Ihrem Code festlegen.

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

    • Schlüssel: FirebaseCrashlyticsCollectionEnabled
    • Wert: false
  2. Sie können die Datenerhebung für ausgewählte Nutzer aktivieren, indem Sie die Datenerhebung Crashlytics zur Laufzeit überschreiben. Der Überschreibungswert bleibt bei allen nachfolgenden Starts Ihrer App erhalten, sodass Crashlytics automatisch Berichte für diesen Nutzer erfassen kann.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

    Wenn der Nutzer die Datenerhebung später ablehnt, können Sie false als Überschreibungswert übergeben. Dieser wird beim nächsten Start der App durch den Nutzer angewendet und bleibt bei allen nachfolgenden Starts für diesen Nutzer bestehen.

Crash Insights-Daten verwalten

Crash Insights hilft Ihnen, Probleme zu beheben, indem Ihre anonymisierten Stacktraces mit Traces aus anderen Firebase-Apps verglichen werden. So können Sie feststellen, ob Ihr Problem Teil eines größeren Trends ist. Bei vielen Problemen bietet Crash Insights sogar Ressourcen, die Ihnen bei der Fehlerbehebung helfen.

In Crash Insights werden aggregierte Absturzdaten verwendet, um allgemeine Stabilitätstrends zu ermitteln. Wenn Sie die Daten Ihrer App nicht teilen möchten, können Sie Crash Insights im Menü Crash Insights oben in der Problemliste im Dashboard DevOps & Engagement > Crashlytics der Firebase Console deaktivieren.

Nächste Schritte