Dostosuj raporty o awariach Firebase Crashlytics

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

  • Automatycznie pobieraj dzienniki nawigacji , jeśli Twoja aplikacja korzysta z pakietu SDK Firebase dla Google Analytics. Dzienniki te zapewniają wgląd w działania użytkownika prowadzące do zdarzenia zebranego przez Crashlytics w Twojej aplikacji.

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

Dodaj niestandardowe klucze

Klucze niestandardowe pomagają uzyskać określony stan aplikacji prowadzący do awarii. Możesz powiązać dowolne pary klucz/wartość z raportami o awariach, a następnie użyć kluczy niestandardowych do wyszukiwania i filtrowania raportów o awariach w konsoli Firebase.

  • W panelu Crashlytics możesz wyszukiwać problemy pasujące do klucza niestandardowego.
  • Przeglądając konkretny problem w konsoli, możesz wyświetlić powiązane klucze niestandardowe dla każdego zdarzenia (podkarta Klucze ), a nawet filtrować zdarzenia według kluczy niestandardowych (menu Filtruj u góry strony).

Użyj metody setCustomValue , aby ustawić pary klucz/wartość. Na przykład:

Szybki

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

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

Cel C

Ustawiając liczby całkowite, wartości logiczne lub zmiennoprzecinkowe, należy umieścić wartość w ramce @( 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 także zmodyfikować wartość istniejącego klucza, wywołując klucz i ustawiając mu inną wartość. Na przykład:

Szybki

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

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

Cel C

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

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

Dodaj zbiorczo pary klucz/wartość, używając metody setCustomKeysAndValues ​​z NSDictionary jako jedynym parametrem:

Szybki

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)

Cel 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 dziennika

Aby zapewnić sobie lepszy kontekst dla zdarzeń prowadzących do awarii, możesz dodać do swojej aplikacji niestandardowe dzienniki Crashlytics. Crashlytics kojarzy dzienniki z danymi o awariach i wyświetla je na stronie Crashlytics w konsoli Firebase , na karcie Dzienniki .

Szybki

Użyj log() lub log(format:, arguments:) , aby pomóc w zlokalizowaniu problemów. Jeśli chcesz uzyskać przydatne wyniki dziennika zawierające komunikaty, obiekt przekazywany do log() musi być zgodny z właściwością CustomStringConvertible . log() zwraca zdefiniowaną dla obiektu właściwość opisu. Na przykład:

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

.log(format:, arguments:) formatuje wartości zwrócone w wyniku wywołania getVaList() . Na przykład:

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

Więcej szczegółów na temat używania log() lub log(format:, arguments:) można znaleźć w dokumentacji referencyjnej Crashlytics.

Cel C

Użyj log lub logWithFormat , aby pomóc w zlokalizowaniu problemów. Pamiętaj, że jeśli chcesz uzyskać przydatne wyniki dziennika zawierające komunikaty, obiekt przekazywany do którejkolwiek metody musi zastąpić właściwość instancji description . Na 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 szczegółów na temat używania log i logWithFormat można znaleźć w dokumentacji referencyjnej Crashlytics.

Ustaw identyfikatory użytkowników

Aby zdiagnozować problem, często warto wiedzieć, który z użytkowników doświadczył danej awarii. Crashlytics umożliwia anonimową identyfikację użytkowników w raportach o awariach.

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

Szybki

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

Cel C

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

Jeśli kiedykolwiek będziesz musiał wyczyścić identyfikator użytkownika po jego ustawieniu, zresetuj wartość do pustego ciągu. 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 pomocą techniczną Firebase .

Zgłaszaj wyjątki niekrytyczne

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

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

Szybki

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

Cel C

[[FIRCrashlytics crashlytics] recordError:error];

Podczas korzystania z metody recordError ważne jest zrozumienie struktury NSError i sposobu, w jaki Crashlytics wykorzystuje dane do grupowania awarii. Nieprawidłowe użycie metody recordError może spowodować nieprzewidywalne zachowanie i może spowodować, że Crashlytics ograniczy raportowanie zarejestrowanych błędów Twojej aplikacji.

Obiekt NSError ma trzy argumenty:

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

W przeciwieństwie do awarii krytycznych, które są grupowane na podstawie analizy śledzenia stosu, zarejestrowane błędy są grupowane według domain i code . Jest to ważne rozróżnienie między awariami śmiertelnymi a zarejestrowanymi błędami. Na przykład:

Szybki

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)

Cel 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];

Rejestrowanie powyższego błędu powoduje utworzenie nowego problemu pogrupowanego według NSSomeErrorDomain i -1001 . Dodatkowe zarejestrowane błędy, które korzystają z 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 pojedynczego zgłoszenia.

Dzienniki i klucze niestandardowe

Podobnie jak raporty o awariach, możesz osadzać dzienniki i klucze niestandardowe, aby dodać kontekst do NSError . Istnieje jednak różnica w tym, jakie dzienniki są dołączane do awarii i rejestrowanych błędów. Kiedy nastąpi awaria i aplikacja zostanie ponownie uruchomiona, dzienniki pobierane przez Crashlytics z dysku to te, które zostały zapisane aż do momentu awarii. Po zarejestrowaniu NSError aplikacja nie kończy się natychmiast. Ponieważ Crashlytics wysyła zarejestrowany raport o błędach tylko przy następnym uruchomieniu aplikacji i musi ograniczyć ilość miejsca przydzielonego na dzienniki na dysku, po zarejestrowaniu błędu NSError możliwe jest zarejestrowanie wystarczającej liczby dzienników, aby wszystkie odpowiednie dzienniki zostały usunięte do czasu wysłania przez Crashlytics raport z urządzenia. Pamiętaj o tej równowadze podczas rejestrowania NSErrors oraz korzystania z dzienników i kluczy niestandardowych w swojej aplikacji.

Względy dotyczące wydajności

Należy pamiętać, że zarejestrowanie błędu NSError może być dość kosztowne. W momencie wykonywania wywołania Crashlytics przechwytuje stos wywołań bieżącego wątku za pomocą procesu zwanego rozwijaniem stosu. Proces ten może obciążać procesor i operacje we/wy, szczególnie w architekturach obsługujących odwijanie DWARF (arm64 i x86). Po zakończeniu rozwijania informacje są zapisywane na dysku synchronicznie. Zapobiega to utracie danych w przypadku awarii następnej linii.

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

A co z wyjątkami NNS?

Crashlytics nie oferuje możliwości bezpośredniego rejestrowania i rejestrowania instancji NSException . Ogólnie rzecz biorąc, interfejsy API Cocoa i Cocoa Touch nie są zabezpieczone przed wyjątkami. Oznacza to, że użycie @catch może mieć bardzo poważne, niezamierzone skutki uboczne w procesie, nawet jeśli jest używane z wyjątkową ostrożnością. Nigdy nie powinieneś używać instrukcji @catch w swoim kodzie. Proszę zapoznać się z dokumentacją Apple na ten temat.

Dostosuj ślady stosu

Jeśli Twoja aplikacja działa w środowisku innym niż natywny (takim jak C++ lub Unity), możesz użyć interfejsu API modelu wyjątków, aby zgłosić metadane awarii w natywnym formacie wyjątku aplikacji. Zgłoszone wyjątki są oznaczone jako niekrytyczne.

Szybki

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)

Cel 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 również inicjować za pomocą samych adresów:

Szybki

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)

Cel 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 dzienniki bułki tartej

Dzienniki nawigacyjne pozwalają lepiej zrozumieć interakcje użytkownika z Twoją aplikacją, które doprowadziły do ​​awarii, zdarzenia niekrytycznego lub zdarzenia ANR. Te dzienniki mogą być pomocne przy próbie odtworzenia i debugowania problemu.

Dzienniki nawigacyjne są obsługiwane przez Google Analytics, więc aby uzyskać dzienniki nawigacyjne, musisz włączyć Google Analytics dla swojego projektu Firebase i dodać do swojej aplikacji pakiet SDK Firebase dla Google Analytics . Po spełnieniu tych wymagań dzienniki nawigacyjne są automatycznie dołączane do danych zdarzenia na karcie Dzienniki podczas przeglądania szczegółów problemu.

Pakiet Analytics SDK automatycznie rejestruje zdarzenie screen_view , które umożliwia w dziennikach nawigacyjnych pokazanie listy ekranów wyświetlonych przed awarią, zdarzeniem innym niż krytyczny lub ANR. Dziennik nawigacyjny screen_view zawiera parametr firebase_screen_class .

Dzienniki nawigacyjne są również wypełniane wszelkimi niestandardowymi zdarzeniami , które ręcznie rejestrujesz w ramach sesji użytkownika, w tym danymi parametrów zdarzenia. Dane te mogą pomóc w pokazaniu serii działań użytkownika prowadzących do awarii, zdarzenia niekrytycznego lub zdarzenia ANR.

Pamiętaj, że możesz kontrolować gromadzenie i wykorzystywanie danych Google Analytics , które obejmują dane wypełniające dzienniki nawigacyjne.

Włącz raportowanie wyrażające zgodę

Domyślnie Crashlytics automatycznie zbiera raporty o awariach dla wszystkich użytkowników Twojej aplikacji. Aby zapewnić użytkownikom większą kontrolę nad wysyłanymi danymi, możesz włączyć raportowanie, wyłączając automatyczne raportowanie i wysyłając dane do Crashlytics tylko wtedy, gdy tak zdecydujesz w swoim kodzie:

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

    • Klucz: FirebaseCrashlyticsCollectionEnabled
    • Wartość: false
  2. Włącz zbieranie dla wybranych użytkowników, wywołując zastąpienie gromadzenia danych Crashlytics w czasie wykonywania. Wartość zastąpienia będzie obowiązywać po każdym uruchomieniu Twojej aplikacji, więc Crashlytics może automatycznie zbierać raporty.

    Aby zrezygnować z automatycznego raportowania awarii, jako wartość zastąpienia podaj false . W przypadku ustawienia false nowa wartość nie zostanie zastosowana do następnego uruchomienia aplikacji.

    Szybki

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Cel C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Zarządzaj danymi Crash Insights

Crash Insights pomaga rozwiązywać problemy, porównując anonimowe ślady stosu ze śladami z innych aplikacji Firebase i informując, czy problem jest częścią większego trendu. W przypadku wielu problemów Crash Insights udostępnia nawet zasoby ułatwiające debugowanie awarii.

Crash Insights wykorzystuje zagregowane dane o awariach w celu identyfikacji typowych trendów stabilności. Jeśli nie chcesz udostępniać danych swojej aplikacji, możesz zrezygnować z Crash Insights w menu Crash Insights u góry listy problemów Crashlytics w konsoli Firebase .