Mit erweiterten Crashlytics-Funktionen Abstürze von Unity-Spielen nachvollziehen

1. Einführung

In diesem Codelab erfahren Sie, wie Sie erweiterte Funktionen von Crashlytics verwenden, um Abstürze und die Umstände, die sie möglicherweise verursacht haben, besser nachzuvollziehen.

Sie fügen einem Beispielspiel, MechaHamster: Level Up with Firebase Edition, neue Funktionen hinzu. Dieses Beispielspiel ist eine neue Version des klassischen Firebase-Spiels MechaHamster. Die meisten integrierten Firebase-Funktionen wurden entfernt, sodass Sie die Möglichkeit haben, neue Firebase-Funktionen zu implementieren.

Sie fügen dem Spiel ein Debug-Menü hinzu. In diesem Debug-Menü werden Methoden aufgerufen, die Sie erstellen, und Sie können die verschiedenen Funktionen von Crashlytics ausprobieren. In diesen Methoden erfahren Sie, wie Sie Ihre automatischen Absturzberichte mit benutzerdefinierten Schlüsseln, benutzerdefinierten Logs, nicht schwerwiegenden Fehlern und mehr annotieren.

Nachdem Sie das Spiel entwickelt haben, verwenden Sie das Debug-Menü und prüfen die Ergebnisse, um zu verstehen, wie Ihr Spiel in der Praxis funktioniert.

Lerninhalte

  • Die Arten von Fehlern, die automatisch von Crashlytics erfasst werden.
  • Zusätzliche Fehler, die absichtlich aufgezeichnet werden können.
  • So fügen Sie diesen Fehlern weitere Informationen hinzu, damit sie leichter nachvollziehbar sind.

Voraussetzungen

  • Unity (empfohlene Mindestversion 2019+) mit einer oder beiden der folgenden Optionen:
    • Unterstützung von iOS-Builds
    • Unterstützung für Android-Builds
  • (Nur für Android) Die Firebase CLI (zum Hochladen von Symbolen für Absturzberichte)

2. Entwicklungsumgebung einrichten

In den folgenden Abschnitten wird beschrieben, wie Sie den Code für Level Up with Firebase herunterladen und in Unity öffnen.

Das Beispielspiel Level Up with Firebase wird in mehreren anderen Firebase + Unity-Codelabs verwendet. Möglicherweise haben Sie die Aufgaben in diesem Abschnitt also bereits abgeschlossen. Wenn ja, können Sie direkt zum letzten Schritt auf dieser Seite gehen: „Firebase SDKs für Unity hinzufügen“.

Code herunterladen

Klonen Sie das GitHub-Repository für dieses Codelab über die Befehlszeile:

git clone https://github.com/firebase/level-up-with-firebase.git

Wenn Sie Git nicht installiert haben, können Sie das Repository auch als ZIP-Datei herunterladen.

Level Up with Firebase im Unity-Editor öffnen

  1. Starten Sie den Unity Hub und klicken Sie auf dem Tab Projekte neben Öffnen auf den Drop-down-Pfeil.
  2. Klicken Sie auf Projekt vom Laufwerk hinzufügen.
  3. Wechseln Sie zum Verzeichnis mit dem Code und klicken Sie auf OK.
  4. Wählen Sie bei Aufforderung eine Unity-Editor-Version und Ihre Zielplattform (Android oder iOS) aus.
  5. Klicken Sie auf den Projektnamen level-up-with-firebase. Das Projekt wird im Unity-Editor geöffnet.
  6. Wenn der Editor nicht automatisch geöffnet wird, öffnen Sie MainGameScene auf dem Tab Project des Unity-Editors unter Assets > Hamster.
    ff4ea3f3c0d29379.png

Weitere Informationen zur Installation und Verwendung von Unity finden Sie unter Mit Unity arbeiten.

3. Firebase zu einem Unity-Projekt hinzufügen

Firebase-Projekt erstellen

  1. Melden Sie sich mit Ihrem Google-Konto in der Firebase Console an.
  2. Klicken Sie auf die Schaltfläche, um ein neues Projekt zu erstellen, und geben Sie dann einen Projektnamen ein (z. B. Mechahamster Codelab).
  3. Klicken Sie auf Weiter.
  4. Lesen und akzeptieren Sie bei Aufforderung die Firebase-Nutzungsbedingungen und klicken Sie dann auf Weiter.
  5. (Optional) Aktivieren Sie die KI-Unterstützung in der Firebase Console (als „Gemini in Firebase“ bezeichnet).
  6. Für dieses Codelab benötigen Sie Google Analytics, um Firebase-Produkte optimal nutzen zu können. Lassen Sie die Ein/Aus-Schaltfläche für die Google Analytics-Option also aktiviert. Folgen Sie der Anleitung auf dem Bildschirm, um Google Analytics einzurichten.
  7. Klicken Sie auf Projekt erstellen, warten Sie, bis Ihr Projekt bereitgestellt wurde, und klicken Sie dann auf Weiter.

App bei Firebase registrieren

  1. Klicken Sie in der Firebase Console in der Mitte der Projektübersicht auf das Unity-Symbol, um den Einrichtungsworkflow zu starten. Wenn Sie Ihrem Firebase-Projekt bereits eine App hinzugefügt haben, klicken Sie auf App hinzufügen, um die Plattformoptionen aufzurufen.
  2. Wählen Sie diese Option aus, um sowohl das Apple-Build-Ziel (iOS) als auch das Android-Build-Ziel zu registrieren.
  3. Geben Sie die plattformspezifischen IDs Ihres Unity-Projekts ein. Geben Sie für dieses Codelab Folgendes ein:
    • Für Apple (iOS): Geben Sie im Feld iOS-Bundle-ID com.google.firebase.level-up ein.
    • Für Android: Geben Sie im Feld Android-Paketname com.google.firebase.level_up ein.
  4. (Optional) Geben Sie die plattformspezifischen Aliasnamen Ihres Unity-Projekts ein.
  5. Klicken Sie auf App registrieren und fahren Sie mit dem Abschnitt Konfigurationsdatei herunterladen fort.

Firebase-Konfigurationsdateien hinzufügen

Nachdem Sie auf App registrieren geklickt haben, werden Sie aufgefordert, zwei Konfigurationsdateien herunterzuladen (eine Konfigurationsdatei für jedes Build-Ziel). Ihr Unity-Projekt benötigt die Firebase-Metadaten in diesen Dateien, um eine Verbindung zu Firebase herzustellen.

  1. Laden Sie beide verfügbaren Konfigurationsdateien herunter:
    • Für Apple (iOS): Laden Sie GoogleService-Info.plist herunter.
    • Für Android: Laden Sie google-services.json herunter.
  2. Öffnen Sie das Fenster Project Ihres Unity-Projekts und verschieben Sie beide Konfigurationsdateien in den Ordner Assets.
  3. Klicken Sie in der Firebase Console im Einrichtungsablauf auf Weiter und fahren Sie mit dem Hinzufügen von Firebase-SDKs für Unity fort.

Firebase SDKs für Unity hinzufügen

  1. Klicken Sie in der Firebase Console auf Firebase Unity SDK herunterladen.
  2. Entpacken Sie das SDK an einem für Sie günstigen Ort.
  3. Rufen Sie in Ihrem geöffneten Unity-Projekt Assets > Import Package > Custom Package auf.
  4. Rufen Sie im Dialogfeld Paket importieren das Verzeichnis auf, das das entpackte SDK enthält, wählen Sie FirebaseAnalytics.unitypackage aus und klicken Sie dann auf Öffnen.
  5. Klicken Sie im Dialogfeld Import Unity Package auf Import.
  6. Wiederholen Sie die vorherigen Schritte, um FirebaseCrashlytics.unitypackage zu importieren.
  7. Kehren Sie zur Firebase Console zurück und klicken Sie im Einrichtungs-Workflow auf Weiter.

Weitere Informationen zum Hinzufügen von Firebase SDKs zu Unity-Projekten finden Sie unter Zusätzliche Unity-Installationsoptionen.

4. Crashlytics in Ihrem Unity-Projekt einrichten

Wenn Sie Crashlytics in Unity-Projekten verwenden möchten, müssen Sie einige zusätzliche Einrichtungsschritte ausführen. Natürlich müssen Sie das SDK initialisieren. Außerdem müssen Sie Ihre Symbole hochladen, damit Sie symbolisch dargestellte Stacktraces in der Firebase Console sehen können. Sie müssen auch einen Testabsturz erzwingen, um sicherzustellen, dass Firebase Ihre Absturzereignisse empfängt.

Crashlytics SDK initialisieren

  1. Fügen Sie in Assets/Hamster/Scripts/MainGame.cs die folgenden using-Anweisungen hinzu:
    using Firebase.Crashlytics;
    using Firebase.Extensions;
    
    Im ersten Modul können Sie Methoden aus dem Crashlytics SDK verwenden, das zweite enthält einige Erweiterungen der C# Tasks API. Ohne beide using-Anweisungen funktioniert der folgende Code nicht.
  2. Fügen Sie in MainGame.cs der vorhandenen Methode Start() die Firebase-Initialisierung hinzu, indem Sie InitializeFirebaseAndStartGame() aufrufen:
    void Start()
    {
      Screen.SetResolution(Screen.width / 2, Screen.height / 2, true);
      InitializeFirebaseAndStartGame();
    }
    
  3. Suchen Sie noch einmal in MainGame.cs nach InitializeFirebaseAndStartGame(), deklarieren Sie eine App-Variable und überschreiben Sie dann die Implementierung der Methode so:
    public Firebase.FirebaseApp app = null;
    
    // Begins the firebase initialization process and afterwards, opens the main menu.
    private void InitializeFirebaseAndStartGame()
    {
      Firebase.FirebaseApp.CheckAndFixDependenciesAsync()
      .ContinueWithOnMainThread(
        previousTask => 
        {
          var dependencyStatus = previousTask.Result;
          if (dependencyStatus == Firebase.DependencyStatus.Available) {
            // Create and hold a reference to your FirebaseApp,
            app = Firebase.FirebaseApp.DefaultInstance;
            // Set the recommended Crashlytics uncaught exception behavior.
            Crashlytics.ReportUncaughtExceptionsAsFatal = true;
            InitializeCommonDataAndStartGame();
          } else {
            UnityEngine.Debug.LogError(
              $"Could not resolve all Firebase dependencies: {dependencyStatus}\n" +
              "Firebase Unity SDK is not safe to use here");
          }
        });
    }
    

Wenn Sie die Initialisierungslogik hier platzieren, wird verhindert, dass der Spieler interagiert, bevor die Firebase-Abhängigkeiten initialisiert wurden.

Die Vorteile und Auswirkungen des Meldens nicht behandelter Ausnahmen als schwerwiegend werden in den Crashlytics-FAQs erläutert.

Projekt erstellen und Symbole hochladen

Die Schritte zum Erstellen und Hochladen von Symbolen unterscheiden sich für iOS- und Android-Apps.

iOS+ (Apple-Plattform)

  1. Exportieren Sie Ihr Projekt im Dialogfeld Build Settings (Build-Einstellungen) in einen Xcode-Arbeitsbereich.
  2. Erstellen Sie Ihre App.
    Für Apple-Plattformen konfiguriert das Firebase Unity Editor-Plug-in Ihr Xcode-Projekt automatisch so, dass für jeden Build eine Crashlytics-kompatible Symboldatei generiert und auf Firebase-Server hochgeladen wird. Diese Symbolinformationen sind erforderlich, um symbolisierte Stacks im Crashlytics-Dashboard zu sehen.

Android

  1. (nur bei der Ersteinrichtung, nicht für jeden Build) Build einrichten:
    1. Erstellen Sie im Stammverzeichnis Ihres Projektverzeichnisses (d.h. als gleichgeordnetes Element Ihres Verzeichnisses Assets) einen neuen Ordner mit dem Namen Builds und dann einen Unterordner mit dem Namen Android.
    2. Legen Sie unter File > Build Settings > Player Settings > Configuration das Scripting Backend auf IL2CPP fest.
      • IL2CPP führt in der Regel zu kleineren Builds mit besserer Leistung.
      • IL2CPP ist auch die EINZIGE verfügbare Option unter iOS. Wenn Sie sie hier auswählen, können Sie die beiden Plattformen besser vergleichen und das Debuggen von Unterschieden zwischen den beiden (wenn Sie beide erstellen) vereinfachen.
  2. Erstellen Sie Ihre App. Gehen Sie zu File > Build Settings und führen Sie die folgenden Schritte aus:
    1. Achten Sie darauf, dass symbols.zip erstellen ausgewählt ist. Wenn ein Drop-down-Menü angezeigt wird, wählen Sie Debugging aus.
    2. Erstellen Sie Ihr APK direkt im Unity-Editor im Unterordner Builds/Android, den Sie gerade erstellt haben.
  3. Nachdem der Build abgeschlossen ist, müssen Sie eine mit Crashlytics kompatible Symboldatei generieren und auf die Firebase-Server hochladen. Diese Symbolinformationen sind erforderlich, um symbolisierte Stacktraces für Abstürze nativer Bibliotheken im Crashlytics-Dashboard zu sehen.

     Generieren und laden Sie diese Symboldatei hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
    • FIREBASE_APP_ID: Ihre Firebase-Android-App-ID (nicht Ihr Paketname). Sie finden diesen Wert in der Datei google-services.json, die Sie zuvor heruntergeladen haben. Es ist der Wert mobilesdk_app_id.
      Beispiel für eine Firebase-Android-App-ID: 1:567383003300:android:17104a2ced0c9b9b
    • PATH/TO/SYMBOLS: Der Pfad der gezippten Symboldatei, die nach Abschluss des Builds im Verzeichnis Builds/Android generiert wurde (z. B. Builds/Android/myapp-1.0-v100.symbols.zip).

Testabsturz erzwingen, um die Einrichtung abzuschließen

Damit Sie die Einrichtung von Crashlytics abschließen und erste Daten im Crashlytics-Dashboard der Firebase Console sehen können, müssen Sie einen Testabsturz erzwingen.

  1. Suchen Sie in der MainGameScene im Editor Hierarchy nach EmptyObjectGameObject, fügen Sie das folgende Skript hinzu und speichern Sie die Szene. Dieses Skript führt einige Sekunden nach dem Ausführen Ihrer App zu einem Testabsturz.
    using System;
    using UnityEngine;
    
    public class CrashlyticsTester : MonoBehaviour {
        // Update is called once per frame
        void Update()
        {
            // Tests your Crashlytics implementation by
            // throwing an exception every 60 frames.
            // You should see reports in the Firebase console
            // a few minutes after running your app with this method.
            if(Time.frameCount >0 && (Time.frameCount%60) == 0)
            {
                throw new System.Exception("Test exception; please ignore");
            }
        }
    }
    
  2. Erstellen Sie Ihre App und laden Sie Symbolinformationen hoch, nachdem der Build abgeschlossen ist.
    • iOS: Das Firebase Unity Editor-Plug-in konfiguriert Ihr Xcode-Projekt automatisch für das Hochladen Ihrer Symboldatei.
    • Android: Führen Sie den Firebase CLI-Befehl crashlytics:symbols:upload aus, um Ihre Symboldatei hochzuladen.
  3. Führen Sie Ihre App aus. Beobachten Sie das Geräte-Log und warten Sie, bis die Ausnahme von CrashlyticsTester ausgelöst wird.
    • iOS: Logs werden im unteren Bereich von Xcode angezeigt.
    • Android: Sie können sich die Logs ansehen, indem Sie den folgenden Befehl im Terminal ausführen: adb logcat.
  4. Rufen Sie das Crashlytics-Dashboard auf, um die Ausnahme zu sehen. Sie finden sie unten im Dashboard in der Tabelle Probleme. Später in diesem Codelab erfahren Sie mehr darüber, wie Sie diese Berichte analysieren können.
  5. Nachdem Sie bestätigt haben, dass das Ereignis in Crashlytics hochgeladen wurde, wählen Sie das EmptyObject GameObject aus, an das Sie es angehängt haben, entfernen Sie nur die CrashlyticsTester-Komponente und speichern Sie die Szene, um sie in ihren ursprünglichen Zustand zurückzusetzen.

5. Fehlerbehebungsmenü aktivieren und verwenden

Bisher haben Sie Crashlytics in Ihr Unity-Projekt eingebunden, die Einrichtung abgeschlossen und bestätigt, dass das Crashlytics SDK Ereignisse in Firebase hochlädt. Als Nächstes erstellen Sie ein Menü in Ihrem Unity-Projekt, das zeigt, wie Sie erweiterte Crashlytics-Funktionen in Ihrem Spiel verwenden. Das Unity-Projekt Level Up with Firebase enthält bereits ein ausgeblendetes Debug-Menü, das Sie sichtbar machen und für das Sie die Funktionalität schreiben.

Debug-Menü aktivieren

Die Schaltfläche für das Debug-Menü ist in Ihrem Unity-Projekt vorhanden, aber derzeit nicht aktiviert. Sie müssen die Schaltfläche aktivieren, um über das MainMenu-Prefab darauf zuzugreifen:

  1. Öffnen Sie im Unity-Editor das Prefab mit dem Namen MainMenu.4148538cbe9f36c5.png.
  2. Suchen Sie in der Prefab-Hierarchie nach dem deaktivierten Unterobjekt mit dem Namen DebugMenuButton und wählen Sie es aus.816f8f9366280f6c.png
  3. Aktivieren Sie DebugMenuButton, indem Sie das Kästchen oben links neben dem Textfeld mit DebugMenuButton8a8089d2b4886da2.png anklicken.
  4. Speichern Sie das Prefab.
  5. Führen Sie das Spiel entweder im Editor oder auf Ihrem Gerät aus. Das Menü sollte jetzt zugänglich sein.

Methodenkörper für das Debug-Menü in der Vorschau ansehen und verstehen

Später in diesem Codelab schreiben Sie Methodenkörper für einige vorkonfigurierte Crashlytics-Debug-Methoden. Im Unity-Projekt Level Up with Firebase werden die Methoden jedoch in DebugMenu.cs definiert und von dort aufgerufen.

Bei einigen dieser Methoden werden sowohl Crashlytics-Methoden aufgerufen als auch Fehler ausgegeben. Die Fähigkeit von Crashlytics, diese Fehler abzufangen, hängt jedoch nicht davon ab, ob diese Methoden zuerst aufgerufen werden. Stattdessen werden die Absturzberichte, die durch das automatische Abfangen von Fehlern generiert werden, durch die Informationen, die durch diese Methoden hinzugefügt werden, ergänzt.

Öffnen Sie DebugMenu.cs und suchen Sie nach den folgenden Methoden:

Methoden zum Generieren und Annotieren von Crashlytics-Problemen:

  • CrashNow
  • LogNonfatalError
  • LogStringsAndCrashNow
  • SetAndOverwriteCustomKeyThenCrash
  • SetLogsAndKeysBeforeANR

Methoden zum Protokollieren von Analytics-Ereignissen zur Unterstützung der Fehlersuche:

  • LogProgressEventWithStringLiterals
  • LogIntScoreWithBuiltInEventAndParams

In späteren Schritten dieses Codelabs implementieren Sie diese Methoden und erfahren, wie sie bei bestimmten Situationen helfen, die bei der Spieleentwicklung auftreten können.

6. Zustellung von Absturzberichten in der Entwicklung sicherstellen

Bevor Sie mit der Implementierung dieser Debugging-Methoden beginnen und sehen, wie sie sich auf Absturzberichte auswirken, sollten Sie wissen, wie Ereignisse an Crashlytics gemeldet werden.

Bei Unity-Projekten werden Absturz- und Ausnahmeereignisse in Ihrem Spiel sofort auf die Festplatte geschrieben. Bei nicht abgefangenen Ausnahmen, die nicht zum Absturz Ihres Spiels führen (z. B. nicht abgefangene C#-Ausnahmen in der Spiellogik), können Sie das Crashlytics SDK so konfigurieren, dass sie als schwerwiegende Ereignisse gemeldet werden. Dazu müssen Sie die Crashlytics.ReportUncaughtExceptionsAsFatal-Property auf true setzen, wenn Sie Crashlytics in Ihrem Unity-Projekt initialisieren. Diese Ereignisse werden in Echtzeit an Crashlytics gemeldet, ohne dass der Endnutzer das Spiel neu starten muss. Native Abstürze werden immer als schwerwiegende Ereignisse gemeldet und gesendet, wenn ein Endnutzer das Spiel neu startet.

Beachten Sie außerdem die folgenden kleinen, aber wichtigen Unterschiede zwischen den verschiedenen Laufzeitumgebungen beim Senden von Crashlytics-Informationen an Firebase:

iOS-Simulator:

  • Crashlytics-Informationen werden nur dann gemeldet, wenn Sie Xcode vom Simulator trennen. Wenn Xcode angehängt ist, werden die Fehler vorab abgefangen, sodass keine Informationen übermittelt werden.

Physische Mobilgeräte (Android und iOS):

  • Android-spezifisch: ANR-Fehler werden nur unter Android 11 und höher gemeldet. ANR-Fehler und nicht schwerwiegende Ereignisse werden beim nächsten Ausführen gemeldet.

Unity-Editor:

Spielabstürze per Knopfdruck in CrashNow() testen

Nachdem Crashlytics in Ihrem Spiel eingerichtet wurde, zeichnet das Crashlytics SDK automatisch Abstürze und nicht abgefangene Ausnahmen auf und lädt sie zur Analyse in Firebase hoch. Die Berichte werden in der Firebase Console im Crashlytics-Dashboard angezeigt.

  1. Um zu demonstrieren, dass dies tatsächlich automatisch erfolgt, öffnen Sie DebugMenu.cs und überschreiben Sie die Methode CrashNow() so:
    void CrashNow()
    {
        TestCrash();
    }
    
  2. Erstelle deine App.
  3. (Nur Android) Laden Sie Ihre Symbole hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Tippen Sie auf die Schaltfläche Crash Now (Jetzt abstürzen) und fahren Sie mit dem nächsten Schritt dieses Codelabs fort, um zu erfahren, wie Sie den Absturzbericht aufrufen und interpretieren.

7. Problemberichte in der Firebase Console

Wenn Sie Ihre Absturzberichte ansehen, müssen Sie ein paar Dinge beachten, um sie optimal nutzen zu können. In jeder Methode wird gezeigt, wie Sie Crashlytics-Berichten verschiedene Arten von Informationen hinzufügen.

  1. Tippen Sie auf die Schaltfläche Crash Now (Jetzt abstürzen) und starten Sie die App neu.
  2. Rufen Sie das Crashlytics-Dashboard auf. Scrollen Sie im Dashboard nach unten zur Tabelle Probleme. Dort werden Ereignisse mit derselben Ursache in „Probleme“ gruppiert.
  3. Klicken Sie in der Tabelle Probleme auf das neue Problem. Dadurch wird die Ereignisübersicht für jedes einzelne Ereignis angezeigt, das an Firebase gesendet wurde.

    Sie sollten etwas Ähnliches wie im folgenden Screenshot sehen. Beachten Sie, dass in der Ereigniszusammenfassung der Stacktrace des Aufrufs, der zum Absturz geführt hat, gut sichtbar ist.40c96abe7f90c3aa.png

Zusätzliche Metadaten

Ein weiterer hilfreicher Tab ist Unity-Metadaten. In diesem Abschnitt finden Sie Informationen zu den Attributen des Geräts, auf dem das Ereignis aufgetreten ist, einschließlich physischer Merkmale, des CPU-Modells/der CPU-Spezifikationen und verschiedener GPU-Messwerte.

Hier ist ein Beispiel dafür, wann die Informationen auf diesem Tab nützlich sein können:
Angenommen, in Ihrem Spiel werden Shader intensiv genutzt, um ein bestimmtes Aussehen zu erzielen. Allerdings haben nicht alle Smartphones GPUs, die diese Funktion rendern können. Die Informationen auf dem Tab Unity-Metadaten können Ihnen dabei helfen, zu entscheiden, auf welcher Hardware Ihre App getestet werden sollte, wenn Sie festlegen, welche Funktionen automatisch verfügbar gemacht oder ganz deaktiviert werden sollen.

Auch wenn auf Ihrem Gerät nie ein Fehler oder Absturz auftritt, ist es aufgrund der großen Vielfalt an Android-Geräten hilfreich, die besonderen „Hotspots“ der Geräte Ihrer Zielgruppe besser zu verstehen.

41d8d7feaa87454d.png

8. Ausnahme auslösen, abfangen und protokollieren

Auch wenn Ihr Code als Entwickler eine Laufzeit-Ausnahme ordnungsgemäß abfängt und verarbeitet, ist es oft sinnvoll, zu vermerken, dass sie aufgetreten ist und unter welchen Umständen. Crashlytics.LogException kann genau für diesen Zweck verwendet werden: zum Senden eines Ausnahmeereignisses an Firebase, damit Sie das Problem in der Firebase Console weiter debuggen können.

  1. Hängen Sie in Assets/Hamster/Scripts/States/DebugMenu.cs Folgendes an die using-Anweisungen an:
    // Import Firebase
    using Firebase.Crashlytics;
    
  2. Überschreiben Sie LogNonfatalError() in DebugMenu.cs so:
    void LogNonfatalError()
    {
        try
        {
            throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}");
        }
        catch(System.Exception exception)
        {
            Crashlytics.LogException(exception);
        }
    }
    
  3. Erstelle deine App.
  4. (Nur Android) Laden Sie Ihre Symbole hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  5. Tippen Sie auf die Schaltfläche Nicht schwerwiegenden Fehler protokollieren und starten Sie die App neu.
  6. Rufen Sie das Crashlytics-Dashboard auf. Es sollte ähnlich aussehen wie im letzten Schritt dieses Codelabs.
  7. Beschränken Sie den Filter Ereignistyp diesmal auf Nicht schwerwiegend, damit nur nicht schwerwiegende Fehler angezeigt werden, z. B. der, den Sie gerade protokolliert haben.
    a39ea8d9944cbbd9.png

9. Strings in Crashlytics protokollieren, um den Ablauf der Programmausführung besser zu verstehen

Haben Sie sich schon einmal gefragt, warum eine Codezeile, die Hunderte oder sogar Tausende Male pro Sitzung über mehrere Pfade aufgerufen wird, plötzlich eine Ausnahme oder einen Absturz verursachen kann? Es wäre zwar schön, den Code in einer IDE durchzugehen und sich die Werte genauer anzusehen, aber was ist, wenn das nur bei einem verschwindend geringen Prozentsatz Ihrer Nutzer passiert? Was würden Sie tun, wenn Sie diesen Absturz nicht reproduzieren können, egal was Sie tun?

In solchen Situationen kann es einen großen Unterschied machen, wenn Sie etwas Kontext liefern. Mit Crashlytics.Log können Sie den benötigten Kontext angeben. Stell dir vor, diese Nachrichten sind Hinweise an dein zukünftiges Ich, was passieren könnte.

Protokolle können auf vielfältige Weise verwendet werden. In der Regel sind sie jedoch am hilfreichsten, um Situationen aufzuzeichnen, in denen die Reihenfolge und/oder das Fehlen von Aufrufen von entscheidender Bedeutung ist.

  1. Überschreiben Sie in Assets/Hamster/Scripts/States/DebugMenu.cs LogStringsAndCrashNow() so:
    void LogStringsAndCrashNow()
    {
        Crashlytics.Log($"This is the first of two descriptive strings in {nameof(LogStringsAndCrashNow)}");
        const bool RUN_OPTIONAL_PATH = false;
        if(RUN_OPTIONAL_PATH)
        {
            Crashlytics.Log(" As it stands, this log should not appear in your records because it will never be called.");
        }
        else
        {
            Crashlytics.Log(" A log that will simply inform you which path of logic was taken. Akin to print debugging.");
        }
        Crashlytics.Log($"This is the second of two descriptive strings in {nameof(LogStringsAndCrashNow)}");
        TestCrash();
    }
    
  2. Erstelle deine App.
  3. (Nur Android) Laden Sie Ihre Symbole hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Tippen Sie auf die Schaltfläche Log Strings and Crash Now (Strings protokollieren und jetzt abstürzen) und starten Sie die App neu.
  5. Kehren Sie zum Crashlytics-Dashboard zurück und klicken Sie in der Tabelle Probleme auf das neueste Problem. Die Ausgabe sollte in etwa so aussehen wie bei den vorherigen Problemen.
    7aabe103b8589cc7.png
  6. Wenn Sie jedoch in einer Ereigniszusammenfassung auf den Tab Logs klicken, wird eine Ansicht wie diese angezeigt:
    4e27aa407b7571cf.png

10. Benutzerdefinierten Schlüssel schreiben und überschreiben

Angenommen, Sie möchten einen Absturz besser nachvollziehen, der mit Variablen zusammenhängt, die auf eine kleine Anzahl von Werten oder Konfigurationen festgelegt sind. Es wäre hilfreich, wenn Sie jederzeit nach der Kombination von Variablen und möglichen Werten filtern könnten, die Sie sich gerade ansehen.

Neben dem Protokollieren beliebiger Strings bietet Crashlytics eine weitere Form des Debuggens, wenn es hilfreich ist, den genauen Status Ihres Programms zum Zeitpunkt des Absturzes zu kennen: benutzerdefinierte Schlüssel.

Dies sind Schlüssel/Wert-Paare, die Sie für eine Sitzung festlegen können. Im Gegensatz zu Logs, die sich ansammeln und rein additiv sind, können Schlüssel überschrieben werden, um nur den aktuellen Status einer Variablen oder Bedingung widerzuspiegeln.

Diese Schlüssel sind nicht nur ein Protokoll des zuletzt aufgezeichneten Status Ihres Programms, sondern können auch als leistungsstarke Filter für Crashlytics-Probleme verwendet werden.

  1. Überschreiben Sie in Assets/Hamster/Scripts/States/DebugMenu.cs SetAndOverwriteCustomKeyThenCrash() so:
    void SetAndOverwriteCustomKeyThenCrash()
    {
        const string CURRENT_TIME_KEY = "Current Time";
        System.TimeSpan currentTime = System.DateTime.Now.TimeOfDay;
        Crashlytics.SetCustomKey(
            CURRENT_TIME_KEY,
            DayDivision.GetPartOfDay(currentTime).ToString() // Values must be strings
            );
    
        // Time Passes
        currentTime += DayDivision.DURATION_THAT_ENSURES_PHASE_CHANGE;
    
        Crashlytics.SetCustomKey(
            CURRENT_TIME_KEY,
            DayDivision.GetPartOfDay(currentTime).ToString()
            );
        TestCrash();
    }
    
  2. Erstelle deine App.
  3. (Nur Android) Laden Sie Ihre Symbole hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Tippen Sie auf die Schaltfläche Benutzerdefinierten Schlüssel festlegen und abstürzen und starten Sie die App neu.
  5. Kehren Sie zum Crashlytics-Dashboard zurück und klicken Sie in der Tabelle Probleme auf das neueste Problem. Auch hier sollten Sie ähnliche Probleme wie zuvor sehen.
  6. Klicken Sie dieses Mal jedoch in der Ereigniszusammenfassung auf den Tab Schlüssel, damit Sie den Wert von Schlüsseln wie Current Time sehen können:
    7dbe1eb00566af98.png

Warum sollten Sie benutzerdefinierte Schlüssel anstelle von benutzerdefinierten Logs verwenden?

  • Logs eignen sich gut zum Speichern sequenzieller Daten, benutzerdefinierte Schlüssel sind jedoch besser, wenn Sie nur den aktuellsten Wert benötigen.
  • In der Firebase Console können Sie Probleme ganz einfach nach den Werten von Schlüsseln im Suchfeld der Tabelle Probleme filtern.

Ähnlich wie bei Logs gibt es jedoch ein Limit für benutzerdefinierte Schlüssel. Crashlytics unterstützt maximal 64 Schlüssel/Wert-Paare. Wenn Sie diesen Grenzwert erreichen, werden keine zusätzlichen Werte gespeichert. Jedes Schlüssel/Wert-Paar kann bis zu 1 KB groß sein.

11. (Nur Android) Benutzerdefinierte Schlüssel und Logs verwenden, um einen ANR zu analysieren und zu diagnostizieren

Eine der schwierigsten Fehlerklassen für Android-Entwickler ist der Fehler App antwortet nicht (ANR). ANR-Fehler treten auf, wenn eine App länger als 5 Sekunden nicht auf Eingaben reagiert. Wenn das passiert, ist die App entweder eingefroren oder sehr langsam. Nutzern wird ein Dialogfeld angezeigt, in dem sie auswählen können, ob sie „Warten“ oder „App schließen“ möchten.

ANR-Fehler beeinträchtigen die Nutzerfreundlichkeit und können (wie im ANR-Link oben erwähnt) die Sichtbarkeit Ihrer App im Google Play Store beeinträchtigen. Aufgrund ihrer Komplexität und da sie oft durch Multithread-Code mit sehr unterschiedlichem Verhalten auf verschiedenen Smartphone-Modellen verursacht werden, ist es oft sehr schwierig, ANR-Fehler beim Debuggen zu reproduzieren. Daher ist es in der Regel am besten, analytisch und deduktiv vorzugehen.

Bei dieser Methode verwenden wir eine Kombination aus Crashlytics.LogException, Crashlytics.Log und Crashlytics.SetCustomKey, um die automatische Protokollierung von Problemen zu ergänzen und uns weitere Informationen zu liefern.

  1. Überschreiben Sie in Assets/Hamster/Scripts/States/DebugMenu.cs SetLogsAndKeysBeforeANR() so:
    void SetLogsAndKeysBeforeANR()
    {
        System.Action<string,long> WaitAndRecord =
        (string methodName, long targetCallLength)=>
        {
            System.Diagnostics.Stopwatch stopWatch = new System.Diagnostics.Stopwatch();
            const string CURRENT_FUNCTION = "Current Async Function";
    
            // Initialize key and start timing
            Crashlytics.SetCustomKey(CURRENT_FUNCTION, methodName);
            stopWatch.Start();
    
            // The actual (simulated) work being timed.
            BusyWaitSimulator.WaitOnSimulatedBlockingWork(targetCallLength);
    
            // Stop timing
            stopWatch.Stop();
    
            if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.EXTREME_DURATION_MILLIS)
            {
              Crashlytics.Log($"'{methodName}' is long enough to cause an ANR.");
            }
            else if(stopWatch.ElapsedMilliseconds>=BusyWaitSimulator.SEVERE_DURATION_MILLIS)
            {
              Crashlytics.Log($"'{methodName}' is long enough it may cause an ANR");
            }
        };
    
        WaitAndRecord("DoSafeWork",1000L);
        WaitAndRecord("DoSevereWork",BusyWaitSimulator.SEVERE_DURATION_MILLIS);
        WaitAndRecord("DoExtremeWork",2*BusyWaitSimulator.EXTREME_DURATION_MILLIS);
    }
    
  2. Erstelle deine App.
  3. Laden Sie Ihre Symbole hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Tippen Sie auf die Schaltfläche mit der Aufschrift Set Logs And Keys → ANR (Logs und Schlüssel festlegen → ANR) und starten Sie die App neu.
  5. Kehren Sie zum Crashlytics-Dashboard zurück und klicken Sie in der Tabelle Issues auf das neue Problem, um die Event summary (Ereigniszusammenfassung) aufzurufen. Wenn der Aufruf ordnungsgemäß erfolgt ist, sollte die Ausgabe in etwa so aussehen:
    876c3cff7037bd07.png

    Wie Sie sehen, hat Firebase die Busy-Wait-Schleife im Thread als Hauptgrund für den ANR-Fehler Ihrer App identifiziert.
  6. Wenn Sie sich die Logs auf dem Tab Logs der Ereigniszusammenfassung ansehen, sehen Sie, dass die letzte Methode, die als abgeschlossen aufgezeichnet wurde, DoSevereWork.
    5a4bec1cf06f6984.png

    ist. Die letzte Methode, die als gestartet aufgeführt wird, ist dagegen DoExtremeWork. Das bedeutet, dass der ANR während dieser Methode aufgetreten ist und das Spiel geschlossen wurde, bevor DoExtremeWork.

    89d86d5f598ecf3a.png protokolliert werden konnte.

Was spricht dafür?

  • ANRs lassen sich nur sehr schwer reproduzieren. Daher ist es unglaublich wichtig, detaillierte Informationen zum Codebereich und zu Messwerten zu erhalten, um sie deduktiv zu ermitteln.
  • Anhand der in den benutzerdefinierten Schlüsseln gespeicherten Informationen können Sie jetzt sehen, welcher asynchrone Thread am längsten ausgeführt wurde und bei welchen die Gefahr bestand, dass ANR-Fehler ausgelöst werden. Anhand dieser Art von verknüpften logischen und numerischen Daten können Sie erkennen, an welcher Stelle in Ihrem Code eine Optimierung am dringendsten erforderlich ist.

12. Analytics-Ereignisse einfügen, um Berichte weiter anzureichern

Die folgenden Methoden können auch über das Debug-Menü aufgerufen werden. Anstatt Probleme selbst zu generieren, verwenden sie Google Analytics als weitere Informationsquelle, um die Funktionsweise Ihres Spiels besser zu verstehen.

Im Gegensatz zu den anderen Methoden, die Sie in diesem Codelab geschrieben haben, sollten Sie diese Methoden in Kombination mit den anderen verwenden. Rufen Sie diese Methoden (durch Drücken der entsprechenden Schaltfläche im Debug-Menü) in beliebiger Reihenfolge auf, bevor Sie eine der anderen Methoden ausführen. Wenn Sie sich dann die Informationen zum jeweiligen Crashlytics-Problem ansehen, sehen Sie ein geordnetes Protokoll von Analytics-Ereignissen. Diese Daten können in einem Spiel verwendet werden, um den Programmablauf oder die Nutzereingabe besser zu verstehen, je nachdem, wie Sie Ihre App instrumentiert haben.

  1. Überschreiben Sie in Assets/Hamster/Scripts/States/DebugMenu.cs die vorhandenen Implementierungen der folgenden Methoden:
    public void LogProgressEventWithStringLiterals()
    {
          Firebase.Analytics.FirebaseAnalytics.LogEvent("progress", "percent", 0.4f);
    }
    
    public void LogIntScoreWithBuiltInEventAndParams()
    {
          Firebase.Analytics.FirebaseAnalytics
            .LogEvent(
              Firebase.Analytics.FirebaseAnalytics.EventPostScore,
              Firebase.Analytics.FirebaseAnalytics.ParameterScore,
              42
            );
    }
    
  2. Erstelle und stelle dein Spiel bereit und rufe dann das Debug-Menü auf.
  3. (Nur Android) Laden Sie Ihre Symbole hoch, indem Sie den folgenden Firebase CLI-Befehl ausführen:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Drücken Sie mindestens eine der folgenden Tasten einmal oder mehrmals, um die oben genannten Funktionen aufzurufen:
    • Log String Event
    • Log Int Event
  5. Drücken Sie die Schaltfläche Crash Now (Jetzt abstürzen).
  6. Starten Sie das Spiel neu, damit das Absturzereignis in Firebase hochgeladen wird.
  7. Wenn Sie verschiedene beliebige Sequenzen von Analytics-Ereignissen protokollieren und Ihr Spiel dann ein Ereignis generiert, aus dem Crashlytics einen Bericht erstellt (wie gerade geschehen), werden diese Ereignisse dem Tab Logs der Crashlytics-Ereignisübersicht hinzugefügt:
    d3b16d78f76bfb04.png

13. Künftig

Damit sollten Sie eine bessere theoretische Grundlage haben, um Ihre automatisch generierten Absturzberichte zu ergänzen. Mithilfe dieser neuen Informationen können Sie den aktuellen Status, Aufzeichnungen vergangener Ereignisse und vorhandene Google Analytics-Ereignisse verwenden, um die Abfolge von Ereignissen und die Logik, die zum Ergebnis geführt hat, besser aufzuschlüsseln.

Wenn Ihre App auf Android 11 (API‑Level 30) oder höher ausgerichtet ist, sollten Sie GWP‑ASan einbinden. Diese Funktion für die native Speicherzuweisung ist nützlich, um Abstürze zu debuggen, die durch native Speicherfehler wie use-after-free- und heap-buffer-overflow-Fehler verursacht werden. Um diese Debugging-Funktion nutzen zu können, müssen Sie GWP-ASan explizit aktivieren.

Nächste Schritte

Codelab: Unity-Spiel mit Remote Config instrumentieren