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 wyłączyć automatyczne raportowanie o awariach i zamiast tego włączyć opcjonalne raportowanie dla swoich użytkowników). Crashlytics udostępnia cztery standardowe 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ć 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.
- Przeglądając konkretny problem w konsoli, możesz wyświetlić powiązane klucze niestandardowe dla każdego zdarzenia (karta podrzędna 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
Podczas ustawiania liczb całkowitych, logicznych lub zmiennoprzecinkowych umieść 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 go na 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"];
Masowo dodaj 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 łączy dzienniki z danymi o awariach i wyświetla je na stronie Crashlytics w konsoli Firebase na karcie Dzienniki .
Szybki
Użyj funkcji log()
lub log(format:, arguments:)
aby wskazać problemy. Jeśli chcesz uzyskać przydatne wyniki dziennika z komunikatami, obiekt przekazywany do log()
musi być zgodny z właściwością CustomStringConvertible
. log()
zwraca właściwość opisu zdefiniowaną dla obiektu. Na przykład:
Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")
.log(format:, arguments:)
formatuje wartości zwracane przez wywołanie funkcji getVaList()
. Na przykład:
Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))
Aby uzyskać więcej informacji na temat używania funkcji log()
lub log(format:, arguments:)
, zapoznaj się z dokumentacją referencyjną Crashlytics .
Cel C
Użyj log
lub logWithFormat
, aby zidentyfikować problemy. Należy zauważyć, że jeśli chcesz uzyskać przydatne dane wyjściowe dziennika z komunikatami, obiekt przekazywany do dowolnej 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];
Aby uzyskać więcej informacji na temat korzystania z log
i logWithFormat
, zapoznaj się z dokumentacją referencyjną 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 raportów, przypisz każdemu użytkownikowi unikalny identyfikator w postaci numeru identyfikacyjnego, tokena lub wartości zahaszowanej:
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 zgłaszania awarii aplikacji Crashlytics umożliwia rejestrowanie wyjątków niekrytycznych i wysyłanie ich do Ciebie przy następnym uruchomieniu aplikacji.
Wyjątki niekrytyczne można rejestrować, 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
oraz sposobu, w jaki Crashlytics wykorzystuje dane do grupowania awarii. Nieprawidłowe użycie metody recordError
może spowodować nieprzewidywalne zachowanie i 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];
Gdy zarejestrujesz powyższy błąd, tworzy nowy problem, który jest pogrupowany według NSSomeErrorDomain
i -1001
. Dodatkowe zarejestrowane błędy, które używają 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 zagadnienia.
Dzienniki i klucze niestandardowe
Podobnie jak raporty o awariach, możesz osadzać dzienniki i niestandardowe klucze, aby dodać kontekst do NSError
. Istnieje jednak różnica między tym, jakie dzienniki są dołączane do awarii, a jakie są rejestrowane błędy. Gdy wystąpi awaria i ponowne uruchomienie aplikacji, Crashlytics pobiera z dysku dzienniki, które zostały zapisane aż do momentu awarii. Po zalogowaniu NSError
aplikacja nie kończy się natychmiast. Ponieważ Crashlytics wysyła raport o zarejestrowanych błędach tylko przy następnym uruchomieniu aplikacji i musi ograniczać ilość miejsca przydzielonego na logi na dysku, po zarejestrowaniu NSError
możliwe jest zarejestrowanie wystarczającej liczby logów, aby wszystkie odpowiednie logi zostały wyprzedzone do czasu wysłania przez Crashlytics raport z urządzenia. Pamiętaj o tej równowadze podczas rejestrowania NSErrors
i korzystania z dzienników i kluczy niestandardowych w aplikacji.
Względy dotyczące wydajności
Należy pamiętać, że rejestrowanie NSError
może być dość kosztowne. W momencie wywołania Crashlytics przechwytuje stos wywołań bieżącego wątku za pomocą procesu zwanego odwijaniem stosu. Ten proces może wymagać dużej mocy procesora i operacji we/wy, szczególnie w przypadku architektur obsługujących odwijanie DWARF (arm64 i x86). Po zakończeniu odwijania informacje są synchronicznie zapisywane na dysku. Zapobiega to utracie danych w przypadku awarii następnej linii.
Chociaż wywołanie tego interfejsu API w wątku w tle jest bezpieczne, pamiętaj, że wysłanie tego wywołania do innej kolejki powoduje utratę kontekstu bieżącego śladu stosu.
A co z NSExceptions?
Crashlytics nie oferuje możliwości bezpośredniego rejestrowania i rejestrowania wystąpień NSException
. Ogólnie rzecz biorąc, interfejsy API Cocoa i Cocoa Touch nie są bezpieczne pod względem wyjątków. Oznacza to, że użycie @catch
może mieć bardzo poważne niezamierzone skutki uboczne w twoim procesie, nawet jeśli jest używane z najwyższą ostrożnością. Nigdy nie powinieneś używać instrukcji @catch
w swoim kodzie. Zapoznaj się z dokumentacją Apple na ten temat.
Dostosuj ślady stosu
Jeśli Twoja aplikacja działa w środowisku nienatywnym (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ą oznaczane 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ż zainicjować 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 zgody
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 przez nich danymi, możesz włączyć raportowanie zgody, 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 danych dla wybranych użytkowników, wywołując funkcję zastępowania zbierania danych Crashlytics w czasie wykonywania. Wartość zastąpienia pozostaje niezmieniona po uruchomieniu Twojej aplikacji, dzięki czemu Crashlytics może automatycznie zbierać raporty.
Aby zrezygnować z automatycznego zgłaszania awarii, podaj
false
jako wartość zastępującą. Gdy jest ustawiona nafalse
, nowa wartość nie ma zastosowania 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 usługa Crash Insights zapewnia nawet zasoby ułatwiające debugowanie awarii.
Crash Insights wykorzystuje zagregowane dane o awariach do identyfikowania 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 .