Dostosowywanie raportów o awariach na platformach Apple

Wybierz platformę: iOS+ Android Flutter Unity


Możesz kliknąć problem i uzyskać szczegółowy raport o zdarzeniu na panelu DevOps i zaangażowanie > Crashlytics w Firebase konsoli. Możesz dostosować te raporty, aby lepiej zrozumieć, co dzieje się w Twojej aplikacji, oraz okoliczności zdarzeń zgłaszanych do Crashlytics.

Dodawanie kluczy niestandardowych

Klucze niestandardowe pomagają uzyskać konkretny stan aplikacji, który doprowadził 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 na panelu DevOps i zaangażowanie > Crashlytics w Firebase konsoli.

  • 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) oraz filtrować zdarzenia 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 liczb całkowitych, wartości logicznych lub zmiennoprzecinkowych 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"];

Możesz też zmodyfikować wartość istniejącego klucza, wywołując klucz i ustawiając go na 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"];

Aby dodać pary klucz-wartość zbiorczo, użyj 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 dziennika

Aby uzyskać więcej kontekstu dotyczącego zdarzeń prowadzących do awarii, możesz dodać niestandardowe Crashlytics dzienniki do aplikacji. Crashlytics powiąże dzienniki z danymi o awariach i wyświetli je na karcie Dzienniki , gdy wyświetlisz szczegóły problemu (wszystkie problemy znajdziesz na panelu DevOps i zaangażowanie > Crashlytics dashboard w konsoli Firebase).

Swift

Aby pomóc w identyfikowaniu problemów, użyj funkcji log() lub log(format:, arguments:). Jeśli chcesz uzyskać przydatne dane wyjściowe dziennika z komunikatami, obiekt przekazywany do log() musi być zgodny z CustomStringConvertible właściwością. log() zwraca właściwość opisu zdefiniowaną dla obiektu. Przykład:

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

.log(format:, arguments:) formatuje wartości zwracane przez wywołanie getVaList(). Przykład:

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

Więcej informacji o tym, jak używać funkcji log() lub log(format:, arguments:), znajdziesz w Crashlytics dokumentacji referencyjnej.

Objective-C

Aby pomóc w identyfikowaniu problemów, użyj funkcji log lub logWithFormat. Pamiętaj, że jeśli chcesz uzyskać przydatne dane wyjściowe dziennika z komunikatami, obiekt przekazywany do dowolnej z tych metod musi zastępować 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 używać funkcji log i logWithFormat, znajdziesz w Crashlytics dokumentacji referencyjnej.

Ustawianie identyfikatorów użytkowników

Aby zdiagnozować problem, często przydatne jest sprawdzenie, który z użytkowników doświadczył danej awarii. Crashlytics zawiera sposób na 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 wartości skrótu:

Swift

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

Objective-C

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

Jeśli po ustawieniu identyfikatora użytkownika musisz go wyczyścić, zresetuj wartość do pustego ciągu znaków. Wyczyszczenie identyfikatora użytkownika nie powoduje usunięcia istniejących Crashlytics rekordów. Jeśli musisz usunąć rekordy powiązane z identyfikatorem użytkownika, skontaktuj się z zespołem pomocy Firebase.

Zgłaszanie wyjątków niekrytycznych

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żesz rejestrować, rejestrując obiekty NSError za pomocą metody recordError. recordError przechwytuje stos wywołań wątku, wywołując [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 i sposób, w jaki Crashlytics używa danych do grupowania awarii. Nieprawidłowe użycie metody recordError może powodować nieprzewidywalne zachowanie i może spowodować, że Crashlytics ograniczy raportowanie zarejestrowanych błędów w aplikacji.

Obiekt NSError ma 3 argumenty:

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

W przeciwieństwie do awarii krytycznych, które są grupowane na podstawie analizy zrzutu stosu, zarejestrowane błędy są grupowane według domain i code. Jest to ważna różnica między awariami 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];

Gdy zarejestrujesz powyższy błąd, utworzy się 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 w ramach tego samego problemu. Dane zawarte w obiekcie userInfo są konwertowane na pary klucz-wartość i wyświetlane w sekcji kluczy/dzienników w ramach poszczególnych problemów.

.

Dzienniki i klucze niestandardowe

Podobnie jak w przypadku raportów 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, a jakie do zarejestrowanych błędów. Gdy wystąpi awaria i aplikacja zostanie ponownie uruchomiona, dzienniki Crashlytics pobiera z dysku, to te, które zostały zapisane do momentu awarii. Gdy zarejestrujesz NSError, aplikacja nie zostanie natychmiast zamknięta. Ponieważ Crashlytics wysyła raport o zarejestrowanym błędzie dopiero przy następnym uruchomieniu aplikacji i musi ograniczyć ilość miejsca na dysku przydzielonego na dzienniki, możliwe jest zarejestrowanie wystarczającej ilości danych po zarejestrowaniu NSError aby wszystkie odpowiednie dzienniki zostały usunięte, zanim Crashlytics wyśle raport z urządzenia. Pamiętaj o tym, rejestrując NSErrors i używając dzienników oraz kluczy niestandardowych w aplikacji.

Możliwe spowolnienie działania witryny

Pamiętaj, że rejestrowanie NSError może być dość kosztowne. W momencie wywołania CrashlyticsCrashlytics przechwytuje stos wywołań bieżącego wątku za pomocą procesu zwanego rozwijaniem stosu. Proces ten może być intensywny pod względem wykorzystania procesora i operacji wejścia/wyjścia, szczególnie w przypadku architektur obsługujących rozwijanie DWARF (arm64 i x86). Po zakończeniu rozwijania informacje są zapisywane na dysku synchronicznie. Zapobiega to utracie danych w przypadku awarii w następnym wierszu.

Chociaż wywoływanie tego interfejsu API w wątku w tle jest bezpieczne, pamiętaj, że wysyłanie tego wywołania do innej kolejki powoduje utratę kontekstu bieżącego stosu wywołań.

A co z NSExceptions?

Crashlytics nie oferuje możliwości bezpośredniego rejestrowania i zapisywania instancji NSException. Ogólnie rzecz biorąc, interfejsy API Cocoa i Cocoa Touch nie są bezpieczne w przypadku wyjątków. Oznacza to, że użycie @catch może mieć bardzo poważne niezamierzone skutki uboczne w Twoim procesie, nawet jeśli używasz go z dużą ostrożnością. W kodzie nigdy nie należy używać instrukcji @catch. Więcej informacji na ten temat znajdziesz w dokumentacji Apple.

Dostosowywanie stosów wywołań

Jeśli Twoja aplikacja działa w środowisku innym niż natywne (np. C++ lub Unity), możesz użyć interfejsu API modelu wyjątków, aby zgłaszać metadane awarii 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];

Niestandardowe ramki stosu można też inicjować 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 ścieżki

Dzienniki ścieżki pozwalają lepiej zrozumieć interakcje użytkownika z Twoją aplikacją, które doprowadziły do awarii, wyjątku niekrytycznego lub zdarzenia ANR. Te dzienniki mogą być przydatne podczas próby odtworzenia i debugowania problemu.

Dzienniki ścieżki są obsługiwane przez Google Analytics, więc aby je uzyskać, musisz włączyć Google Analytics w projekcie Firebase i dodać do aplikacji pakiet Firebase SDK dla Google Analytics. Gdy te wymagania zostaną spełnione, dzienniki ścieżki będą automatycznie dołączane do danych zdarzenia na karcie Dzienniki , gdy wyświetlisz szczegóły problemu (wszystkie problemy znajdziesz na panelu DevOps i zaangażowanie > Crashlytics w konsoli Firebase).

Pakiet Analytics SDK automatycznie rejestruje zdarzenie screen_view które umożliwia wyświetlanie w dziennikach ścieżki listy ekranów wyświetlanych przed awarią, wyjątkiem niekrytycznym lub zdarzeniem ANR. Dziennik ścieżki screen_view zawiera parametr firebase_screen_class.

Dzienniki ścieżki są też wypełniane wszystkimi zdarzeniami niestandardowymi, które ręcznie rejestrujesz w sesji użytkownika , w tym danymi parametrów zdarzenia. Te dane mogą pomóc w pokazaniu serii działań użytkownika, które doprowadziły do awarii, wyjątku niekrytycznego lub zdarzenia ANR.

Pamiętaj, że możesz kontrolować zbieranie i wykorzystywanie danychGoogle Analytics, w tym danych, które wypełniają dzienniki ścieżki.

Włączanie raportowania za zgodą użytkownika

Domyślnie Crashlytics automatycznie zbiera raporty o awariach wszystkich użytkowników Twojej aplikacji. Aby zapewnić użytkownikom większą kontrolę nad wysyłanymi przez nich danymi, możesz włączyć raportowanie za zgodą użytkownika, wyłączając automatyczne raportowanie i wysyłając dane do Crashlytics tylko wtedy, gdy zdecydujesz się na to 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 w czasie działania aplikacji Crashlytics zastąpienie zbierania danych przez Crashlytics. Wartość zastąpienia jest zachowywana we wszystkich kolejnych uruchomieniach aplikacji, dzięki czemu Crashlytics może automatycznie zbierać raporty dla tego użytkownika.

    Swift

    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)

    Objective-C

    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

    Jeśli użytkownik później zrezygnuje ze zbierania danych, możesz przekazać wartość false jako wartość zastąpienia. Zostanie ona zastosowana przy następnym uruchomieniu aplikacji przez użytkownika i będzie zachowywana we wszystkich kolejnych uruchomieniach.

Zarządzanie danymi statystyk awarii

Statystyki awarii pomagają rozwiązywać problemy, porównując zanonimizowane stosy wywołań ze stosami wywołań z innych aplikacji Firebase i informując, czy Twój problem jest częścią większego trendu. W przypadku wielu problemów statystyki awarii udostępniają też zasoby, które pomagają w debugowaniu awarii.

Statystyki awarii używają zagregowanych danych o awariach do identyfikowania typowych trendów stabilności. Jeśli nie chcesz udostępniać danych aplikacji, możesz zrezygnować ze statystyk awarii w menu Statystyki awarii u góry listy problemów na panelu DevOps i zaangażowanie > Crashlytics dashboard w Firebase konsoli.

Dalsze kroki