W tym przewodniku opisano, jak dostosować raporty o awariach za pomocą pakietu SDK Firebase Crashlytics. Domyślnie Crashlytics automatycznie zbiera raporty o awariach dla wszystkich użytkowników Twojej aplikacji (możesz zamiast tego wyłączyć automatyczne raportowanie o awariach i włączyć raportowanie dobrowolne dla swoich użytkowników). Crashlytics udostępnia cztery gotowe mechanizmy rejestrowania: klucze niestandardowe , dzienniki niestandardowe , identyfikatory użytkowników i przechwycone wyjątki .
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];
Włącz raportowanie wyrażające zgodę
Domyślnie Crashlytics automatycznie zbiera raporty o awariach dla 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 wtedy, gdy tak zdecydujesz w swoim kodzie:
Wyłącz automatyczne zbieranie, dodając nowy klucz do pliku
Info.plist
:- Klucz:
FirebaseCrashlyticsCollectionEnabled
- Wartość:
false
- Klucz:
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 ustawieniafalse
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 .