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 przekazany 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 z logów 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, często warto 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ł 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 przesył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 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 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 dzienniki 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 odwijania 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 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ż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, co umożliwia wyświetlanie w logach informacji o ścieżce użytkownika przed wystąpieniem błędu, niekrytycznego błędu lub zdarzenia ANR. Plik z logiem 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 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 wszystkich 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 analizy awarii

Analiza awarii pomaga rozwiązywać problemy przez porównywanie anonimowych 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.