Dostosowywanie raportów o awariach Firebase Crashlytics

W panelu Crashlytics możesz kliknąć problem i uzyskać szczegółowy raport o zdarzeniach. Możesz dostosować te raporty, aby lepiej zrozumieć, co dzieje się w Twojej aplikacji i okoliczności związanych ze zdarzeniami zgłoszonymi do Crashlytics.

  • Jeśli Twoja aplikacja korzysta z pakietu SDK Firebase dla Google Analytics, automatycznie pobieraj logi menu nawigacyjnego. Logi te dają wgląd w działania użytkowników, które doprowadziły do zdarzenia zebranego przez Crashlytics w Twojej aplikacji.

  • Wyłącz automatyczne zgłaszanie awarii i włącz raportowanie dla użytkowników. Pamiętaj, że Crashlytics domyślnie zbiera automatycznie raporty o awariach dotyczące wszystkich użytkowników Twojej aplikacji.

Dodaj klucze niestandardowe

Klucze niestandardowe pomagają uzyskać konkretny stan aplikacji, który doprowadził do awarii. Dowolne pary klucz-wartość możesz powiązać z raportami o awariach, a potem używać kluczy niestandardowych do wyszukiwania i filtrowania raportów o awariach w konsoli Firebase.

  • W panelu Crashytics możesz wyszukiwać problemy pasujące do klucza niestandardowego.
  • Podczas sprawdzania konkretnego problemu w konsoli możesz wyświetlić powiązane klucze niestandardowe powiązane z każdym zdarzeniem (podkarta Klucze), a nawet przefiltrować zdarzenia według kluczy niestandardowych (menu Filtr u góry strony).

Do ustawiania par klucz-wartość użyj metody setCustomValue. Przykład:

Swift

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

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

Objective-C

Podczas ustawiania liczb całkowitych, wartości logicznych lub liczb zmiennoprzecinkowych wpisz wartość w polu @(value).

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

// Set str_key to "hello".
[[FIRCrashlytics crashlytics] setCustomValue:@"hello" forKey:@"str_key"];

Możesz też zmienić wartość istniejącego klucza, wywołując go i ustawiając dla niego inną wartość. Przykład:

Swift

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

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

Objective-C

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

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

Dodaj pary klucz-wartość zbiorczo, używając metody setCustomKeysAndValues z parametrem NSDictionary:

Swift

let keysAndValues = [
                 "string key" : "string value",
                 "string key 2" : "string value 2",
                 "boolean key" : true,
                 "boolean key 2" : false,
                 "float key" : 1.01,
                 "float key 2" : 2.02
                ] as [String : Any]

Crashlytics.crashlytics().setCustomKeysAndValues(keysAndValues)

Objective-C

NSDictionary *keysAndValues =
    @{@"string key" : @"string value",
      @"string key 2" : @"string value 2",
      @"boolean key" : @(YES),
      @"boolean key 2" : @(NO),
      @"float key" : @(1.01),
      @"float key 2" : @(2.02)};

[[FIRCrashlytics crashlytics] setCustomKeysAndValues: keysAndValues];

Dodaj niestandardowe komunikaty logu

Aby zapewnić sobie szerszy kontekst dla zdarzeń prowadzących do awarii, możesz dodać do aplikacji niestandardowe logi Crashlytics. Crashlytics powiąże dzienniki z danymi awarii i wyświetli je na stronie Crashlytics w konsoli Firebase na karcie Logi.

Swift

Aby wskazać problemy, użyj log() lub log(format:, arguments:). Jeśli chcesz otrzymywać przydatne dane wyjściowe logów z wiadomościami, obiekt, który przekazujesz do log(), musi być zgodny z właściwością CustomStringConvertible. log() zwraca właściwość opisu zdefiniowaną dla obiektu. Przykład:

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

Wartości formatów .log(format:, arguments:) zwrócone przez wywołanie getVaList(). Przykład:

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

Więcej informacji o korzystaniu z log() i log(format:, arguments:) znajdziesz w dokumentacji referencyjnej Crashlytics.

Objective-C

Aby wskazać problemy, użyj log lub logWithFormat. Pamiętaj, że jeśli chcesz otrzymywać przydatne dane wyjściowe dzienników z wiadomościami, obiekt przekazywany do jednej z metod musi zastąpić właściwość instancji description. Przykład:

[[FIRCrashlytics crashlytics] log:@"Simple string message"];

[[FIRCrashlytics crashlytics] logWithFormat:@"Higgs-Boson detected! Bailing out... %@", attributesDict];

[[FIRCrashlytics crashlytics] logWithFormat:@"Logging a variable argument list %@" arguments:va_list_arg];

Więcej informacji o tym, jak używać właściwości log i logWithFormat, znajdziesz w dokumentacji referencyjnej Crashlytics.

Ustawianie identyfikatorów użytkowników

Przy diagnozowaniu problemu często warto wiedzieć, u których użytkowników wystąpiła dana awaria. Crashlytics umożliwia anonimowe identyfikowanie użytkowników w raportach o awariach.

Aby dodać identyfikatory użytkowników do raportów, przypisz każdemu użytkownikowi unikalny identyfikator w postaci numeru identyfikacyjnego, tokena lub zaszyfrowanej wartości:

Swift

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

Objective-C

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

Jeśli musisz usunąć identyfikator użytkownika po jego ustawieniu, zresetuj wartość do pustego ciągu znaków. Wyczyszczenie identyfikatora użytkownika nie spowoduje usunięcia istniejących rekordów Crashlytics. Jeśli chcesz usunąć rekordy powiązane z identyfikatorem User-ID, skontaktuj się z zespołem pomocy Firebase.

Zgłaszanie wyjątków niekrytycznych

Crashlytics pozwala nie tylko automatycznie zgłaszać awarie aplikacji, ale też rejestrować niekrytyczne wyjątki i wysyłać je przy następnym uruchomieniu aplikacji.

Możesz rejestrować niekrytyczne wyjątki, rejestrując obiekty NSError metodą recordError. Funkcja recordError przechwytuje stos wywołań wątku przez wywołanie metody [NSThread callStackReturnAddresses].

Swift

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

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Gdy korzystasz z metody recordError, ważne jest zrozumienie struktury NSError i tego, jak Crashlytics używa danych do grupowania awarii. Nieprawidłowe użycie metody recordError może spowodować nieprzewidywalne zachowanie i ograniczyć raportowanie logów błędów dotyczących aplikacji przez Crashlytics.

Obiekt NSError ma 3 argumenty:

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

W przeciwieństwie do awarii krytycznych, które są grupowane za pomocą analizy zrzutu stosu, zarejestrowane błędy są grupowane według atrybutów domain i code. Jest to ważna rozróżnienie między awariami krytycznymi a błędami zarejestrowanymi. Przykład:

Swift

let userInfo = [
  NSLocalizedDescriptionKey: NSLocalizedString("The request failed.", comment: ""),
  NSLocalizedFailureReasonErrorKey: NSLocalizedString("The response returned a 404.", comment: ""),
  NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Does this page exist?", comment: ""),
  "ProductID": "123456",
  "View": "MainView"
]

let error = NSError.init(domain: NSCocoaErrorDomain,
                         code: -1001,
                         userInfo: userInfo)

Objective-C

NSDictionary *userInfo = @{
  NSLocalizedDescriptionKey: NSLocalizedString(@"The request failed.", nil),
  NSLocalizedFailureReasonErrorKey: NSLocalizedString(@"The response returned a 404.", nil),
  NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString(@"Does this page exist?", nil),
  @"ProductID": @"123456",
  @"View": @"MainView",
};

NSError *error = [NSError errorWithDomain:NSCocoaErrorDomain
                                     code:-1001
                                 userInfo:userInfo];

Gdy zarejestrujesz ten błąd, zostanie utworzony nowy problem pogrupowany według atrybutów NSSomeErrorDomain i -1001. Dodatkowe zarejestrowane błędy, które używają tej samej domeny i wartości kodu, są zgrupowane w ramach tego samego problemu. Dane zawarte w obiekcie userInfo są konwertowane na pary klucz-wartość i wyświetlane w sekcji klucze/logi w ramach danego problemu.

Logi i klucze niestandardowe

Podobnie jak w przypadku raportów o awariach możesz osadzić dzienniki i klucze niestandardowe, aby wzbogacić obiekt NSError o odpowiedni kontekst. Występuje jednak różnica pod względem tego, które logi są dołączane do awarii, a które błędy zarejestrowane. W przypadku awarii i ponownego uruchomienia aplikacji logi, które Crashlytics pobiera z dysku, to te, które zostały zapisane do momentu awarii. Po zarejestrowaniu NSError aplikacja nie zostaje natychmiast zamknięta. Crashlytics wysyła raport o błędach tylko przy następnym uruchomieniu aplikacji i musi ograniczyć ilość miejsca przydzielonego na logi na dysku. Dlatego po zarejestrowaniu parametru NSError możliwe jest zarejestrowanie wystarczającej ilości danych, tak aby wszystkie odpowiednie logi zostały wykonane przed wysyłką raportu z urządzenia przez Crashlytics. Pamiętaj o tym podczas logowania danych NSErrors oraz używania logów i kluczy niestandardowych w aplikacji.

Możliwe spowolnienie działania witryny

Pamiętaj, że zapisywanie danych NSError może być dość kosztowne. W momencie wykonywania wywołania Crashlytics przechwytuje stos wywołań bieżącego wątku za pomocą procesu nazywanego odwijaniem stosu. Ten proces może wymagać obciążenia procesora i wejścia/wyjścia, zwłaszcza w architekturach, które obsługują rozwijanie plików DWARF (arm64 i x86). Po zakończeniu odwracania informacje informacje są synchronicznie zapisywane na dysku. Zapobiega to utracie danych w przypadku awarii następnego wiersza.

Chociaż wywołanie tego interfejsu API można bezpiecznie wywołać w wątku w tle, pamiętaj, że wysłanie tego wywołania do innej kolejki powoduje utratę kontekstu bieżącego zrzutu stosu.

Co z NSExceptions?

Crashlytics nie udostępnia możliwości bezpośredniego logowania i rejestrowania instancji NSException. Ogólnie interfejsy API Cocoa i Cocoa Touch nie są bezpieczne w wyjątkach. Oznacza to, że korzystanie z usługi @catch może mieć bardzo poważne, niezamierzone skutki uboczne, nawet jeśli jest używane bardzo ostrożnie. Nie używaj w kodzie instrukcji @catch. Zapoznaj się z dokumentacją Apple na ten temat.

Dostosuj zrzuty stosu

Jeśli Twoja aplikacja działa w środowisku nienatywnym (takim jak C++ lub Unity), możesz użyć interfejsu Exception Model API do raportowania metadanych awarii w natywnym formacie wyjątku aplikacji. Zgłoszone wyjątki są oznaczone jako niekrytyczne.

Swift

var  ex = ExceptionModel(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame(symbol:"makeError", file:"handler.js", line:495),
  StackFrame(symbol:"then", file:"routes.js", line:102),
  StackFrame(symbol:"main", file:"app.js", line:12),
]

crashlytics.record(exceptionModel:ex)

Objective-C

FIRExceptionModel *model =
    [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
model.stackTrace = @[
  [FIRStackFrame stackFrameWithSymbol:@"makeError" file:@"handler.js" line:495],
  [FIRStackFrame stackFrameWithSymbol:@"then" file:@"routes.js" line:102],
  [FIRStackFrame stackFrameWithSymbol:@"main" file:@"app.js" line:12],
];

[[FIRCrashlytics crashlytics] recordExceptionModel:model];

Niestandardowe ramki stosu można też inicjować jedynie za pomocą adresów:

Swift

var  ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame(address:0xfa12123),
  StackFrame(address:12412412),
  StackFrame(address:194129124),
]

crashlytics.record(exceptionModel:ex)

Objective-C

FIRExceptionModel *model =
    [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
model.stackTrace = @[
  [FIRStackFrame stackFrameWithAddress:0xfa12123],
  [FIRStackFrame stackFrameWithAddress:12412412],
  [FIRStackFrame stackFrameWithAddress:194129124],
];


[[FIRCrashlytics crashlytics] recordExceptionModel:model];

Pobierz logi menu nawigacyjnego

Logi menu nawigacyjnego pozwalają lepiej poznać interakcje użytkownika z aplikacją, które doprowadziły do awarii, błędów niekrytycznych lub błędów ANR. Logi te mogą być pomocne przy odtworzeniu i debugowaniu problemu.

Logi menu nawigacyjnego są obsługiwane przez Google Analytics, więc aby uzyskać dostęp do logów menu nawigacyjnego, musisz włączyć Google Analytics w swoim projekcie Firebase i dodać pakiet SDK Firebase dla Google Analytics do swojej aplikacji. Po spełnieniu tych wymagań dzienniki menu nawigacyjnego są automatycznie dołączane do danych zdarzenia na karcie Logi, gdy wyświetlasz szczegóły problemu.

Pakiet Analytics SDK automatycznie rejestruje zdarzenie screen_view, które włącza w dziennikach menu nawigacyjnego wyświetlanie listy ekranów wyświetlonych przed awarią, zdarzeniem niekrytycznym lub zdarzeniem ANR. Dziennik menu nawigacyjnego screen_view zawiera parametr firebase_screen_class.

Logi menu nawigacyjnego zawierają też zdarzenia niestandardowe zarejestrowane ręcznie w sesji użytkownika, w tym dane parametrów zdarzeń. Te dane ułatwiają ukazanie serii działań użytkowników, które prowadzą do awarii, zdarzeń niekrytycznych lub błędów ANR.

Pamiętaj, że możesz kontrolować zbieranie i wykorzystywanie danych Google Analytics, które obejmują dane umieszczane w logach menu nawigacyjnego.

Włącz raportowanie akceptacji

Domyślnie Crashlytics automatycznie zbiera raporty o awariach dotyczące wszystkich użytkowników aplikacji. Aby dać użytkownikom większą kontrolę nad danymi, które wysyłają, możesz włączyć raportowanie, wyłączając automatyczne raportowanie i wysyłając dane do Crashlytics tylko wtedy, gdy na to zdecydujesz się w kodzie:

  1. Wyłącz automatyczne zbieranie danych, dodając nowy klucz do pliku Info.plist:

    • Klucz: FirebaseCrashlyticsCollectionEnabled
    • Wartość: false
  2. Włącz zbieranie danych dla wybranych użytkowników, wywołując zastępowanie zbierania danych Crashlytics w czasie działania. Wartość zastąpienia pozostanie bez zmian po każdym uruchomieniu aplikacji, więc Crashlytics może automatycznie zbierać raporty.

    Aby zrezygnować z automatycznego zgłaszania awarii, podaj wartość false jako wartość zastąpienia. Gdy ustawisz wartość false, nowa wartość będzie stosowana do następnego uruchomienia aplikacji.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Zarządzanie danymi analizy awarii

Statystyki awarii pomagają rozwiązywać problemy, porównując zanonimizowane ślady stosu ze śladami z innych aplikacji Firebase, aby poinformować Cię, czy Twój problem jest częścią większego trendu. W przypadku wielu problemów narzędzie Analiza awarii udostępnia nawet zasoby, które pomogą Ci je debugować.

Statystyki awarii wykorzystują zbiorcze dane o awariach, aby identyfikować typowe trendy dotyczące stabilności. Jeśli nie chcesz udostępniać danych o aplikacji, możesz zrezygnować ze Statystyk awarii w menu Analiza awarii u góry listy problemów Crashlytics w konsoli Firebase.