Dostosowywanie raportów o awariach Firebase Crashlytics


Na pulpicie Crashlytics możesz kliknąć problem, aby uzyskać szczegółowy raport o wydarzeniu. Możesz dostosowywać te raporty, aby lepiej zrozumieć, co dzieje się w aplikacji, i jakie są okoliczności związane ze zgłoszonymi zdarzeniami w Crashlytics.

  • Automatycznie otrzymuj logi ścieżki, jeśli Twoja aplikacja korzysta z pakietu SDK Firebase w Google Analytics. Te logi zapewniają wgląd w działania użytkownika, które doprowadziły do zarejestrowania w Twojej aplikacji zdarzenia Crashlytics.

  • Wyłącz automatyczne raportowanie awarii i włącz raportowanie z wyrażeniem zgody dla użytkowników. Pamiętaj, że domyślnie Crashlytics automatycznie zbiera raporty o awariach dla wszystkich użytkowników aplikacji.

Dodawanie kluczy niestandardowych

Klucze niestandardowe pomagają określić stan aplikacji, który doprowadził do awarii. Możesz powiązać z raportami o awariach dowolne pary klucz-wartość, a następnie używać niestandardowych kluczy do wyszukiwania i filtrowania raportów o awariach w konsoli Firebase.

  • W panelu Crashlytics możesz wyszukiwać problemy pasujące do klucza niestandardowego.
  • Podczas sprawdzania konkretnego problemu w konsoli możesz wyświetlić powiązane klucze niestandardowe dla każdego zdarzenia (podkarta Klucze) i nawet je filtrować według kluczy niestandardowych (menu Filtr u góry strony).

Aby ustawić pary 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 wartości całkowitych, logicznych lub zmiennoprzecinkowych wpisz wartość w polu tekstowym jako @(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ż zmodyfikować wartość istniejącego klucza, wywołując go i ustawiając 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"];

Dodawaj pary klucz-wartość zbiorczo, używając metody setCustomKeysAndValues z jedynym 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];

Dodawanie niestandardowych komunikatów z logów

Aby uzyskać więcej informacji o zdarzeniach prowadzących do awarii, możesz dodać do aplikacji niestandardowe logi Crashlytics. Crashlytics łączy te logi z danymi o awarii i wyświetla je na stronie Crashlyticskonsoli Firebase na karcie Logi.

Swift

Aby określić problemy, użyj log() lub log(format:, arguments:). Jeśli chcesz uzyskać przydatne dane wyjściowe dziennika z wiadomościami, obiekt przekazywany do funkcji log() musi być zgodny z właściwością CustomStringConvertible. log() zwraca definiowaną przez Ciebie w obiekcie właściwość description. Przykład:

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

.log(format:, arguments:) formatuje wartości zwracane przez funkcję getVaList(). Przykład:

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

Więcej informacji o używaniu funkcji log() lub log(format:, arguments:) znajdziesz w dokumentacji referencyjnej Crashlytics.

Objective-C

Aby określić problemy, użyj log lub logWithFormat. Jeśli chcesz uzyskać przydatne dane wyjściowe z logiem z wiadomościami, obiekt przekazany do dowolnej metody 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 używaniu funkcji loglogWithFormat znajdziesz w dokumentacji referencyjnej dotyczącej Crashlytics.

Konfigurowanie identyfikatorów użytkowników

Aby zdiagnozować problem, warto często wiedzieć, którzy użytkownicy doświadczyli danego błędu. Crashlytics umożliwia anonimowe identyfikowanie użytkowników w raportach o awariach.

Aby dodawać identyfikatory użytkowników do raportów, przypisz do każdego z nich unikalny identyfikator w postaci numeru identyfikacyjnego, tokena lub wartości zaszyfrowanej:

Swift

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

Objective-C

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

Jeśli kiedykolwiek będziesz musiał(-a) wyczyścić identyfikator użytkownika po jego ustawieniu, zresetuj jego wartość na pusty ciąg znaków. Wyczyszczenie identyfikatora użytkownika nie powoduje usunięcia istniejących rekordów Crashlytics. Jeśli chcesz usunąć rekordy powiązane z identyfikatorem użytkownika, skontaktuj się z zespołem pomocy Firebase.

Zgłaszanie błędów niekrytycznych

Oprócz automatycznego zgłaszania awarii aplikacji Crashlytics umożliwia rejestrowanie niekrytycznych wyjątków i wysyłanie ich do Ciebie przy następnym uruchomieniu aplikacji.

Możesz rejestrować niekrytyczne wyjątki, rejestrując obiekty NSError za pomocą metody recordError. Funkcja recordError zapisuje stos wywołań wątku, wywołując funkcję [NSThread callStackReturnAddresses].

Swift

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

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Podczas korzystania z metody recordError ważne jest, aby zrozumieć strukturę NSError oraz sposób, w jaki Crashlytics używa danych do grupowania awarii. Nieprawidłowe użycie metody recordError może powodować nieprzewidywalne działanie i może spowodować, że Crashlytics ograniczy raportowanie błędów zarejestrowanych w aplikacji.

Obiekt NSError ma 3 argumenty:

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

W przeciwieństwie do krytycznych awarii, które są grupowane za pomocą analizy ścieżki stosu, zarejestrowane błędy są grupowane według domaincode. To ważne rozróżnienie między awariami krytycznymi a rejestrowanymi błędami. 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 powyższy błąd, utworzysz nowy problem, który zostanie pogrupowany według NSSomeErrorDomain i -1001. Dodatkowe zarejestrowane błędy, które używają tych samych wartości domeny i kodu, są grupowane pod tym samym problemem. Dane zawarte w obiekcie userInfo są przekształcane w pary klucz-wartość i wyświetlane w sekcji klucze/logi w ramach konkretnego problemu.

Logi i klucze niestandardowe

Podobnie jak w przypadku raportów o awariach, możesz umieszczać w NSError logi i klucze niestandardowe, aby dodać kontekst. Różnica polega jednak na tym, jakie dzienniki są dołączane do awarii, a jakie do błędów. Gdy wystąpi błąd i aplikacja zostanie ponownie uruchomiona, dzienniki Crashlytics pobrane z dysku są tymi, które zostały zapisane bezpośrednio przed wystąpieniem błędu. Gdy zarejestrujesz NSError, aplikacja nie zostanie natychmiast zamknięta. Ponieważ Crashlytics wysyła raport o błędach tylko po następnym uruchomieniu aplikacji i musi ograniczać ilość miejsca na dysku zarezerwowanego na dzienniki, po zarejestrowaniu NSError można przekazać wystarczającą ilość danych, aby wszystkie istotne dzienniki zostały zastąpione do czasu wysłania raportu z urządzenia przez Crashlytics. Pamiętaj o tym, gdy rejestrujesz NSErrors i używasz dzienników oraz niestandardowych kluczy w aplikacji.

Możliwe spowolnienie działania witryny

Pamiętaj, że rejestrowanie NSError może być dość kosztowne. W momencie wywołania Crashlytics zapisuje bieżący stos wywołań wątku za pomocą procesu zwanego odwijaniem stosu. Ten proces może być obciążający dla procesora i wejść/wyjść, szczególnie w przypadku architektur, które obsługują odwijanie DWARF (arm64 i x86). Po zakończeniu odwijania informacje są synchronicznie zapisywane na dysku. Zapobiega to utracie danych, jeśli następny wiersz ulegnie awarii.

Chociaż wywoływanie tego interfejsu API w wątku w tle jest bezpieczne, pamiętaj, że wysłanie tego wywołania do innej kolejki powoduje utratę kontekstu bieżącego śledzenia stosu.

Co z NSExceptions?

Crashlytics nie oferuje możliwości bezpośredniego rejestrowania i zapisywania NSException. Ogólnie rzecz biorąc, interfejsy Cocoa i Cocoa Touch nie są odporne na wyjątki. Oznacza to, że użycie @catch może mieć bardzo poważne niezamierzone skutki uboczne, nawet przy zachowaniu najwyższej ostrożności. Nigdy nie używaj w kodzie instrukcji @catch. Więcej informacji znajdziesz w dokumentacji Apple.

Dostosowywanie ścieżek wywołań

Jeśli aplikacja działa w nienatywnościowym środowisku (np. C++ lub Unity), możesz użyć interfejsu Exception Model API, aby zgłaszać metadane o awariach w natywnym formacie wyjątków aplikacji. Zgłoszone wyjątki są oznaczane 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];

Ramki niestandardowego zbioru można też zainicjować tylko 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];

Pobieranie dzienników elementów menu nawigacyjnego

Dzięki dziennikom ścieżek możesz lepiej poznać interakcje użytkownika z aplikacją, które doprowadziły do awarii, niekrytycznego błędu lub zdarzenia ANR. Te logi mogą być przydatne podczas próby odtworzenia i debugowania problemu.

Logi ścieżki breadcrumbs są obsługiwane przez Google Analytics, więc aby je uzyskać, musisz włączyć Google Analytics w projekcie Firebase i dodać do aplikacji pakiet SDK Firebase dla Google Analytics. Gdy spełnisz te wymagania, ścieżki breadcrumbs będą automatycznie uwzględniane w danych zdarzenia na karcie Logi, gdy wyświetlisz szczegóły problemu.

Pakiet SDK Analytics automatycznie rejestruje zdarzenie screen_view, dzięki czemu logi ścieżki pokazują listę ekranów wyświetlonych przed zdarzeniem ANR, niekrytycznym zdarzeniem lub zdarzeniem ANR. Plik z logiem informacji o elementach nawigacyjnych screen_view zawiera parametr firebase_screen_class.

W logach drożek chleba są też wypełniane wszystkie zdarzenia niestandardowe, które ręcznie rejestrujesz w sesji użytkownika, w tym dane parametrów zdarzenia. Te dane mogą pomóc w określeniu sekwencji działań użytkownika, które doprowadziły do awarii, niekrytycznego błędu lub błędu ANR.

Pamiętaj, że możesz kontrolować zbieranie i wykorzystywanie danych Google Analytics, w tym danych wypełniających dzienniki ścieżek.

Włączanie raportowania zgody

Domyślnie Crashlytics automatycznie zbiera raporty o awariach dla wszystkich użytkowników aplikacji. Aby zapewnić użytkownikom większą kontrolę nad przesyłanymi danymi, możesz włączyć raportowanie z wymuszoną zgodą, wyłączając raportowanie automatyczne i wysyłając dane do Crashlytics tylko wtedy, gdy zdecydujesz się na to w kodze.

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

    • Klucz: FirebaseCrashlyticsCollectionEnabled
    • Wartość: false
  2. Włącz zbieranie danych w przypadku wybranych użytkowników, wywołując podczas działania funkcji override danych Crashlytics. Wartość zastępowania jest zachowywana we wszystkich kolejnych uruchomieniach aplikacji, dzięki czemu Crashlytics może automatycznie zbierać raporty dotyczące tego użytkownika.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

    Jeśli użytkownik zrezygnuje z zbierania danych, możesz przekazać wartość false jako wartość zastąpienia. Zostanie ona zastosowana przy następnym uruchomieniu aplikacji przez tego użytkownika i będzie obowiązywać przy wszystkich kolejnych uruchomieniach.

Zarządzanie danymi z analizy awarii

Analiza błędów pomaga rozwiązywać problemy przez porównywanie zanonimizowanych zrzutów stosu z zrzutami z innych aplikacji Firebase i informowanie, czy Twój problem jest częścią większego trendu. W przypadku wielu problemów statystyki awarii udostępniają nawet zasoby, które pomogą Ci w debugowaniu awarii.

Raport Crash Insights korzysta z zagregowanych danych o wypadkach, aby identyfikować wspólne trendy dotyczące stabilności. Jeśli nie chcesz udostępniać danych aplikacji, możesz zrezygnować ze statystyk awarii w menu Statystyki awarii u góry listy Crashlytics problemów w konsoli Firebase.