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 rozumieć, 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ą uzyskać konkretny 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 dzienniki Crashlytics. Crashlytics łączy dzienniki z danymi o awarii i wyświetla je na stronie Crashlyticskonsoli Firebase na karcie Dzienniki.

Swift

Aby określić problemy, użyj typów log() lub log(format:, arguments:). Jeśli chcesz uzyskać przydatne dane wyjściowe z logiem i 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 typów log lub logWithFormat. Jeśli chcesz uzyskać przydatne dane wyjściowe dziennika 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 niekrytycznych wyjątków

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

Możesz rejestrować niekrytyczne wyjątki, rejestrując obiekty NSError za pomocą metody recordError. 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 na podstawie analizy ścieżki stosu, zarejestrowane błędy są grupowane według domaincode. Jest to ważna różnica 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 ten błąd, powstanie 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 kończy się natychmiast. 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.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 we/wy, szczególnie w przypadku architektur, które obsługują odwijanie DWARF (arm64 i x86). Po zakończeniu rozwijania informacje są synchronicznie zapisywane na dysku. Zapobiega to utracie danych, jeśli następny wiersz ulegnie awarii.

Chociaż wywoływanie tego interfejsu API na 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 nagrywania instancji NSException. Ogólnie rzecz biorąc, interfejsy API 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 jeśli jest używane z największą ostrożnością. Nigdy nie używaj w kodzie instrukcji @catch. Więcej informacji znajdziesz w dokumentacji Apple.

Dostosowywanie śladów skumulowanych

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 mogą być również inicjowane 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żek 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, co umożliwia wyświetlanie w logach informacji o ścieżce użytkownika przed wystąpieniem błędu aplikacji, błędu niekrytycznego lub zdarzenia ANR. Plik z logiem informacji o elementach nawigacyjnych screen_view zawiera parametr firebase_screen_class.

W logach ścieżek przechowywane są też 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 zgodnego z wyrażeniem 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 wymaganiem zgody użytkownika, 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ąpienia jest zachowywana w przypadku kolejnych uruchomień aplikacji, aby Crashlytics mogła automatycznie zbierać raporty.

    Aby zrezygnować z automatycznego raportowania awarii, podaj wartość false jako wartość zastępczą. Jeśli ustawisz wartość false, nowa wartość zostanie zastosowana dopiero po ponownym uruchomieniu aplikacji.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Zarządzanie danymi z Raportu o awariach

Analiza błędów pomaga rozwiązywać problemy przez porównywanie anonimowych zrzutów stosu z zrzutami z innych aplikacji Firebase i informowanie, czy 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.