Dostosowywanie raportów o awariach na platformach Apple

Wybierz platformę: iOS+ Android Flutter Unity


Możesz kliknąć problem i wyświetlić szczegółowy raport Zdarzenia w Firebase konsoli na panelu DevOps i zaangażowanie > Crashlytics. Możesz dostosowywać te raporty, aby lepiej zrozumieć, co dzieje się w aplikacji i jakie są okoliczności zdarzeń zgłaszanych do Crashlytics.

Dodawanie kluczy niestandardowych

Klucze niestandardowe pomagają poznać konkretny stan aplikacji, który doprowadził do awarii. Z raportami o awariach możesz powiązać dowolne pary klucz-wartość, a następnie używać kluczy niestandardowych do wyszukiwania i filtrowania raportów o awariach w panelu DevOps i zaangażowanie > Crashlytics w konsoli Firebase.

  • 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), a nawet 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 liczb zmiennoprzecinkowych umieść wartość w polu jako @(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ż zmienić wartość istniejącego klucza, wywołując go i ustawiając 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 uzyskać więcej informacji o zdarzeniach, które doprowadziły do awarii, możesz dodać do aplikacji niestandardowe dzienniki Crashlytics. Crashlytics powiąże dzienniki z danymi o awariach i wyświetli je na karcie Dzienniki, gdy będziesz przeglądać szczegóły problemu (wszystkie problemy możesz zobaczyć w Firebase Console na panelu DevOps i zaangażowanie > Crashlytics).

Swift

Aby ułatwić sobie wykrywanie problemów, użyj log() lub log(format:, arguments:). Jeśli chcesz uzyskać przydatne dane wyjściowe logu z wiadomościami, obiekt przekazywany do log() musi być zgodny z właściwością CustomStringConvertible. 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 używaniu log() lub log(format:, arguments:) znajdziesz w Crashlytics dokumentacji referencyjnej.

Objective-C

Aby ułatwić sobie wykrywanie problemów, użyj log lub logWithFormat. Pamiętaj, że jeśli chcesz uzyskać przydatne dane wyjściowe logu z wiadomościami, 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 używaniu log i logWithFormat znajdziesz w Crashlytics dokumentacji referencyjnej.

Ustawianie identyfikatorów użytkowników

Aby zdiagnozować problem, często warto wiedzieć, u których użytkowników wystąpiła dana awaria. Crashlytics zawiera sposób anonimowej identyfikacji 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 usunąć, zresetuj jego wartość na pusty ciąg znaków. Wyczyszczenie identyfikatora użytkownika nie powoduje usunięcia dotychczasowych rekordów Crashlytics. Jeśli chcesz usunąć rekordy powiązane z identyfikatorem użytkownika, skontaktuj się z zespołem pomocy Firebase.

Zgłaszanie wyjątków niekrytycznych

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

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

Swift

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

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Jeśli używasz metody recordError, musisz znać strukturę NSError i wiedzieć, jak Crashlytics wykorzystuje dane do grupowania awarii. Nieprawidłowe użycie metody recordError może powodować nieprzewidywalne działanie i sprawić, że usługa Crashlytics ograniczy raportowanie błędów zarejestrowanych 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. 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, zostanie utworzony nowy problem, który będzie 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/logów w ramach pojedynczego problemu.

Logi i klucze niestandardowe

Podobnie jak w przypadku raportów o awariach, możesz umieszczać logi i klucze niestandardowe, aby dodać kontekst do NSError. Istnieje jednak różnica między dziennikami dołączanymi do awarii a dziennikami dołączanymi do zarejestrowanych błędów. Gdy dojdzie do awarii i aplikacja zostanie ponownie uruchomiona, logi, które Crashlytics pobierze z dysku, będą tymi, które zostały zapisane bezpośrednio przed awarią. Gdy zarejestrujesz zdarzenie NSError, aplikacja nie zostanie natychmiast zamknięta. Crashlytics wysyła raport o błędzie dopiero przy następnym uruchomieniu aplikacji i musi ograniczyć ilość miejsca na dysku przeznaczonego na dzienniki. Dlatego po zarejestrowaniu zdarzenia NSError może zostać zapisanych tyle informacji, że wszystkie istotne dzienniki zostaną usunięte, zanim Crashlytics wyśle raport z urządzenia. Pamiętaj o tym, gdy rejestrujesz NSErrors i używasz logów oraz kluczy niestandardowych w aplikacji.

Możliwe spowolnienie działania witryny

Pamiętaj, że rejestrowanie zdarzenia NSError może być dość kosztowne. W momencie wywołania Crashlytics przechwytuje stos wywołań bieżącego wątku, używając procesu zwanego rozwinięciem stosu. Ten proces może być obciążający dla procesora i operacji wejścia/wyjścia, zwłaszcza w architekturach obsługujących wywijanie DWARF (arm64 i x86). Po zakończeniu wycofywania informacje są zapisywane na dysku synchronicznie. Zapobiega to utracie danych w przypadku awarii następnego wiersza.

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 zrzutu stosu.

Co z NSExceptions?

Crashlytics nie oferuje funkcji bezpośredniego logowania i rejestrowania instancji 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 procesie, nawet jeśli jest używane z zachowaniem najwyższej ostrożności. Nigdy nie używaj instrukcji @catch w kodzie. Więcej informacji znajdziesz w dokumentacji Apple.

Dostosowywanie zrzutów stosu

Jeśli aplikacja działa w środowisku nienatywnym (np. C++ lub Unity), możesz użyć interfejsu Exception Model API, aby zgłaszać metadane awarii w formacie natywnego wyjątku 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ć za pomocą samych 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 logów działań użytkownika

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

Logi działań użytkownika są obsługiwane przez Google Analytics, więc aby je otrzymywać, musisz włączyć Google Analytics w projekcie w Firebase i dodać do aplikacji pakiet SDK Firebase dla Google Analytics. Gdy spełnisz te wymagania, logi działań użytkownika będą automatycznie dołączane do danych zdarzenia na karcie Logi, gdy wyświetlisz szczegóły problemu (wszystkie problemy możesz zobaczyć w konsoli Firebase na panelu DevOps i zaangażowanie > Crashlytics).

Pakiet SDK Analytics automatycznie rejestruje zdarzenie screen_view, dzięki czemu logi działań użytkownika mogą wyświetlać listę ekranów wyświetlonych przed awarią, błędem niekrytycznym lub zdarzeniem ANR. Log działań użytkownika screen_view zawiera parametr firebase_screen_class.

Logi działań użytkownika są też wypełniane wszelkimi zdarzeniami niestandardowymi, które ręcznie rejestrujesz w sesji użytkownika, w tym danymi parametrów zdarzenia. Te dane mogą pokazywać serię działań użytkownika, 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, które wypełniają logi działań użytkownika.

Włączanie raportowania o wyrażeniu zgody

Domyślnie Crashlytics automatycznie zbiera raporty o awariach od wszystkich użytkowników aplikacji. Aby zapewnić użytkownikom większą kontrolę nad wysyłanymi danymi, możesz włączyć raportowanie na podstawie akceptacji, wyłączając raportowanie automatyczne i wysyłając dane do Crashlytics tylko wtedy, gdy wybierzesz tę 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 zachowywana we wszystkich kolejnych uruchomieniach aplikacji, dzięki czemu Crashlytics może automatycznie zbierać raporty dotyczące 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ść zastępującą false, która zostanie zastosowana przy następnym uruchomieniu aplikacji przez użytkownika i będzie obowiązywać przy wszystkich kolejnych uruchomieniach.

Zarządzanie danymi Crash Insights

Crash Insights pomaga rozwiązywać problemy, porównując zanonimizowane zrzuty stosu ze zrzutami z innych aplikacji w Firebase i informując, czy problem jest częścią większego trendu. W przypadku wielu problemów Crash Insights udostępnia nawet zasoby, które pomagają w debugowaniu awarii.

Statystyki awarii wykorzystują zbiorcze dane o awariach do identyfikowania typowych trendów dotyczących 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 w panelu DevOps i zaangażowanie > Crashlytics w konsoli Firebase.

Dalsze kroki