Zrozum awarie gier Unity, korzystając z zaawansowanych funkcji Crashlytics, Zrozumienie awarii gier Unity, korzystając z zaawansowanych funkcji Crashlytics

1. Wstęp

Podczas tych zajęć z programowania dowiesz się, jak korzystać z zaawansowanych funkcji Crashlytics, które zapewnią Ci lepszy wgląd w awarie i okoliczności, które mogły je spowodować.

Dodasz nową funkcjonalność do przykładowej gry MechaHamster: Level Up w Firebase Edition . Ta przykładowa gra to nowa wersja klasycznej gry Firebase MechaHamster, która usuwa większość wbudowanych funkcji Firebase, dając ci szansę na wdrożenie nowych zastosowań Firebase w ich miejsce.

Dodasz menu debugowania do gry. To menu debugowania wywołuje metody, które utworzysz i umożliwia korzystanie z różnych funkcjonalności Crashlytics. Metody te pokażą Ci, jak dodawać adnotacje do automatycznych raportów o awariach, używając niestandardowych kluczy, niestandardowych dzienników, błędów niekrytycznych i nie tylko.

Po zbudowaniu gry skorzystasz z menu debugowania i sprawdzisz wyniki, aby zrozumieć unikalny wgląd w to, jak gra działa w środowisku naturalnym.

Czego się dowiesz

  • Rodzaje błędów automatycznie wychwytywanych przez Crashlytics.
  • Dodatkowe błędy, które można celowo zarejestrować.
  • Jak dodać więcej informacji do tych błędów, aby były łatwiejsze do zrozumienia.

Co będziesz potrzebował

  • Unity (minimalna zalecana wersja 2019+) z jednym lub obydwoma z poniższych:
    • Obsługa kompilacji iOS
    • Obsługa kompilacji Androida
  • (Tylko dla Androida) Interfejs CLI Firebase (używany do przesyłania symboli raportów o awariach)

2. Skonfiguruj środowisko programistyczne

W poniższych sekcjach opisano, jak pobrać kod Level Up z Firebase i otworzyć go w Unity.

Pamiętaj, że ta przykładowa gra Level Up with Firebase jest używana w kilku innych laboratoriach programowania Firebase + Unity, więc zadania opisane w tej sekcji mogły już zostać ukończone. Jeśli tak, możesz przejść bezpośrednio do ostatniego kroku na tej stronie: „Dodaj zestawy SDK Firebase dla Unity”.

Pobierz kod

Sklonuj repozytorium GitHub tego laboratorium kodowego z wiersza poleceń:

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

Alternatywnie, jeśli nie masz zainstalowanego gita, możesz pobrać repozytorium jako plik ZIP .

Otwórz Level Up w Firebase w edytorze Unity

  1. Uruchom Unity Hub i na karcie Projekty kliknij strzałkę listy rozwijanej obok opcji Otwórz .
  2. Kliknij Dodaj projekt z dysku .
  3. Przejdź do katalogu zawierającego kod, a następnie kliknij OK .
  4. Jeśli zostanie wyświetlony monit, wybierz wersję edytora Unity, której chcesz używać, oraz platformę docelową (Android lub iOS).
  5. Kliknij nazwę projektu, poziom-up-with-firebase , a projekt otworzy się w edytorze Unity.
  6. Jeśli Twój edytor nie otworzy go automatycznie, otwórz MainGameScene w Zasoby > Hamster w zakładce Projekt w Edytorze Unity.
    ff4ea3f3c0d29379.png

Aby uzyskać więcej informacji na temat instalowania i używania Unity, zobacz Praca w Unity .

3. Dodaj Firebase do swojego projektu Unity

Utwórz projekt Firebase

  1. W konsoli Firebase kliknij Dodaj projekt .
  2. Aby utworzyć nowy projekt, wprowadź żądaną nazwę projektu.
    Spowoduje to również ustawienie identyfikatora projektu (wyświetlanego pod nazwą projektu) na wartość opartą na nazwie projektu. Opcjonalnie możesz kliknąć ikonę edycji na identyfikatorze projektu, aby go jeszcze bardziej dostosować.
  3. Jeśli pojawi się monit, przejrzyj i zaakceptuj warunki Firebase .
  4. Kliknij Kontynuuj .
  5. Wybierz opcję Włącz Google Analytics dla tego projektu , a następnie kliknij Kontynuuj .
  6. Wybierz istniejące konto Google Analytics, którego chcesz użyć, lub wybierz opcję Utwórz nowe konto , aby utworzyć nowe konto.
  7. Kliknij opcję Utwórz projekt .
  8. Po utworzeniu projektu kliknij Kontynuuj .

Zarejestruj swoją aplikację w Firebase

  1. Wciąż w konsoli Firebase , na środku strony przeglądu projektu kliknij ikonę Unity, aby uruchomić proces konfiguracji lub, jeśli dodałeś już aplikację do projektu Firebase, kliknij Dodaj aplikację , aby wyświetlić opcje platformy.
  2. Wybierz, aby zarejestrować elementy docelowe kompilacji Apple (iOS) i Androida.
  3. Wprowadź identyfikatory specyficzne dla platformy projektu Unity. W przypadku tego ćwiczenia z kodowania wprowadź następujące dane:
  4. (Opcjonalnie) Wprowadź pseudonimy specyficzne dla platformy projektu Unity.
  5. Kliknij opcję Zarejestruj aplikację , a następnie przejdź do sekcji Pobierz plik konfiguracyjny .

Dodaj pliki konfiguracyjne Firebase

Po kliknięciu opcji Zarejestruj aplikację zostanie wyświetlony monit o pobranie dwóch plików konfiguracyjnych (po jednym pliku konfiguracyjnym dla każdego celu kompilacji). Twój projekt Unity potrzebuje metadanych Firebase w tych plikach, aby połączyć się z Firebase.

  1. Pobierz oba dostępne pliki konfiguracyjne:
    • Dla Apple (iOS) : pobierz plik GoogleService-Info.plist .
    • Dla Androida : pobierz plik google-services.json .
  2. Otwórz okno Projekt swojego projektu Unity, a następnie przenieś oba pliki konfiguracyjne do folderu Zasoby .
  3. Wróć do konsoli Firebase, w procesie konfiguracji kliknij Dalej i przejdź do Dodaj zestawy SDK Firebase dla Unity.

Dodaj pakiety SDK Firebase dla Unity

  1. Kliknij opcję Pobierz pakiet SDK Firebase Unity w konsoli Firebase.
  2. Rozpakuj SDK w dogodnym miejscu.
  3. W otwartym projekcie Unity przejdź do opcji Zasoby > Importuj pakiet > Pakiet niestandardowy .
  4. W oknie dialogowym Importuj pakiet przejdź do katalogu zawierającego rozpakowany pakiet SDK, wybierz FirebaseAnalytics.unitypackage i kliknij Otwórz .
  5. W wyświetlonym oknie dialogowym Importuj pakiet Unity kliknij opcję Importuj .
  6. Powtórz poprzednie kroki, aby zaimportować FirebaseCrashlytics.unitypackage .
  7. Wróć do konsoli Firebase i w procesie konfiguracji kliknij Dalej .

Aby uzyskać więcej informacji na temat dodawania zestawów SDK Firebase do projektów Unity, zobacz Dodatkowe opcje instalacji Unity .

4. Skonfiguruj Crashlytics w swoim projekcie Unity

Aby używać Crashlytics w projektach Unity, musisz wykonać kilka dodatkowych kroków konfiguracyjnych. Oczywiście będziesz musiał zainicjować zestaw SDK. Ale musisz także przesłać swoje symbole, aby zobaczyć symboliczne ślady stosu w konsoli Firebase, i musisz wymusić awarię testową, aby upewnić się, że Firebase otrzymuje zdarzenia awarii.

Zainicjuj zestaw SDK Crashlytics

  1. W Assets/Hamster/Scripts/MainGame.cs dodaj następujące instrukcje using :
    using Firebase.Crashlytics;
    using Firebase.Extensions;
    
    Pierwszy moduł umożliwia korzystanie z metod z pakietu Crashlytics SDK, a drugi zawiera pewne rozszerzenia interfejsu API zadań C# . Bez obu instrukcji using poniższy kod nie będzie działać.
  2. Nadal w MainGame.cs dodaj inicjalizację Firebase do istniejącej metody Start() , wywołując InitializeFirebaseAndStartGame() :
    void Start()
    {
      Screen.SetResolution(Screen.width / 2, Screen.height / 2, true);
      InitializeFirebaseAndStartGame();
    }
    
  3. I ponownie w MainGame.cs znajdź InitializeFirebaseAndStartGame() , zadeklaruj zmienną aplikacji, a następnie nadpisz implementację metody w następujący sposób:
    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");
          }
        });
    }
    

Umieszczenie tutaj logiki inicjalizacji uniemożliwia interakcję gracza przed zainicjowaniem zależności Firebase.

Korzyści i skutki zgłaszania nieobsłużonych wyjątków jako krytycznych omówiono w często zadawanych pytaniach dotyczących Crashlytics .

Zbuduj swój projekt i prześlij symbole

Kroki tworzenia i przesyłania symboli są różne w przypadku aplikacji na iOS i Androida.

iOS+ (platforma Apple)

  1. W oknie dialogowym Ustawienia kompilacji wyeksportuj projekt do obszaru roboczego Xcode.
  2. Zbuduj swoją aplikację.
    W przypadku platform Apple wtyczka Firebase Unity Editor automatycznie konfiguruje projekt Xcode w celu wygenerowania i przesłania pliku symboli zgodnego z Crashlytics na serwery Firebase dla każdej kompilacji. Te informacje o symbolach są wymagane, aby zobaczyć symboliczne ślady stosu na pulpicie nawigacyjnym Crashlytics.

Android

  1. (tylko podczas początkowej konfiguracji, nie dla każdej kompilacji) Skonfiguruj swoją kompilację:
    1. Utwórz nowy folder o nazwie Builds w katalogu głównym katalogu projektu (tj. jako element równorzędny katalogu Assets ), a następnie utwórz podfolder o nazwie Android .
    2. W Plik > Ustawienia kompilacji > Ustawienia odtwarzacza > Konfiguracja ustaw Zaplecze skryptowe na IL2CPP.
      • IL2CPP generalnie powoduje, że kompilacje są mniejsze i mają lepszą wydajność.
      • IL2CPP jest także JEDYNĄ dostępną opcją na iOS i wybranie jej tutaj pozwala na lepszą parzystość obu platform i upraszcza debugowanie różnic między nimi (jeśli zdecydujesz się zbudować obie).
  2. Zbuduj swoją aplikację. W menu Plik > Ustawienia kompilacji wykonaj następujące czynności:
    1. Upewnij się, że opcja Utwórz symbols.zip jest zaznaczona (lub jeśli jest wyświetlana lista rozwijana, wybierz opcję Debugowanie ).
    2. Zbuduj swój plik APK bezpośrednio z edytora Unity w utworzonym właśnie podfolderze Builds/Android .
  3. Po zakończeniu kompilacji musisz wygenerować plik symboli zgodny z Crashlytics i przesłać go na serwery Firebase. Te informacje o symbolach są wymagane, aby w panelu kontrolnym Crashlytics wyświetlić symboliczne ślady stosu w przypadku awarii bibliotek natywnych.

    Wygeneruj i prześlij ten plik symboli, uruchamiając następujące polecenie CLI Firebase :
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
    • FIREBASE_APP_ID : Twój identyfikator aplikacji Firebase na Androida (nie nazwa pakietu). Znajdź tę wartość w pobranym wcześniej pliku google-services.json . Jest to wartość mobilesdk_app_id .
      Przykładowy identyfikator aplikacji Firebase na Androida: 1:567383003300:android:17104a2ced0c9b9b
    • PATH/TO/SYMBOLS : ścieżka spakowanego pliku symboli wygenerowanego w katalogu Builds/Android po zakończeniu kompilacji (na przykład: Builds/Android/myapp-1.0-v100.symbols.zip ).

Wymuś awarię testową, aby zakończyć konfigurację

Aby dokończyć konfigurowanie Crashlytics i zobaczyć początkowe dane w panelu kontrolnym Crashlytics konsoli Firebase, musisz wymusić awarię testową.

  1. W MainGameScene znajdź pusty GameObject w edytorze Hierarchy , dodaj do niego następujący skrypt, a następnie zapisz scenę. Ten skrypt spowoduje awarię testową kilka sekund po uruchomieniu aplikacji.
    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. Zbuduj aplikację i prześlij informacje o symbolach po zakończeniu kompilacji.
    • iOS : wtyczka Firebase Unity Editor automatycznie konfiguruje projekt Xcode w celu przesłania pliku symboli.
    • Android : Uruchom crashlytics:symbols:upload interfejsu Firebase CLI, aby przesłać plik symboli.
  3. Uruchom swoją aplikację. Po uruchomieniu aplikacji przejrzyj dziennik urządzenia i poczekaj na wyzwolenie wyjątku z CrashlyticsTester .
    • iOS : Wyświetl dzienniki w dolnym panelu Xcode.
    • Android : Wyświetl logi, uruchamiając następującą komendę w terminalu: adb logcat .
  4. Odwiedź panel Crashlytics , aby zobaczyć wyjątek! Zobaczysz to w tabeli Problemy u dołu pulpitu nawigacyjnego. W dalszej części zajęć z programowania dowiesz się więcej o tym, jak eksplorować te raporty.
  5. Po potwierdzeniu, że wydarzenie zostało przesłane do Crashlytics, wybierz pusty obiekt GameObject do którego zostało dołączone, usuń tylko komponent CrashlyticsTester , a następnie zapisz scenę, aby przywrócić ją do pierwotnego stanu.

5. Włącz i zrozum menu debugowania

Jak dotąd dodałeś Crashlytics do swojego projektu Unity, zakończyłeś konfigurację i potwierdziłeś, że pakiet SDK Crashlytics przesyła zdarzenia do Firebase. Utworzysz teraz menu w swoim projekcie Unity, które pokaże, jak używać bardziej zaawansowanych funkcji Crashlytics w swojej grze. Projekt Level Up with Firebase Unity ma już ukryte menu debugowania, które udostępnisz jako widoczne i napiszesz dla niego funkcjonalność.

Włącz menu debugowania

Przycisk umożliwiający dostęp do menu debugowania istnieje w projekcie Unity, ale obecnie nie jest włączony. Musisz włączyć przycisk, aby uzyskać do niego dostęp z prefabrykatu MainMenu :

  1. W edytorze Unity otwórz prefabrykat o nazwie MainMenu . 4148538cbe9f36c5.png
  2. W hierarchii prefabrykatów znajdź wyłączony obiekt podrzędny o nazwie DebugMenuButton , a następnie wybierz go. 816f8f9366280f6c.png
  3. Włącz DebugMenuButton , zaznaczając pole w lewym górnym rogu po lewej stronie pola tekstowego zawierającego DebugMenuButton . 8a8089d2b4886da2.png
  4. Zapisz prefabrykat.
  5. Uruchom grę w edytorze lub na swoim urządzeniu. Menu powinno być teraz dostępne.

Wyświetl podgląd i zapoznaj się z treściami metod dla menu debugowania

W dalszej części tego ćwiczenia z programowania napiszesz treści metod dla niektórych wstępnie skonfigurowanych metod debugowania Crashlytics. Jednak w projekcie Level Up with Firebase Unity metody są zdefiniowane i wywoływane w DebugMenu.cs .

Chociaż niektóre z tych metod będą zarówno wywoływać metody Crashlytics, jak i zgłaszać błędy, zdolność Crashlytics do wychwytywania tych błędów nie zależy od wcześniejszego wywołania tych metod. Zamiast tego raporty o awariach generowane na podstawie automatycznie wychwytujących błędów zostaną wzbogacone o informacje dodane za pomocą tych metod.

Otwórz DebugMenu.cs , a następnie znajdź następujące metody:

Metody generowania i opisywania problemów z Crashlytics:

  • CrashNow
  • LogNonfatalError
  • LogStringsAndCrashNow
  • SetAndOverwriteCustomKeyThenCrash
  • SetLogsAndKeysBeforeANR

Metody rejestrowania zdarzeń Analytics w celu ułatwienia debugowania:

  • LogProgressEventWithStringLiterals
  • LogIntScoreWithBuiltInEventAndParams

W późniejszych etapach tego ćwiczenia z programowania zaimplementujesz te metody i dowiesz się, jak pomagają one radzić sobie z konkretnymi sytuacjami, które mogą wystąpić podczas tworzenia gier.

6. Zapewnij dostarczanie raportów o awariach w fazie rozwoju

Zanim zaczniesz wdrażać te metody debugowania i zobaczysz, jak wpływają one na raporty o awariach, upewnij się, że rozumiesz, w jaki sposób zdarzenia są zgłaszane do Crashlytics.

W przypadku projektów Unity zdarzenia awarii i wyjątków w grze są natychmiast zapisywane na dysku. W przypadku nieprzechwyconych wyjątków, które nie powodują awarii gry (na przykład nieprzechwyconych wyjątków C# w logice gry), zestaw Crashlytics SDK może zgłosić je jako zdarzenia krytyczne, ustawiając właściwość Crashlytics.ReportUncaughtExceptionsAsFatal na true w miejscu inicjowania Crashlytics w projekcie Unity . Zdarzenia te są zgłaszane do Crashlytics w czasie rzeczywistym, bez konieczności ponownego uruchamiania gry przez użytkownika końcowego. Należy pamiętać, że awarie natywne są zawsze zgłaszane jako zdarzenia krytyczne i wysyłane, gdy użytkownik końcowy ponownie uruchamia grę.

Ponadto należy pamiętać o następujących małych, ale znaczących różnicach między sposobem, w jaki różne środowiska wykonawcze wysyłają informacje Crashlytics do Firebase:

Symulator iOS:

  • Informacje Crashlytics są raportowane wtedy i tylko wtedy, gdy odłączysz Xcode od symulatora. Jeśli dołączony jest Xcode, wychwytuje błędy powyżej, uniemożliwiając dostarczenie informacji.

Mobilne urządzenia fizyczne (Android i iOS):

  • Dotyczy Androida: błędy ANR są raportowane tylko w przypadku Androida 11 lub nowszego. Błędy ANR i zdarzenia inne niż śmiertelne są zgłaszane w następnym przebiegu.

Redaktor Jedności:

Przetestuj zawieszanie gry jednym naciśnięciem przycisku w CrashNow()

Po skonfigurowaniu Crashlytics w grze pakiet Crashlytics SDK automatycznie rejestruje awarie i nieprzechwycone wyjątki i przesyła je do Firebase w celu analizy. Raporty są wyświetlane w panelu kontrolnym Crashlytics w konsoli Firebase.

  1. Aby zademonstrować, że jest to rzeczywiście automatyczne: otwórz DebugMenu.cs , a następnie zastąp metodę CrashNow() w następujący sposób:
    void CrashNow()
    {
        TestCrash();
    }
    
  2. Zbuduj swoją aplikację.
  3. (Tylko Android) Prześlij swoje symbole, uruchamiając następujące polecenie CLI Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Naciśnij przycisk Awaria teraz i przejdź do następnego kroku ćwiczeń z programowania, aby dowiedzieć się, jak wyświetlić i zinterpretować raport o awarii.

7. Zapoznaj się z raportami problemów w konsoli Firebase

Jeśli chodzi o przeglądanie raportów o awariach, musisz dowiedzieć się nieco więcej o tym, jak w pełni je wykorzystać. Każda z opisanych przez Ciebie metod pokaże, jak dodać różne typy informacji do raportów Crashlytics.

  1. Stuknij przycisk Awaria teraz , a następnie uruchom ponownie aplikację.
  2. Przejdź do panelu Crashlytics . Przewiń w dół do tabeli Problemy na dole panelu, gdzie Crashlytics grupuje zdarzenia o tej samej pierwotnej przyczynie w „problemy”.
  3. Kliknij nowy problem wymieniony w tabeli Problemy . Spowoduje to wyświetlenie podsumowania każdego pojedynczego zdarzenia wysłanego do Firebase.

    Powinieneś zobaczyć coś takiego jak poniższy zrzut ekranu. Zwróć uwagę, że podsumowanie zdarzenia wyraźnie przedstawia ślad stosu wywołania, które doprowadziło do awarii. 40c96abe7f90c3aa.png

Dodatkowe metadane

Kolejną pomocną zakładką jest zakładka Metadane Unity . Ta sekcja informuje o atrybutach urządzenia, na którym miało miejsce zdarzenie, w tym o cechach fizycznych, modelu/specyfikacjach procesora i wszelkiego rodzaju metrykach GPU.

Oto przykład, w którym informacje zawarte na tej karcie mogą być przydatne:
Wyobraź sobie, że Twoja gra w dużym stopniu wykorzystuje moduły cieniujące, aby uzyskać określony wygląd, ale nie wszystkie telefony mają procesory graficzne zdolne do renderowania tej funkcji. Informacje na karcie Metadane Unity mogą dać ci lepszy pogląd na to, pod kątem jakiego sprzętu Twoja aplikacja powinna przetestować, decydując, które funkcje mają zostać automatycznie udostępnione lub całkowicie wyłączone.

Chociaż błąd lub awaria może nigdy nie wystąpić na Twoim urządzeniu, ze względu na ogromną różnorodność urządzeń z Androidem na wolności, pomaga to lepiej zrozumieć poszczególne „hotspoty” na urządzeniach Twoich odbiorców.

41d8d7feaa87454d.png

8. Rzuć, złap i zarejestruj wyjątek

Często jako programista, nawet jeśli Twój kod prawidłowo przechwytuje i obsługuje wyjątek czasu wykonania, warto zauważyć, że do takiego zdarzenia doszło i w jakich okolicznościach. Crashlytics.LogException można wykorzystać dokładnie w tym celu — aby wysłać zdarzenie wyjątku do Firebase, aby można było dalej debugować problem w konsoli Firebase.

  1. W Assets/Hamster/Scripts/States/DebugMenu.cs dołącz następujące instrukcje do instrukcji using :
    // Import Firebase
    using Firebase.Crashlytics;
    
  2. Nadal w DebugMenu.cs zastąp LogNonfatalError() w następujący sposób:
    void LogNonfatalError()
    {
        try
        {
            throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}");
        }
        catch(System.Exception exception)
        {
            Crashlytics.LogException(exception);
        }
    }
    
  3. Zbuduj swoją aplikację.
  4. (Tylko Android) Prześlij swoje symbole, uruchamiając następujące polecenie CLI Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  5. Stuknij przycisk Zarejestruj błąd niekrytyczny , a następnie uruchom ponownie aplikację.
  6. Przejdź do panelu Crashlytics i powinieneś zobaczyć coś podobnego do tego, co widziałeś w ostatnim kroku tego ćwiczenia z kodowania.
  7. Tym razem jednak ogranicz filtr typu zdarzenia do zdarzeń niekrytycznych , aby wyświetlać tylko błędy niekrytyczne, takie jak ten, który właśnie zarejestrowałeś.
    a39ea8d9944cbbd9.png

9. Rejestruj ciągi znaków w Crashlytics, aby lepiej zrozumieć przebieg wykonywania programu

Czy próbowałeś kiedyś dowiedzieć się, dlaczego wiersz kodu wywoływany z wielu ścieżek setki, jeśli nie tysiące razy na sesję, może nagle wygenerować wyjątek lub spowodować awarię? Chociaż miło byłoby przejrzeć kod w IDE i przyjrzeć się bliżej wartościom, co jednak, jeśli zdarza się to tylko wśród znikomo małego odsetka użytkowników? Co gorsza, co byś zrobił, gdybyś nie mógł odtworzyć tej awarii bez względu na to, co byś zrobił?

W takich sytuacjach posiadanie kontekstu może zrobić ogromną różnicę. Dzięki Crashlytics.Log masz możliwość zapisania potrzebnego kontekstu. Potraktuj te wiadomości jako wskazówki dla siebie w przyszłości na temat tego, co może się wydarzyć.

Chociaż dzienniki można wykorzystywać na wiele sposobów, zazwyczaj są one najbardziej przydatne do rejestrowania sytuacji, w których kolejność i/lub brak połączeń jest niezwykle ważną informacją.

  1. W Assets/Hamster/Scripts/States/DebugMenu.cs zastąp LogStringsAndCrashNow() w następujący sposób:
    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. Zbuduj swoją aplikację.
  3. (Tylko Android) Prześlij swoje symbole, uruchamiając następujące polecenie CLI Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Stuknij przycisk Loguj ciągi i awarię teraz , a następnie uruchom ponownie aplikację.
  5. Wróć do panelu Crashlytics i kliknij najnowszy problem wymieniony w tabeli Problemy . Ponownie powinieneś zobaczyć coś podobnego do poprzednich problemów.
    7aabe103b8589cc7.png
  6. Jeśli jednak klikniesz kartę Dzienniki w podsumowaniu wydarzenia , wyświetli się taki widok:
    4e27aa407b7571cf.png

10. Zapisz i zastąp klucz niestandardowy

Załóżmy, że chcesz lepiej zrozumieć awarię odpowiadającą zmiennym ustawionym na niewielką liczbę wartości lub konfiguracji. Przydatna może być możliwość filtrowania w dowolnym momencie na podstawie kombinacji zmiennych i możliwych wartości, na które patrzysz.

Oprócz rejestrowania dowolnych ciągów znaków Crashlytics oferuje inną formę debugowania, gdy warto znać dokładny stan programu w momencie awarii: klucze niestandardowe.

Są to pary klucz-wartość, które można ustawić dla sesji. W przeciwieństwie do dzienników, które gromadzą się i mają charakter czysto addytywny, klucze można nadpisywać, aby odzwierciedlały jedynie najnowszy stan zmiennej lub warunku.

Oprócz tego, że są rejestrem ostatniego zarejestrowanego stanu programu, klucze te mogą być następnie używane jako zaawansowane filtry problemów z Crashlytics.

  1. W Assets/Hamster/Scripts/States/DebugMenu.cs zastąp SetAndOverwriteCustomKeyThenCrash() w następujący sposób:
    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. Zbuduj swoją aplikację.
  3. (Tylko Android) Prześlij swoje symbole, uruchamiając następujące polecenie CLI Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Stuknij przycisk Ustaw klucz niestandardowy i awarię , a następnie uruchom ponownie aplikację.
  5. Wróć do panelu Crashlytics i kliknij najnowszy problem wymieniony w tabeli Problemy . Ponownie powinieneś zobaczyć coś podobnego do poprzednich problemów.
  6. Tym razem jednak kliknij zakładkę Klucze w podsumowaniu wydarzenia , aby wyświetlić wartość kluczy, w tym Current Time :
    7dbe1eb00566af98.png

Dlaczego chcesz używać niestandardowych kluczy zamiast niestandardowych dzienników?

  • Dzienniki dobrze przechowują dane sekwencyjne, ale klucze niestandardowe są lepsze, jeśli chcesz tylko najnowszą wartość.
  • W konsoli Firebase możesz łatwo filtrować problemy według wartości kluczy w polu wyszukiwania tabeli problemów .

Jednak podobnie jak dzienniki, klucze niestandardowe mają limit. Crashlytics obsługuje maksymalnie 64 pary klucz-wartość. Po osiągnięciu tego progu dodatkowe wartości nie są zapisywane. Każda para klucz-wartość może mieć rozmiar do 1 KB.

11. (Tylko Android) Użyj niestandardowych kluczy i dzienników, aby zrozumieć i zdiagnozować błąd ANR

Jedną z najtrudniejszych do debugowania klas problemów dla programistów Androida jest błąd ANR ( Aplikacja nie odpowiada ). Błędy ANR występują, gdy aplikacja nie odpowiada na wprowadzane dane przez ponad 5 sekund. Jeśli tak się stanie, oznacza to, że aplikacja albo się zawiesiła, albo działa bardzo wolno. Użytkownikom wyświetla się okno dialogowe, w którym mogą wybrać, czy chcą „Czekać”, czy „Zamknąć aplikację”.

Błędy ANR są niekorzystne dla użytkownika i (jak wspomniano w linku ANR powyżej) mogą mieć wpływ na wykrywalność Twojej aplikacji w Sklepie Google Play. Ze względu na ich złożoność i ponieważ często są spowodowane wielowątkowym kodem o bardzo różnym zachowaniu w różnych modelach telefonów, odtwarzanie błędów ANR podczas debugowania jest często bardzo trudne, jeśli nie prawie niemożliwe. Dlatego najlepszym podejściem jest podejście do nich analitycznie i dedukcyjnie.

W tej metodzie użyjemy kombinacji Crashlytics.LogException , Crashlytics.Log i Crashlytics.SetCustomKey w celu uzupełnienia automatycznego rejestrowania problemów i dostarczenia nam większej ilości informacji.

  1. W Assets/Hamster/Scripts/States/DebugMenu.cs zastąp SetLogsAndKeysBeforeANR() w następujący sposób:
    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. Zbuduj swoją aplikację.
  3. Prześlij swoje symbole, uruchamiając następujące polecenie CLI Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Naciśnij przycisk Ustaw dzienniki i klucze → ANR , a następnie uruchom ponownie aplikację.
  5. Wróć do panelu Crashlytics , a następnie kliknij nowy problem w tabeli Problemy , aby wyświetlić podsumowanie zdarzenia . Jeśli połączenie przebiegło prawidłowo, powinieneś zobaczyć coś takiego:
    876c3cff7037bd07.png

    Jak widać, Firebase wskazał zajęte oczekiwanie na wątek jako główny powód, dla którego Twoja aplikacja wywołała błąd ANR.
  6. Jeśli spojrzysz na logi na karcie Dzienniki podsumowania zdarzeń , zobaczysz, że ostatnią metodą zarejestrowaną jako ukończoną jest DoSevereWork .
    5a4bec1cf06f6984.png

    Natomiast ostatnią metodą wymienioną jako początkową jest DoExtremeWork , która wskazuje, że podczas tej metody wystąpił błąd ANR, a gra została zamknięta, zanim zdążyła zarejestrować DoExtremeWork .

    89d86d5f598ecf3a.png

Czemu to robić?

  • Odtwarzanie błędów ANR jest niezwykle trudne, dlatego możliwość uzyskania bogatych informacji o obszarze kodu i metrykach jest niezwykle ważna dla znalezienia ich w sposób dedukcyjny.
  • Dzięki informacjom przechowywanym w kluczach niestandardowych wiesz teraz, który wątek asynchroniczny działał najdłużej, a któremu groziło wyzwolenie błędów ANR. Tego rodzaju powiązane dane logiczne i numeryczne pokażą Ci, gdzie w kodzie najbardziej wymagana jest optymalizacja.

12. Przeplatanie zdarzeń Analytics w celu dalszego wzbogacania raportów

Poniższe metody można również wywołać z menu debugowania, ale zamiast same generować problemy, wykorzystują Google Analytics jako kolejne źródło informacji, które pozwala lepiej zrozumieć działanie Twojej gry.

W przeciwieństwie do innych metod napisanych w tym laboratorium z kodowania, należy używać tych metod w połączeniu z innymi. Wywołuj te metody (naciskając odpowiedni przycisk w menu debugowania) w dowolnej kolejności, zanim uruchomisz jedną z pozostałych. Następnie, gdy sprawdzisz informacje dotyczące konkretnego problemu z Crashlytics, zobaczysz uporządkowany dziennik zdarzeń Analytics. Dane te można wykorzystać w grze, aby lepiej zrozumieć kombinację przebiegu programu lub wkładu użytkownika, w zależności od sposobu instrumentacji aplikacji.

  1. W Assets/Hamster/Scripts/States/DebugMenu.cs zastąp istniejące implementacje następujących metod:
    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. Zbuduj i wdróż swoją grę, a następnie wejdź do menu debugowania .
  3. (Tylko Android) Prześlij swoje symbole, uruchamiając następujące polecenie CLI Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Aby wywołać powyższe funkcje, naciśnij przynajmniej jeden z poniższych przycisków:
    • Rejestruj zdarzenie ciągu
    • Zaloguj zdarzenie wewnętrzne
  5. Naciśnij przycisk Awaria teraz .
  6. Uruchom ponownie grę, aby przesłać zdarzenie awarii do Firebase.
  7. Kiedy rejestrujesz różne dowolne sekwencje zdarzeń Analytics, a następnie gra generuje zdarzenie, na podstawie którego Crashlytics tworzy raport (tak jak to właśnie robisz), są one dodawane do karty Dzienniki w podsumowaniu zdarzeń Crashlytics w następujący sposób:
    d3b16d78f76bfb04.png

13. Idąc dalej

Dzięki temu powinieneś mieć lepszą podstawę teoretyczną, na której możesz uzupełnić automatycznie generowane raporty o awariach. Te nowe informacje umożliwiają wykorzystanie bieżącego stanu, zapisów przeszłych zdarzeń i istniejących zdarzeń Google Analytics w celu lepszego rozbicia sekwencji zdarzeń i logiki, która doprowadziła do ich wyniku.

Jeśli Twoja aplikacja jest przeznaczona dla systemu Android 11 (poziom interfejsu API 30) lub nowszego, rozważ zastosowanie GWP-ASan , natywnej funkcji alokatora pamięci przydatnej do debugowania awarii spowodowanych błędami pamięci natywnej, takimi jak błędy use-after-free i heap-buffer-overflow . Aby skorzystać z tej funkcji debugowania, jawnie włącz GWP-ASan .

Następne kroki

Przejdź do gry Instrument your Unity with Remote Config , gdzie dowiesz się, jak używać zdalnej konfiguracji i testów A/B w Unity.