На панели инструментов Crashlytics вы можете нажать на проблему и получить подробный отчет о событии. Вы можете настроить эти отчеты, чтобы лучше понять, что происходит в вашем приложении, и обстоятельства событий, о которых сообщается в Crashlytics .
Настройте свое приложение для регистрации пользовательских ключей , пользовательских сообщений журнала и идентификаторов пользователей .
Сообщайте об исключениях в Crashlytics .
Автоматически получайте журналы навигации , если ваше приложение использует Firebase SDK для Google Analytics . Эти журналы дают вам видимость действий пользователя, ведущих к событию, собранному Crashlytics в вашем приложении.
Отключите автоматическую отчетность о сбоях и включите возможность добровольной отчетности для ваших пользователей. Обратите внимание, что по умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения.
Добавить пользовательские ключи
Пользовательские ключи помогают вам получить определенное состояние вашего приложения, приводящее к сбою. Вы можете связать произвольные пары ключ/значение с вашими отчетами о сбоях, а затем использовать пользовательские ключи для поиска и фильтрации отчетов о сбоях в консоли Firebase .
- На панели Crashlytics вы можете искать проблемы, соответствующие пользовательскому ключу.
- При просмотре определенной проблемы в консоли вы можете просматривать связанные с ней пользовательские ключи для каждого события (вкладка «Ключи» ) и даже фильтровать события по пользовательским ключам (меню «Фильтр» в верхней части страницы).
Используйте метод setCustomValue
для установки пар ключ/значение. Например:
Быстрый
// 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
При установке целых чисел, логических значений или чисел с плавающей точкой заключите значение в @( 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"];
Вы также можете изменить значение существующего ключа, вызвав ключ и установив для него другое значение. Например:
Быстрый
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"];
Массовое добавление пар ключ/значение с помощью метода setCustomKeysAndValues
с NSDictionary в качестве единственного параметра:
Быстрый
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];
Добавить пользовательские сообщения журнала
Чтобы получить больше контекста для событий, приведших к сбою, вы можете добавить пользовательские журналы Crashlytics в свое приложение. Crashlytics связывает журналы с вашими данными о сбоях и отображает их на странице Crashlytics консоли Firebase на вкладке Журналы .
Быстрый
Используйте log()
или log(format:, arguments:)
для выявления проблем. Если вы хотите получить полезный вывод журнала с сообщениями, объект, который вы передаете в log()
должен соответствовать свойству CustomStringConvertible
. log()
возвращает свойство description, которое вы определяете для объекта. Например:
Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")
.log(format:, arguments:)
форматирует значения, возвращаемые вызовом getVaList()
. Например:
Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))
Более подробную информацию об использовании log()
или log(format:, arguments:)
можно найти в справочной документации Crashlytics .
Objective-C
Используйте log
или logWithFormat
для выявления проблем. Обратите внимание, что если вы хотите получить полезный вывод журнала с сообщениями, объект, который вы передаете в любой из методов, должен переопределять свойство экземпляра description
. Например:
[[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];
Более подробную информацию об использовании log
и logWithFormat
можно найти в справочной документации Crashlytics .
Установить идентификаторы пользователя
Для диагностики проблемы часто бывает полезно знать, кто из ваших пользователей столкнулся с данным сбоем. Crashlytics включает способ анонимной идентификации пользователей в ваших отчетах о сбоях.
Чтобы добавить идентификаторы пользователей в отчеты, присвойте каждому пользователю уникальный идентификатор в виде идентификационного номера, токена или хешированного значения:
Быстрый
Crashlytics.crashlytics().setUserID("123456789")
Objective-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
Если вам когда-либо понадобится очистить идентификатор пользователя после его установки, сбросьте значение на пустую строку. Очистка идентификатора пользователя не удаляет существующие записи Crashlytics . Если вам нужно удалить записи, связанные с идентификатором пользователя, обратитесь в службу поддержки Firebase .
Сообщить о нефатальных исключениях
Помимо автоматического оповещения о сбоях вашего приложения, Crashlytics позволяет регистрировать нефатальные исключения и отправлять их вам при следующем запуске приложения.
Вы можете регистрировать нефатальные исключения, записывая объекты NSError
с помощью метода recordError
. recordError
захватывает стек вызовов потока, вызывая [NSThread callStackReturnAddresses]
.
Быстрый
Crashlytics.crashlytics().record(error: error)
Objective-C
[[FIRCrashlytics crashlytics] recordError:error];
При использовании метода recordError
важно понимать структуру NSError
и то, как Crashlytics использует данные для группировки сбоев. Неправильное использование метода recordError
может привести к непредсказуемому поведению и может привести к тому, что Crashlytics ограничит отчетность о зарегистрированных ошибках для вашего приложения.
Объект NSError
имеет три аргумента:
-
domain: String
-
code: Int
-
userInfo: [AnyHashable : Any]? = nil
В отличие от фатальных сбоев, которые группируются с помощью анализа трассировки стека, зарегистрированные ошибки группируются по domain
и code
. Это важное различие между фатальными сбоями и зарегистрированными ошибками. Например:
Быстрый
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];
Когда вы регистрируете ошибку выше, она создает новую проблему, сгруппированную по NSSomeErrorDomain
и -1001
. Дополнительные зарегистрированные ошибки, которые используют тот же домен и кодовые значения, группируются под той же проблемой. Данные, содержащиеся в объекте userInfo
, преобразуются в пары ключ-значение и отображаются в разделе ключей/журналов в рамках отдельной проблемы.
Журналы и пользовательские ключи
Как и в случае с отчетами о сбоях, вы можете встраивать журналы и пользовательские ключи для добавления контекста в NSError
. Однако есть разница в том, какие журналы прикрепляются к сбоям, а какие — к зарегистрированным ошибкам. Когда происходит сбой и приложение перезапускается, журналы, которые Crashlytics извлекает с диска, — это те, которые были записаны непосредственно до момента сбоя. Когда вы регистрируете NSError
, приложение не завершает работу немедленно. Поскольку Crashlytics отправляет только зарегистрированный отчет об ошибке при следующем запуске приложения и должно ограничивать объем места, выделенного для журналов на диске, можно регистрировать достаточно после записи NSError
, чтобы все соответствующие журналы были удалены к тому времени, когда Crashlytics отправит отчет с устройства. Помните об этом балансе при регистрации NSErrors
и использовании журналов и пользовательских ключей в вашем приложении.
Соображения производительности
Помните, что регистрация NSError
может быть довольно затратной. В момент вызова Crashlytics захватывает стек вызовов текущего потока с помощью процесса, называемого раскручиванием стека. Этот процесс может быть ресурсоемким для ЦП и ввода-вывода, особенно на архитектурах, поддерживающих раскручивание DWARF (arm64 и x86). После завершения раскручивания информация синхронно записывается на диск. Это предотвращает потерю данных в случае сбоя следующей строки.
Хотя вызывать этот API в фоновом потоке безопасно, помните, что при отправке этого вызова в другую очередь теряется контекст текущей трассировки стека.
А как насчет NSExceptions?
Crashlytics не предлагает возможности для регистрации и записи экземпляров NSException
напрямую. Вообще говоря, API Cocoa и Cocoa Touch не являются безопасными для исключений. Это означает, что использование @catch
может иметь очень серьезные непреднамеренные побочные эффекты в вашем процессе, даже при использовании с крайней осторожностью. Никогда не используйте операторы @catch
в своем коде. Пожалуйста, обратитесь к документации Apple по этой теме.
Настройте трассировки стека
Если ваше приложение работает в неродной среде (например, C++ или Unity), вы можете использовать API модели исключений для сообщения метаданных сбоя в родном формате исключений вашего приложения. Сообщаемые исключения помечаются как нефатальные.
Быстрый
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];
Пользовательские стековые фреймы также можно инициализировать только с помощью адресов:
Быстрый
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];
Получить навигационные крошки
Журналы Breadcrumb дают вам лучшее понимание взаимодействий, которые пользователь имел с вашим приложением, что привело к сбою, нефатальному или событию ANR. Эти журналы могут быть полезны при попытке воспроизвести и отладить проблему.
Журналы навигации работают на базе Google Analytics, поэтому для получения журналов навигации вам необходимо включить Google Analytics для вашего проекта Firebase и добавить Firebase SDK для Google Analytics в свое приложение. После выполнения этих требований журналы навигации автоматически включаются в данные события на вкладке «Журналы» при просмотре сведений о проблеме.
Analytics SDK автоматически регистрирует событие screen_view
, которое позволяет журналам breadcrumb отображать список экранов, просмотренных до сбоя, нефатального или ANR-события. Журнал screen_view
breadcrumb содержит параметр firebase_screen_class
.
Журналы Breadcrumb также заполняются любыми пользовательскими событиями , которые вы вручную регистрируете в сеансе пользователя, включая данные параметров события. Эти данные могут помочь отобразить ряд действий пользователя, которые привели к сбою, нефатальному событию или событию ANR.
Обратите внимание, что вы можете контролировать сбор и использование данных Google Analytics , включая данные, заполняющие журналы навигации.
Включить возможность отправки отчетов
По умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения. Чтобы предоставить пользователям больше контроля над отправляемыми ими данными, вы можете включить отправку отчетов по выбору, отключив автоматическую отправку отчетов и отправляя данные в Crashlytics только тогда, когда вы выберете это в своем коде.
Отключите автоматический сбор, добавив новый ключ в файл
Info.plist
:- Ключ:
FirebaseCrashlyticsCollectionEnabled
- Значение:
false
- Ключ:
Включите сбор для выбранных пользователей, вызвав переопределение сбора данных Crashlytics во время выполнения. Значение переопределения сохраняется при всех последующих запусках вашего приложения, поэтому Crashlytics может автоматически собирать отчеты для этого пользователя.
Быстрый
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Objective-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
Если пользователь позже откажется от сбора данных, вы можете передать
false
в качестве переопределяющего значения, которое будет применено при следующем запуске приложения пользователем и будет сохраняться при всех последующих запусках для этого пользователя.
Управление данными Crash Insights
Crash Insights помогает вам решать проблемы, сравнивая ваши анонимные трассировки стека с трассировками из других приложений Firebase и сообщая вам, является ли ваша проблема частью более крупной тенденции. Для многих проблем Crash Insights даже предоставляет ресурсы, которые помогут вам отладить сбой.
Crash Insights использует агрегированные данные о сбоях для определения общих тенденций стабильности. Если вы предпочитаете не делиться данными своего приложения, вы можете отказаться от Crash Insights в меню Crash Insights в верхней части списка проблем Crashlytics в консоли Firebase .