Dostosowywanie raportów o awariach Firebase Crashlytics

W panelu Crashlytics możesz kliknąć problem i wyświetlić szczegółowy raport o zdarzeniach. Możesz dostosować te raporty, aby lepiej zrozumieć, co dzieje się w Twojej aplikacji i okoliczności dotyczące zdarzeń zgłoszonych do Crashlytics.

  • automatycznie pobierać dzienniki menu nawigacyjnego, jeśli Twoja aplikacja korzysta z pakietu SDK Firebase dla Google Analytics. Logi te zapewniają wgląd w działania użytkownika prowadzące do zdarzenia w aplikacji zebranego przez Crashlytics.

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

Dodaj klucze niestandardowe

Klucze niestandardowe pomagają określić stan aplikacji, który doprowadził do awarii. Do raportów o awariach możesz powiązać wybrane pary klucz-wartość, a następnie za pomocą kluczy niestandardowych wyszukiwać i filtrować raporty o awariach w konsoli Firebase.

  • W panelu Crashlytics możesz wyszukiwać problemy pasujące do klucza niestandardowego.
  • Gdy sprawdzasz konkretny problem w konsoli, możesz wyświetlić klucze niestandardowe powiązane z każdym zdarzeniem (podkarta Klucze), a nawet filtrować zdarzenia według kluczy niestandardowych (w 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

Jeśli chcesz ustawić liczby całkowite, wartości logiczne lub liczby zmiennoprzecinkowe, umieść 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"];

Wartość istniejącego klucza możesz też zmienić, wywołując go i ustawiając jego 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 NSDictionary jako jedynym parametrem:

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 logu

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

Swift

Użyj narzędzi log() lub log(format:, arguments:), aby łatwiej wskazać problemy. Aby uzyskać przydatne dane wyjściowe dziennika z komunikatami, obiekt przekazywany do log() musi być zgodny z właściwością CustomStringConvertible. log() zwraca właściwość opisu zdefiniowaną dla danego obiektu. Przykład:

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

Wartości formatu .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 Crashlytics.

Objective-C

Użyj narzędzi log lub logWithFormat, aby łatwiej wskazać problemy. Jeśli chcesz uzyskać przydatne dane wyjściowe logu z komunikatami, obiekt przekazywany 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 tym, jak korzystać z log i logWithFormat, znajdziesz w dokumentacji referencyjnej Crashlytics.

Konfigurowanie identyfikatorów użytkowników

W celu zdiagnozowania 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 zahaszowanej wartości:

Swift

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

Objective-C

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

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

Zgłoś niekrytyczne wyjątki

Crashlytics nie tylko automatycznie zgłasza awarie aplikacji, ale też umożliwia rejestrowanie niekrytycznych wyjątków i wysyłanie ich przy następnym uruchomieniu aplikacji.

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

Swift

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

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

W przypadku korzystania z metody recordError ważne jest, aby zrozumieć strukturę NSError i dowiedzieć się, jak Crashlytics wykorzystuje te dane do grupowania awarii. Nieprawidłowe użycie metody recordError może spowodować nieprzewidywalne zachowanie i spowodować, że Crashlytics ograniczy raportowanie rejestrowanych błędów dotyczących aplikacji.

Obiekt NSError ma 3 argumenty:

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

W odróżnieniu od awarii krytycznych, które są grupowane za pomocą analizy zrzutu stosu, zarejestrowane błędy są pogrupowane według domain i code. To ważna różnica między błędami krytycznymi a zarejestrowanymi 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];

Zapisanie powyższego błędu powoduje utworzenie nowego problemu pogrupowanego według kategorii NSSomeErrorDomain i -1001. Dodatkowe zarejestrowane błędy, które używają tej samej wartości domeny i kodu, są grupowane 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 umieszczać dzienniki i klucze niestandardowe, aby dodać kontekst do obiektu NSError. Występuje jednak różnica między tym, które logi są dołączane do awarii, a tym, jakie błędy są rejestrowane. Gdy wystąpi awaria i aplikacja zostanie ponownie uruchomiona, Crashlytics pobierze z dysku logi zapisane do momentu awarii. Gdy zarejestrujesz NSError, aplikacja nie kończy się od razu. Crashlytics wysyła raport o błędach tylko przy następnym uruchomieniu aplikacji i musi ograniczać ilość miejsca przeznaczonego na logi na dysku, dlatego po zarejestrowaniu NSError można zalogować się wystarczająco dużo, aby wszystkie istotne logi zostały obrócone do momentu wysłania przez Crashlytics raportu z urządzenia. Pamiętaj o tym podczas rejestrowania danych (NSErrors) i używania logów oraz kluczy niestandardowych w aplikacji.

Możliwe spowolnienie działania witryny

Pamiętaj, że logowanie NSError może być dość drogie. W momencie wywołania Crashlytics przechwytuje stos wywołań bieżącego wątku za pomocą procesu zwanego odjazdem stosu. Ten proces może intensywnie korzystać z procesorów i wejścia/wyjścia, zwłaszcza w architekturach obsługujących relaks DWARF (arm64 i x86). Po zakończeniu odpoczynku informacje są synchronicznie zapisywane na dysku. Zapobiega to utracie danych w razie awarii następnego wiersza.

Chociaż można bezpiecznie wywołać ten interfejs API 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 oferuje możliwości bezpośredniego rejestrowania i rejestrowania instancji NSException. Ogólnie rzecz biorąc, interfejsy Cocoa i Cocoa Touch nie są bezpieczne. Oznacza to, że korzystanie z funkcji @catch może mieć bardzo poważne, niezamierzone efekty uboczne, nawet jeśli jest używane z rozwagą. 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 innym środowisku niż natywnym (np. C++ lub Unity), możesz za pomocą interfejsu Exception Model API zgłosić metadane awarii w jej natywnym formacie. 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 również inicjować za pomocą tylko 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 menu nawigacyjnego

Logi menu nawigacyjnego pozwalają lepiej zrozumieć interakcje użytkownika z aplikacją, które doprowadziły do awarii, błędu niekrytycznego lub błędu ANR. Logi mogą być przydatne podczas próby odtworzenia i debugowania problemu.

Logi menu nawigacyjnego są obsługiwane przez Google Analytics, więc aby je pobierać, musisz włączyć Google Analytics dla swojego projektu Firebase i dodać do aplikacji pakiet SDK Firebase dla Google Analytics. Po spełnieniu tych wymagań logi menu nawigacyjnego są automatycznie dołączane do danych zdarzenia na karcie Logi po wyświetleniu szczegółów problemu.

Pakiet SDK Analytics automatycznie rejestruje zdarzenie screen_view, dzięki czemu w dziennikach menu nawigacyjnego znajduje się lista ekranów wyświetlonych przed zdarzeniem awarii, niekrytycznym lub ANR. Log menu nawigacyjnego screen_view zawiera parametr firebase_screen_class.

Są one też wypełniane wszystkimi zdarzeniami niestandardowymi, które rejestrujesz ręcznie w ramach sesji użytkownika, w tym danymi parametrów zdarzenia. Dane te pomagają pokazywać serię działań użytkowników, które doprowadziły do awarii, błędu niekrytycznego lub błędu ANR.

Pamiętaj, że możesz kontrolować zbieranie i wykorzystywanie danych Google Analytics, w tym danych wypełniających logi menu nawigacyjnego.

Włącz raportowanie dotyczące wyrażania zgody

Domyślnie Crashlytics automatycznie zbiera raporty o awariach wszystkich użytkowników Twojej aplikacji. Aby dać 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, jeśli wybierzesz opcję 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ąpienie zbierania danych Crashlytics w czasie działania. Wartość zastąpienia jest utrzymywana po uruchomieniu aplikacji, więc Crashlytics może automatycznie zbierać raporty.

    Aby zrezygnować z automatycznego raportowania o awariach, jako wartość zastąpienia przekaż false. Gdy ustawiona jest wartość false, nowa wartość nie jest stosowana do następnego uruchomienia aplikacji.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Zarządzanie danymi narzędzia Crash Insights

Statystyki awarii pomagają rozwiązywać problemy, porównując zanonimizowane zrzuty stosu z śladami z innych aplikacji Firebase i informując, czy Twój problem nie należy do większego trendu. W przypadku wielu problemów narzędzie Crash Insights udostępnia nawet zasoby, które pomagają debugować awarię.

Crash Insights używa zbiorczych danych o awariach, aby identyfikować typowe trendy związane ze stabilnością. Jeśli nie chcesz udostępniać danych o aplikacji, możesz zrezygnować z Statystyk awarii, korzystając z menu Statystyki awarii u góry listy problemów Crashlytics w konsoli Firebase.