Awarie w grach na Unity przy użyciu zaawansowanych funkcji Crashlytics

1. Wprowadzenie

Dzięki tym ćwiczeniom w Codelabs dowiesz się, jak korzystać z zaawansowanych funkcji Crashlytics, które zapewniają lepszy wgląd w awarie i o potencjalnych przyczynach.

Do przykładowej gry MechaHamster: kolejny poziom w wersji Firebase dodasz nową funkcję. Ta przykładowa gra to nowa wersja klasycznej gry Firebase MechaHamster, która usuwa większość wbudowanych funkcji Firebase, dzięki czemu możesz wdrożyć nowe zastosowania Firebase zamiast niej.

Dodasz do gry menu debugowania. To menu debugowania wywołuje utworzone przez Ciebie metody i umożliwia korzystanie z różnych funkcji Crashlytics. Dzięki tym metodom dowiesz się, jak dodawać adnotacje do automatycznych raportów o awariach za pomocą m.in. kluczy niestandardowych i dzienników niestandardowych oraz błędów niekrytycznych.

Po skompilowaniu gry będziesz korzystać z menu debugowania, a potem sprawdzać wyniki, aby poznać unikalny widok, jaki zapewnia gra w środowisku naturalnym.

Czego się nauczysz

  • Typy błędów wykrywanych automatycznie przez Crashlytics.
  • Inne błędy, które mogą być rejestrowane.
  • Jak dodać do tych błędów więcej informacji, aby były bardziej zrozumiałe.

Czego potrzebujesz

  • Unity (minimalna wersja zalecana w wersji 2019 lub nowszej) z co najmniej jedną z tych wersji:
    • Obsługa kompilacji na iOS
    • Obsługa kompilacji Androida
  • (Tylko Android) Interfejs wiersza poleceń Firebase (używany do przesyłania symboli na potrzeby raportów o awariach)

2. Konfigurowanie środowiska programistycznego

W poniższych sekcjach opisano, jak pobrać kod Kolejny poziom dzięki Firebase i otworzyć go w Unity.

Uwaga: ta przykładowa gra typu Przejdź na kolejny poziom z Firebase jest już używana w kilku innych laboratoriach z programowania Firebase i Unity, więc być może masz już za sobą zadania z tej sekcji. Jeśli tak, możesz przejść bezpośrednio do ostatniego kroku na tej stronie: „Dodaj pakiety SDK Firebase dla Unity”.

Pobieranie kodu

Skopiuj repozytorium GitHub tego ćwiczenia z programowania za pomocą wiersza poleceń:

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

Jeśli nie masz zainstalowanej aplikacji git, możesz pobrać repozytorium jako plik ZIP.

Otwórz Przejdź na wyższy poziom dzięki Firebase w edytorze Unity

  1. Uruchom Unity Hub i na karcie Projects (Projekty) kliknij strzałkę w dół obok opcji Open (Otwórz).
  2. Kliknij Dodaj projekt z dysku.
  3. Przejdź do katalogu zawierającego kod i kliknij OK.
  4. Jeśli pojawi się taka prośba, wybierz wersję edytora Unity, której chcesz użyć, oraz platformę docelową (Android lub iOS).
  5. Kliknij nazwę projektu level-up-with-firebase, aby otworzyć projekt w edytorze Unity.
  6. Jeśli edytor nie otworzy się automatycznie, otwórz MainGameScene w sekcji Zasoby > Hamster (Hamster) na karcie Project (Projekt) w edytorze Unity.
    ff4ea3f3c0d29379.png

Więcej informacji o instalowaniu i używaniu Unity znajdziesz w artykule Praca w Unity.

3. Dodaj Firebase do projektu Unity

Tworzenie projektu Firebase

  1. W konsoli Firebase kliknij Dodaj projekt.
  2. Aby utworzyć nowy projekt, wpisz odpowiednią nazwę.
    Spowoduje to również ustawienie identyfikatora projektu (wyświetlanego pod nazwą projektu) na podstawie nazwy projektu. Opcjonalnie możesz kliknąć ikonę edytuj przy identyfikatorze projektu, aby jeszcze bardziej go dostosować.
  3. W razie potrzeby przeczytaj i zaakceptuj warunki korzystania z Firebase.
  4. Kliknij Dalej.
  5. Wybierz opcję Włącz Google Analytics dla tego projektu, a potem kliknij Dalej.
  6. Wybierz istniejące konto Google Analytics, którego chcesz użyć, lub kliknij Utwórz nowe konto, aby utworzyć nowe konto.
  7. Kliknij Utwórz projekt.
  8. Po utworzeniu projektu kliknij Dalej.

Zarejestruj aplikację w Firebase

  1. Nie wychodząc z konsoli Firebase, na środku strony przeglądu projektu kliknij ikonę Unity, aby uruchomić przepływ pracy konfiguracji. Jeśli aplikacja została już dodana do projektu Firebase, kliknij Dodaj aplikację, aby wyświetlić opcje platformy.
  2. Wybierz, aby zarejestrować cele kompilacji dla Apple (iOS) i Androida.
  3. Wpisz identyfikatory platformy projektu Unity. W ramach tego ćwiczenia w Codelabs wpisz następujące informacje:
  4. (Opcjonalnie) Wpisz pseudonimy związane z platformą projektu Unity.
  5. Kliknij Zarejestruj aplikację, a następnie przejdź do sekcji Pobierz plik konfiguracyjny.

Dodaj pliki konfiguracji Firebase

Po kliknięciu Zarejestruj aplikację wyświetli się prośba o pobranie 2 plików konfiguracji (po 1 pliku konfiguracji dla każdego celu kompilacji). Twój projekt w Unity wymaga metadanych Firebase w tych plikach, aby połączyć się z Firebase.

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

Dodaj pakiety SDK Firebase dla Unity

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

Więcej informacji o dodawaniu pakietów SDK Firebase do projektów Unity znajdziesz w artykule Dodatkowe opcje instalacji Unity.

4. Konfigurowanie Crashlytics w projekcie Unity

Aby używać Crashlytics w projektach w Unity, musisz wykonać jeszcze kilka czynności konfiguracyjnych. Oczywiście musisz zainicjować pakiet SDK. Musisz też jednak przesłać symbole, aby w konsoli Firebase zobaczyć symbolizowane zrzuty stosu, a także wymusić awarię testową, aby upewnić się, że Firebase otrzymuje zdarzenia awarii.

Inicjowanie pakietu SDK Crashlytics

  1. W polu Assets/Hamster/Scripts/MainGame.cs dodaj te oświadczenia using:
    using Firebase.Crashlytics;
    using Firebase.Extensions;
    
    W pierwszym module możesz korzystać z metod z pakietu SDK Crashlytics, a drugi zawiera rozszerzenia C# Tasks API. Bez obu instrukcji using poniższy kod nie będzie działać.
  2. Będąc w aplikacji MainGame.cs, dodaj inicjalizację Firebase do istniejącej metody Start(), wywołując metodę InitializeFirebaseAndStartGame():
    void Start()
    {
      Screen.SetResolution(Screen.width / 2, Screen.height / 2, true);
      InitializeFirebaseAndStartGame();
    }
    
  3. Ponownie w elemencie MainGame.cs znajdź pole InitializeFirebaseAndStartGame(), zadeklaruj zmienną aplikacji, a potem zastąp implementację metody w ten 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 inicjowania zapobiega interakcji z odtwarzaczem przed zainicjowaniem zależności Firebase.

Korzyści i efekty zgłaszania nieobsłużonych wyjątków jako krytycznych omówiono w najczęstszych pytaniach dotyczących Crashlytics.

Tworzenie projektu i przesyłanie symboli

Proces tworzenia i przesyłania symboli różni się w zależności od aplikacji na iOS i Androida.

iOS+ (platforma Apple)

  1. W oknie Build Settings (Ustawienia kompilacji) wyeksportuj swój projekt do obszaru roboczego Xcode.
  2. Utwórz aplikację.
    Na platformach Apple wtyczka Firebase Unity Editor automatycznie konfiguruje projekt Xcode tak, aby w przypadku każdej kompilacji generował i przesyłał plik symboli zgodny z Crashlytics na serwery Firebase. Te informacje o symbolach są wymagane, aby w panelu Crashlytics można było zobaczyć zrzuty stosu z symbolami.

Android

  1. (tylko podczas wstępnej konfiguracji, nie dla każdej kompilacji) Skonfiguruj kompilację:
    1. Utwórz nowy folder o nazwie Kompilacje w katalogu głównym projektu (np. jako folder równorzędny z katalogiem Assets), a następnie utwórz podfolder o nazwie Android.
    2. W sekcji Plik > Ustawienia kompilacji > Ustawienia odtwarzacza > Configuration (Konfiguracja), ustaw Backend dla skryptów na IL2CPP.
      • IL2CPP zazwyczaj sprawia, że kompilacje są mniejsze i mają większą wydajność.
      • IL2CPP jest też jedyną dostępną opcją w systemie iOS. Wybranie jej tutaj sprawia, że 2 platformy są bardziej spójne i upraszczają debugowanie w przypadku różnic między tymi platformami (jeśli postanowisz je utworzyć).
  2. Utwórz aplikację. W sekcji Plik > Ustawienia kompilacji, wykonaj te czynności:
    1. Upewnij się, że opcja Utwórz symbole.zip jest zaznaczona (lub wybierz Debugowanie, jeśli wyświetli się menu).
    2. Utwórz plik APK bezpośrednio z edytora Unity do utworzonego właśnie podfolderu Kompilacje/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 do wyświetlenia w panelu Crashlytics zrzutów stosu z symbolami w przypadku awarii biblioteki natywnej.

    Wygeneruj i prześlij plik symboli, uruchamiając to polecenie w interfejsie wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
    • FIREBASE_APP_ID: identyfikator aplikacji Firebase na Androida (nie nazwa pakietu). Tę wartość znajdziesz 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 skompresowanego pliku symboli wygenerowana w katalogu Kompilacje/Android po zakończeniu kompilacji (np. Builds/Android/myapp-1.0-v100.symbols.zip).

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

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

  1. W sekcji MainGameScene w edytorze Hierarchia znajdź EmptyObjectGameObject, dodaj do niego poniższy skrypt i 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. Po zakończeniu kompilacji utwórz aplikację i prześlij informacje o symbolach.
    • iOS: Wtyczka Firebase Unity Editor automatycznie konfiguruje projekt Xcode tak, aby przesyłał plik symboli.
    • Android: aby przesłać plik symboli, uruchom polecenie wiersza poleceń Firebase crashlytics:symbols:upload.
  3. Uruchom aplikację. Po uruchomieniu aplikacji obserwuj dziennik urządzenia i poczekaj na uruchomienie wyjątku z CrashlyticsTester.
    • iOS: logi możesz wyświetlać w dolnym panelu Xcode.
    • Android: aby wyświetlić dzienniki, uruchom w terminalu to polecenie: adb logcat.
  4. Otwórz panel Crashytics, aby wyświetlić wyjątek. Znajdziesz go w tabeli Problemy u dołu panelu. W dalszej części modułu Codelabs dowiesz się więcej o sposobie analizowania tych raportów.
  5. Po potwierdzeniu, że zdarzenie zostało przesłane do Crashlytics, wybierz EmptyObject GameObject, do którego zostało dołączone, usuń tylko komponent CrashlyticsTester, a następnie zapisz scenę, by przywrócić ją do pierwotnego stanu.

5. Włączanie i analizowanie menu debugowania

Do tej pory udało Ci się dodać Crashlytics do projektu w Unity, zakończyć konfigurację i potwierdzić, że pakiet SDK Crashlytics przesyła zdarzenia do Firebase. Utworzysz teraz menu w projekcie w Unity, które pokaże, jak korzystać z bardziej zaawansowanych funkcji Crashlytics w grze. Projekt Unity Kolejny poziom dzięki Firebase ma już ukryte menu debugowania, które będzie widoczne i dostępne, gdy będzie można opisać jego funkcje.

Włączanie menu debugowania

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

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

Wyświetlanie podglądu i analizowanie treści metod w menu debugowania

W dalszej części tego ćwiczenia w Codelabs dowiesz się, jak treść niektórych wstępnie skonfigurowanych metod debugowania Crashlytics. W projekcie Unity Kolejny poziom dzięki Firebase można jednak określać metody zdefiniowane w DebugMenu.cs i je wywoływać.

Choć niektóre z tych metod wywołują metody Crashlytics i powodują błędy, zdolność Crashlytics do wychwycenia tych błędów nie zależy od wcześniejszego wywołania tych metod. Raporty o awariach generowane w wyniku automatycznego wykrywania błędów są uzupełniane informacjami dodanymi przez te metody.

Otwórz DebugMenu.cs i znajdź następujące metody:

Metody generowania problemów z Crashlytics i dodawania do nich adnotacji:

  • CrashNow
  • LogNonfatalError
  • LogStringsAndCrashNow
  • SetAndOverwriteCustomKeyThenCrash
  • SetLogsAndKeysBeforeANR

Metody rejestrowania zdarzeń Analytics, które ułatwiają debugowanie:

  • LogProgressEventWithStringLiterals
  • LogIntScoreWithBuiltInEventAndParams

W kolejnych krokach tego ćwiczenia z programowania wdrożysz te metody i dowiesz się, jak mogą pomóc w konkretnych sytuacjach, które mogą wystąpić na etapie tworzenia gier.

6. Zapewnianie dostarczania raportów o awariach w trakcie opracowywania

Zanim zaczniesz wdrażać te metody debugowania i sprawdzać, jak wpływają one na raporty o awariach, dowiedz się, jak zdarzenia są zgłaszane do Crashlytics.

W projektach Unity zdarzenia awarii i wyjątków w grze są natychmiast zapisywane na dysku. Jeśli masz niewyłapane wyjątki, które nie powodują awarii gry (np. niewyłapane wyjątki C# w logice gry), pakiet SDK Crashlytics może zgłaszać je jako zdarzenia krytyczne. W tym celu ustaw właściwość Crashlytics.ReportUncaughtExceptionsAsFatal na true i zainicjuj Crashlytics w projekcie Unity. Te zdarzenia są zgłaszane do Crashlytics w czasie rzeczywistym bez konieczności ponownego uruchomienia gry przez użytkownika. Pamiętaj, że awarie natywne są zawsze zgłaszane jako awarie i wysyłane, gdy użytkownik ponownie uruchomi grę.

Oprócz tego pamiętaj o następujących niewielkich, ale istotnych różnicach między sposobem wysyłania informacji z Crashlytics do Firebase przez różne środowiska wykonawcze:

Symulator iOS:

  • Informacje z Crashlytics są raportowane tylko po odłączeniu Xcode od symulatora. Jeśli dołączony jest kod Xcode, wykrywa błędy na wyższym poziomie, co uniemożliwia dostarczenie informacji.

Fizyczne urządzenia mobilne (Android i iOS):

  • W przypadku Androida: błędy ANR są zgłaszane tylko na urządzeniach z Androidem 11 i nowszym. Błędy ANR i zdarzenia niekrytyczne są raportowane przy następnym uruchomieniu.

Edytor Unity:

Przetestuj awarię gry po naciśnięciu przycisku w aplikacji CrashNow()

Po skonfigurowaniu Crashlytics w grze pakiet SDK Crashlytics automatycznie rejestruje awarie i nieobsłużone wyjątki oraz przesyła je do Firebase do analizy. Raporty wyświetlają się w panelu Crahlytics w konsoli Firebase.

  1. Aby udowodnić, że dzieje się to automatycznie, otwórz DebugMenu.cs, a następnie zastąp metodę CrashNow() w ten sposób:
    void CrashNow()
    {
        TestCrash();
    }
    
  2. Utwórz aplikację.
  3. (Tylko Android) Prześlij symbole, uruchamiając następujące polecenie interfejsu wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Kliknij przycisk Wypadek teraz i przejdź do następnego kroku tego ćwiczenia z programowania, aby dowiedzieć się, jak wyświetlać i interpretować raport o awariach.

7. Raporty o problemach w konsoli Firebase

Musisz dowiedzieć się więcej o wyświetlaniu raportów o awariach, by je w pełni wykorzystać. Każda z napisanych przez Ciebie metod pokaże, jak dodawać różne typy informacji do raportów Crashlytics.

  1. Kliknij przycisk Wywołaj teraz, a następnie ponownie uruchom aplikację.
  2. Otwórz panel Crashytics. Przewiń w dół do tabeli Problemy u dołu panelu. Crashlytics grupuje w „problemach” zdarzenia, które mają tę samą główną przyczynę.
  3. Kliknij nowy problem wymieniony w tabeli Problemy. Spowoduje to wyświetlenie podsumowania zdarzeń dla każdego pojedynczego zdarzenia wysłanego do Firebase.

    Powinno wyświetlić się mniej więcej taki zrzut ekranu. Zwróć uwagę, jak w Podsumowaniu zdarzenia wyraźnie widać zrzut stosu wywołania, które doprowadziło do awarii.40c96abe7f90c3aa.png

Dodatkowe metadane

Kolejna pomocna karta to Metadane Unity. W tej sekcji znajdziesz informacje o atrybutach urządzenia, na którym wystąpiło zdarzenie, w tym o funkcjach fizycznych, modelu i specyfikacjach procesora oraz wszelkich rodzajach wskaźników GPU.

Oto przykład informacji z tej karty:
Wyobraź sobie, że Twoja gra intensywnie używa cieniowania, aby uzyskać określony wygląd, ale nie wszystkie telefony mają procesory graficzne obsługujące tę funkcję. Informacje na karcie Metadane Unity pomogą Ci lepiej zrozumieć, na jakim sprzęcie będzie testowana Twoja aplikacja. Dzięki niej dowiesz się, które funkcje mają być automatycznie udostępniane lub całkowicie wyłączone.

O ile na urządzeniu nie dochodzi do błędów ani awarii, to jednak ze względu na ogromną różnorodność urządzeń z Androidem pomaga w lepszym poznaniu poszczególnych „hotspotów”. urządzeń odbiorców.

41d8d7feaa87454d.png

8. Wrzucanie, złapanie i rejestrowanie wyjątku

Nawet jeśli Twój kod zostanie poprawnie wychwycony i obsłużony przez wyjątek środowiska wykonawczego, deweloper często zanotuje, że taki wyjątek wystąpił i w jakich okolicznościach. Crashlytics.LogException może służyć właśnie w tym celu, czyli do wysyłania zdarzenia wyjątku do Firebase, co umożliwia dalsze debugowanie problemu w konsoli Firebase.

  1. W Assets/Hamster/Scripts/States/DebugMenu.cs dołącz do instrukcji using:
    // Import Firebase
    using Firebase.Crashlytics;
    
  2. Będąc na liście DebugMenu.cs, zastąp LogNonfatalError() w ten sposób:
    void LogNonfatalError()
    {
        try
        {
            throw new System.Exception($"Test exception thrown in {nameof(LogNonfatalError)}");
        }
        catch(System.Exception exception)
        {
            Crashlytics.LogException(exception);
        }
    }
    
  3. Utwórz aplikację.
  4. (Tylko Android) Prześlij symbole, uruchamiając następujące polecenie interfejsu wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  5. Kliknij przycisk Zarejestruj błąd niekrytyczny i ponownie uruchom aplikację.
  6. Otwórz panel Crashlytics. Powinien pojawić się podobny efekt jak w ostatnim kroku tego ćwiczenia z programowania.
  7. Tym razem ogranicz filtr Typ zdarzenia do wartości Niekrytyczne, aby widoczne były tylko błędy niekrytyczne, takie jak ten dodany przed chwilą.
    A39EA8d9944cbbd9.png

9. Rejestruj ciągi tekstowe w Crashlytics, aby lepiej zrozumieć przepływ wykonywania programu

Czy kiedykolwiek próbowałeś(-aś) dowiedzieć się, dlaczego wiersz kodu, który jest wywoływany z wielu ścieżek, setki, a nawet tysiące razy w trakcie jednej sesji, może nagle wygenerować wyjątek lub awarię? Chociaż dobrze jest przejrzeć kod w IDE i bliższe się przyjrzeć wartościom, co zrobić, jeśli dzieje się tak tylko wśród niewielkiego odsetka użytkowników? Co gorsza, co by było zrobić, jeśli bez względu na to, co robisz, nie jesteś w stanie odtworzyć tego błędu?

W takich sytuacjach kontekst może wiele zmienić. Crashlytics.Log umożliwia zapisanie potrzebnego kontekstu. Potraktuj te komunikaty jak wskazówki dotyczące tego, co może się wydarzyć w przyszłości.

Dzienniki można wykorzystać na wiele sposobów, ale zwykle najbardziej przydają się do rejestrowania sytuacji, w których istotną rolę odgrywa kolejność lub brak połączeń.

  1. W programie Assets/Hamster/Scripts/States/DebugMenu.cs zastąp LogStringsAndCrashNow() w ten 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. Utwórz aplikację.
  3. (Tylko Android) Prześlij symbole, uruchamiając następujące polecenie interfejsu wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Kliknij przycisk Zarejestruj ciągi tekstowe i Awaria teraz, a następnie ponownie uruchom aplikację.
  5. Wróć do panelu Crashytics i kliknij najnowszy problem wymieniony w tabeli Problemy. Powinno wyświetlić się coś podobnego do poprzednich.
    7aabe103b8589cc7.png
  6. Jeśli jednak klikniesz kartę Logi w sekcji Podsumowanie zdarzeń, zobaczysz widok taki:
    4e27aa407b7571cf.png

10. Zapisywanie i zastępowanie klucza niestandardowego

Załóżmy, że chcesz lepiej zrozumieć awarię związaną ze zmiennymi ustawionymi na niewielką liczbę wartości lub konfiguracji. Warto mieć możliwość filtrowania na podstawie kombinacji zmiennych i możliwych wartości w danym momencie.

Oprócz rejestrowania dowolnych ciągów ciągów Crashlytics udostępnia też inną formę debugowania, która pozwala lepiej poznać dokładny stan programu w przypadku awarii: klucze niestandardowe.

Są to pary klucz-wartość, które możesz ustawić dla sesji. W przeciwieństwie do logów, które gromadzą i są całkowicie addytywne, klucze można zastępować tylko w celu odzwierciedlenia najnowszego stanu zmiennej lub warunku.

Te klucze nie tylko rejestrują ostatni zarejestrowany stan programu, ale mogą też służyć jako zaawansowane filtry do rozwiązywania problemów z Crashlytics.

  1. W programie Assets/Hamster/Scripts/States/DebugMenu.cs zastąp SetAndOverwriteCustomKeyThenCrash() w ten 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. Utwórz aplikację.
  3. (Tylko Android) Prześlij symbole, uruchamiając następujące polecenie interfejsu wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Kliknij przycisk Ustaw niestandardowy klucz i awarię, a następnie ponownie uruchom aplikację.
  5. Wróć do panelu Crashytics i kliknij najnowszy problem wymieniony w tabeli Problemy. Tutaj również powinien pojawić się problem podobny do poprzednich.
  6. Tym razem kliknij kartę Klucze w sekcji Podsumowanie zdarzeń, aby zobaczyć wartości kluczy, w tym Current Time:
    7dbe1eb00566af98.png

Dlaczego lepiej używać kluczy niestandardowych zamiast logów niestandardowych?

  • Logi dobrze przechowują dane sekwencyjne, ale klucze niestandardowe są lepsze, gdy zależy Ci tylko na najnowszej wartości.
  • W konsoli Firebase możesz łatwo filtrować problemy według wartości kluczy w polu wyszukiwania tabeli Problemy.

Podobnie jak logi, klucze niestandardowe mają jednak limit. Crashlytics obsługuje maksymalnie 64 pary klucz-wartość. Gdy osiągniesz ten próg, dodatkowe wartości nie będą zapisywane. Rozmiar każdej pary klucz-wartość nie może przekraczać 1 KB.

11. (Tylko Android) Używanie niestandardowych kluczy i dzienników do analizowania i diagnozowania błędów ANR

Jedną z najtrudniejszych klas problemów do debugowania przez deweloperów aplikacji na Androida jest błąd Aplikacja nie odpowiada (ANR). Błędy ANR występują, gdy aplikacja nie odpowiada na dane wejściowe przez ponad 5 sekund. Jeśli tak się stanie, oznacza to, że aplikacja zawiesiła się lub działa bardzo wolno. Użytkownicy widzą okno, w którym mogą wybrać, czy chcą „Czekać”. lub „Zamknij aplikację”.

Błędy ANR negatywnie wpływają na wrażenia użytkowników i (jak wspomnieliśmy w linku do błędów ANR powyżej) mogą wpływać na wykrywalność aplikacji w Sklepie Google Play. Z powodu ich złożoności oraz tego, że często są powodowane przez wielowątkowy kod o znacznie różniącym się działaniu w różnych modelach telefonów, odtwarzanie błędów ANR jest często bardzo trudne lub prawie niemożliwe. Z tego powodu najlepszym podejściem jest zwykle podejście do nich analityczne i dedukcyjne.

W ramach tej metody będziemy korzystać z kombinacji parametrów Crashlytics.LogException, Crashlytics.Log i Crashlytics.SetCustomKey, aby uzupełnić automatyczne logowanie problemów i przekazać nam więcej informacji.

  1. W programie Assets/Hamster/Scripts/States/DebugMenu.cs zastąp SetLogsAndKeysBeforeANR() w ten 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. Utwórz aplikację.
  3. Prześlij symbole, uruchamiając następujące polecenie interfejsu wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Kliknij przycisk Ustaw dzienniki i klucze → ANR, a następnie ponownie uruchom aplikację.
  5. Wróć do panelu Crashlytics i kliknij nowy problem w tabeli Problemy, aby wyświetlić Podsumowanie zdarzeń. Jeśli połączenie zostało prawidłowo zrealizowane, powinien wyświetlić się komunikat podobny do tego:
    876c3cff7037bd07.png

    Jak widzisz, Firebase wskazało zajęty czas oczekiwania w wątku jako główną przyczynę wywołania błędu ANR przez aplikację.
  6. Jeśli spojrzysz na logi na karcie Logi Podsumowania zdarzeń, zobaczysz, że ostatnia metoda zarejestrowana jako zakończona to DoSevereWork.
    5a4bec1cf06f6984.png

    Dlatego ostatnia metoda rozpoczęcia to DoExtremeWork, która oznacza, że podczas tej metody wystąpił błąd ANR i gra została zamknięta, zanim mogła zostać zarejestrowana DoExtremeWork.

    89d86d5f598ecf3a.png

Jakie są korzyści?

  • Odtwarzanie błędów ANR jest niezwykle trudne, dlatego możliwość uzyskania szczegółowych informacji o obszarze kodu i danych jest niezmiernie ważna, aby można było je wywnioskować.
  • Dzięki informacjom przechowywanym w kluczach niestandardowych wiesz teraz, który wątek asynchroniczny działał najdłużej, a który mógł spowodować błędy ANR. Tego rodzaju powiązane dane logiczne i liczbowe pokazują, który fragment kodu jest najbardziej niezbędny do optymalizacji.

12. Łączenie zdarzeń Analytics w celu dalszego wzbogacania raportów

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

W przeciwieństwie do innych metod opracowanych przez Ciebie w ramach tego ćwiczenia z programowania, musisz używać tych metod w połączeniu z innymi. Wywołuj te metody w dowolnej kolejności, naciskając odpowiedni przycisk w menu debugowania, zanim uruchomisz którąś z innych. Następnie, gdy przeanalizujesz informacje dotyczące konkretnego problemu Crashlytics, zobaczysz uporządkowany dziennik zdarzeń Analytics. Tych danych można użyć w grze, aby lepiej zrozumieć kombinację przebiegu programu lub danych wejściowych użytkownika, w zależności od tego, jak została skonfigurowana aplikacja.

  1. W pliku Assets/Hamster/Scripts/States/DebugMenu.cs zastąp obecne implementacje tych 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. Skompiluj i wdróż grę, a potem otwórz menu debugowania.
  3. (Tylko Android) Prześlij symbole, uruchamiając następujące polecenie interfejsu wiersza poleceń Firebase:
    firebase crashlytics:symbols:upload --app=<FIREBASE_APP_ID> <PATH/TO/SYMBOLS>
    
  4. Naciśnij co najmniej jeden z następujących przycisków co najmniej raz, aby wywołać powyższe funkcje:
    • Zarejestruj zdarzenie ciągu tekstowego
    • Zdarzenie logowania Int
  5. Naciśnij przycisk Wypadek teraz.
  6. Ponownie uruchom grę, aby przesłać zdarzenie awarii do Firebase.
  7. Gdy zarejestrujesz różne dowolne sekwencje zdarzeń Analytics, a następnie gra wygeneruje zdarzenie, na podstawie którego Crashlytics utworzy raport (tak jak zwykle), zostaną one dodane do karty Logi w Podsumowaniu zdarzeń Crashlytics w ten sposób:
    d3b16d78f76bfb04.png

13. W przód

Dzięki temu masz dostęp do lepszych teoretycznych podstaw do uzupełnienia automatycznie generowanych raportów o awariach. Te nowe informacje umożliwiają korzystanie z bieżącego stanu, rejestrów wcześniejszych zdarzeń i istniejących zdarzeń Google Analytics do lepszego podziału sekwencji zdarzeń i logiki, która doprowadziła do danego wyniku.

Jeśli Twoja aplikacja jest kierowana na Androida 11 (poziom interfejsu API 30) lub nowszego, rozważ wdrożenie GWP-ASan – funkcji przydzielającej pamięć natywną, która przydaje się do debugowania awarii spowodowanych przez błędy pamięci natywnej, takie jak błędy use-after-free i heap-buffer-overflow. Aby skorzystać z tej funkcji debugowania, wyraźnie włącz GWP-ASan.

Następne kroki

Przejdź do ćwiczenia z programowania w sekcji Dostosowywanie gry na Unity przy użyciu Zdalnej konfiguracji, podczas którego nauczysz się korzystać ze Zdalnej konfiguracji i Testów A/B w Unity.