На панели управления 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")
Цель-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")
Цель-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)
Цель-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()
возвращает свойство описания, определенное вами для объекта. Например:
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 .
Цель-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")
Цель-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
Если вам когда-нибудь понадобится очистить идентификатор пользователя после его установки, сбросьте значение на пустую строку. Очистка идентификатора пользователя не удаляет существующие записи Crashlytics . Если вам нужно удалить записи, связанные с идентификатором пользователя, обратитесь в службу поддержки Firebase .
Сообщать о нефатальных исключениях
Помимо автоматического сообщения о сбоях вашего приложения, Crashlytics позволяет вам записывать нефатальные исключения и отправлять их вам при следующем запуске вашего приложения.
Вы можете записывать нефатальные исключения, записывая объекты NSError
с помощью метода recordError
. recordError
захватывает стек вызовов потока, вызывая [NSThread callStackReturnAddresses]
.
Быстрый
Crashlytics.crashlytics().record(error: error)
Цель-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)
Цель-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)
Цель-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)
Цель-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];
Получить навигационные журналы
Журналы навигации позволяют лучше понять взаимодействие пользователя с вашим приложением, которое привело к сбою, несмертельному событию или событию ANR. Эти журналы могут быть полезны при попытке воспроизвести и отладить проблему.
Журналы навигации основаны на Google Analytics, поэтому для получения журналов навигации вам необходимо включить Google Analytics для вашего проекта Firebase и добавить Firebase SDK для Google Analytics в свое приложение. Как только эти требования будут выполнены, навигационные журналы автоматически включаются в данные о событии на вкладке «Журналы» , когда вы просматриваете подробности проблемы.
Analytics SDK автоматически регистрирует событие screen_view
, которое позволяет в журналах навигации отображать список экранов, просмотренных до сбоя, нефатального события или события ANR. Хлебный журнал screen_view
содержит параметр firebase_screen_class
.
Журналы навигации также заполняются любыми пользовательскими событиями , которые вы вручную регистрируете в сеансе пользователя, включая данные параметров событий. Эти данные могут помочь показать серию действий пользователя, приведших к сбою, нефатальному событию или событию ANR.
Обратите внимание, что вы можете контролировать сбор и использование данных Google Analytics , включая данные, заполняющие журналы навигации.
Включить подписку на получение отчетов
По умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения. Чтобы предоставить пользователям больше контроля над отправляемыми ими данными, вы можете включить возможность включения отчетов, отключив автоматические отчеты и отправляя данные в Crashlytics только тогда, когда вы решите это сделать в своем коде:
Отключите автоматический сбор, добавив новый ключ в файл
Info.plist
:- Ключ:
FirebaseCrashlyticsCollectionEnabled
- Значение:
false
- Ключ:
Включите сбор для избранных пользователей, вызвав переопределение сбора данных Crashlytics во время выполнения. Значение переопределения сохраняется при запуске вашего приложения, поэтому Crashlytics может автоматически собирать отчеты.
Чтобы отказаться от автоматического сообщения о сбоях, передайте
false
в качестве значения переопределения. Если установлено значениеfalse
, новое значение не применяется до следующего запуска приложения.Быстрый
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Цель-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
Управление данными Crash Insights
Crash Insights помогает вам решать проблемы, сравнивая анонимные трассировки стека со трассировками из других приложений Firebase и сообщая вам, является ли ваша проблема частью более широкой тенденции. Для многих проблем Crash Insights даже предоставляет ресурсы, которые помогут вам устранить сбой.
Crash Insights использует агрегированные данные о сбоях для выявления общих тенденций стабильности. Если вы предпочитаете не делиться данными своего приложения, вы можете отказаться от Crash Insights в меню Crash Insights в верхней части списка проблем Crashlytics в консоли Firebase .
,На приборной панели Crashlytics вы можете нажать на проблему и получить подробный отчет о событиях. Вы можете настроить эти отчеты, чтобы помочь вам лучше понять, что происходит в вашем приложении, и обстоятельствах, связанных с событиями, о которых сообщалось о Crashlytics .
Прикажите ваше приложение для регистрации пользовательских ключей , пользовательских сообщений журналов и идентификаторов пользователей .
Сообщайте исключения для Crashlytics .
Автоматически получайте журналы Breadcrumb, если ваше приложение использует Firebase SDK для Google Analytics . Эти журналы дают вам видимость в действиях пользователей, приводящих к событию, Crashlytics в вашем приложении.
Выключите автоматические отчеты о сбоях и включите отчеты для ваших пользователей. Обратите внимание, что по умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения.
Добавьте пользовательские ключи
Пользовательские ключи помогут вам получить конкретное состояние вашего приложения, приводящего к сбою. Вы можете связать пары произвольных ключей/значения с вашими отчетами о сбоях, а затем использовать пользовательские ключи для поиска и отчетов о сбоях в консоли Firebase .
- На приборной панели Crashlytics вы можете найти проблемы, которые соответствуют пользовательскому ключу.
- Когда вы просматриваете конкретную проблему в консоли, вы можете просмотреть связанные с ними пользовательские клавиши для каждого события (подтаба Keys ) и даже отфильтровать события по пользовательским ключам (меню фильтра в верхней части страницы).
Используйте метод 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")
Цель-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")
Цель-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)
Цель-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()
Возвращает свойство описания, которое вы определяете для объекта. Например:
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 .
Цель-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")
Цель-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
Если вам когда -нибудь нужно будет очистить идентификатор пользователя после его установки, сбросьте значение в пустую строку. Очистка идентификатора пользователя не удаляет существующие записи Crashlytics . Если вам нужно удалить записи, связанные с идентификатором пользователя, свяжитесь с поддержкой Firebase .
Сообщите о не-лечебных исключениях
В дополнение к автоматическому сообщению о сбоях вашего приложения, Crashlytics позволяет записывать нерадостные исключения и отправляет их вам в следующий раз, когда вы запустите ваше приложение.
Вы можете записать нерадостные исключения, записывая объекты NSError
с помощью метода recordError
. recordError
захватывает стек вызовов потока, вызывая [NSThread callStackReturnAddresses]
.
Быстрый
Crashlytics.crashlytics().record(error: error)
Цель-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)
Цель-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
, преобразуются в пары клавиш и отображаются в разделе Keys/Logs в отдельной проблеме.
Журналы и пользовательские ключи
Так же, как отчеты о сбоях, вы можете встроить журналы и пользовательские ключи, чтобы добавить контекст в NSError
. Тем не менее, существует разница в том, что журналы прикрепляются к сбоям по сравнению с регистральными ошибками. Когда происходит сбой, и приложение перезапускается, бревна Crashlytics Retrieves с диска - это те, которые были написаны вплоть до момента крушения. Когда вы регистрируете NSError
, приложение не сразу завершается. Поскольку Crashlytics отправляет только отчет об ошибках зарегистрированного при запуске следующего приложения и должен ограничить количество места, выделяемого для журналов на диске, можно выйти из строя после того, как записан NSError
, так что все соответствующие журналы вывернуты к моменту Crashlytics отправлять отчет с устройства. Имейте в виду этот баланс при NSErrors
регистрации и используйте журналы и пользовательские ключи в вашем приложении.
Соображения производительности
Имейте в виду, что регистрация NSError
может быть довольно дорогим. В то время, когда вы совершаете звонок, Crashlytics захватывает стек вызовов текущего потока, используя процесс, называемый стеком, раскручивающий. Этот процесс может быть интенсивным процессором и вводом/выводом, особенно на архитектурах, которые поддерживают разматывание карла (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)
Цель-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)
Цель-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 события. Эти журналы могут быть полезны при попытке воспроизвести и отладить проблему.
Журналы Breadcrumb работают от Google Analytics, поэтому для получения журналов Breadcrumb вам необходимо включить Google Analytics для вашего проекта Firebase и добавить Firebase SDK для Google Analytics в ваше приложение. Как только эти требования будут выполнены, журналы Breadcrumb автоматически включаются в данные события на вкладке журналов , когда вы просмотрите детали проблемы.
Analytics SDK автоматически регистрирует событие screen_view
, которое позволяет журналам Breadcrumb отображать список экранов, просмотренных перед сбоем, не-фатальными или ANR событие. Журнал screen_view
Breadcrumb содержит параметр firebase_screen_class
.
Журналы Breadcrumb также заполняются любыми пользовательскими событиями , которые вы вручную войдут в сеанс пользователя, включая данные параметров события. Эти данные могут помочь показать серию действий пользователя, ведущих к сбою, не фатальническому или ANR событию.
Обратите внимание, что вы можете управлять сбором и использованием данных Google Analytics , которые включают данные, которые заполняют журналы Breadcrumb.
Включить отчеты
По умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения. Чтобы дать пользователям больше контроля над данными, которые они отправляют, вы можете включить отчеты, отключив автоматическую отчетность и отправив данные только в Crashlytics , когда вы решите в своем коде:
Выключите автоматическую коллекцию, добавив новый ключ к вашему файлу
Info.plist
:- Ключ:
FirebaseCrashlyticsCollectionEnabled
- Значение:
false
- Ключ:
Включите коллекцию для выбора пользователей, вызывая переопределение сбора данных Crashlytics Data. Стоимость переопределения сохраняется в течение запуска вашего приложения, поэтому Crashlytics может автоматически собирать отчеты.
Чтобы отказаться от автоматической отчетности по сбою, пройти
false
в качестве значения переопределения. При установке наfalse
новое значение не применяется до следующего запуска приложения.Быстрый
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Цель-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
Управлять данными о сбоях
Crash Insights поможет вам решить проблемы, сравнивая ваши анонимные трассировки стека с трассами от других приложений Firebase и сообщив вам, является ли ваша проблема частью более широкой тенденции. Для многих проблем Crash Insights даже предоставляет ресурсы, чтобы помочь вам отладить аварию.
Crash Insights использует агрегированные данные о сбоях для выявления общих тенденций стабильности. Если вы предпочитаете не делиться данными вашего приложения, вы можете отказаться от сбоев в меню Crash Insights в верхней части вашего списка проблем Crashlytics в консоли Firebase .
,In the Crashlytics dashboard, you can click into an issue and get a detailed event report. You can customize those reports to help you better understand what's happening in your app and the circumstances around events reported to Crashlytics .
Instrument your app to log custom keys , custom log messages , and user identifiers .
Report exceptions to Crashlytics .
Automatically get breadcrumb logs if your app uses the Firebase SDK for Google Analytics . These logs give you visibility into user actions leading up to a Crashlytics -collected event in your app.
Turn off automatic crash reporting and enable opt-in reporting for your users. Note that, by default, Crashlytics automatically collects crash reports for all your app's users.
Add custom keys
Custom keys help you get the specific state of your app leading up to a crash. You can associate arbitrary key/value pairs with your crash reports, then use the custom keys to search and filter crash reports in the Firebase console.
- In the Crashlytics dashboard , you can search for issues that match a custom key.
- When you're reviewing a specific issue in the console, you can view the associated custom keys for each event ( Keys subtab) and even filter the events by custom keys ( Filter menu at the top of the page).
Use the setCustomValue
method to set key/value pairs. Например:
Быстрый
// Set int_key to 100. Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key") // Set str_key to "hello". Crashlytics.crashlytics().setCustomValue("hello", forKey: "str_key")
Цель-C
When setting integers, booleans, or floats, box the value as @( 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"];
You can also modify the value of an existing key by calling the key and setting it to a different value. Например:
Быстрый
Crashlytics.crashlytics().setCustomValue(100, forKey: "int_key") // Set int_key to 50 from 100. Crashlytics.crashlytics().setCustomValue(50, forKey: "int_key")
Цель-C
[[FIRCrashlytics crashlytics] setCustomValue:@(100) forKey:@"int_key"]; // Set int_key to 50 from 100. [[FIRCrashlytics crashlytics] setCustomValue:@(50) forKey:@"int_key"];
Add key/value pairs in bulk by using the setCustomKeysAndValues
method with an NSDictionary as the only parameter:
Быстрый
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)
Цель-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];
Add custom log messages
To give yourself more context for the events leading up to a crash, you can add custom Crashlytics logs to your app. Crashlytics associates the logs with your crash data and displays them in the Crashlytics page of the Firebase console , under the Logs tab.
Быстрый
Use log()
or log(format:, arguments:)
to help pinpoint issues. If you want to get a useful log output with messages, the object that you pass to log()
must conform to the CustomStringConvertible
property. log()
returns the description property you define for the object. Например:
Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")
.log(format:, arguments:)
formats values returned from calling getVaList()
. Например:
Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))
For more details on how to use log()
or log(format:, arguments:)
, refer to the Crashlytics reference documentation .
Цель-C
Use log
or logWithFormat
to help pinpoint issues. Note that if you want to get a useful log output with messages, the object that you pass to either method must override the description
instance property. Например:
[[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];
For more details on how to use log
and logWithFormat
, refer to the Crashlytics reference documentation .
Set user identifiers
To diagnose an issue, it's often helpful to know which of your users experienced a given crash. Crashlytics includes a way to anonymously identify users in your crash reports.
To add user IDs to your reports, assign each user a unique identifier in the form of an ID number, token, or hashed value:
Быстрый
Crashlytics.crashlytics().setUserID("123456789")
Цель-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
If you ever need to clear a user identifier after you set it, reset the value to a blank string. Clearing a user identifier does not remove existing Crashlytics records. If you need to delete records associated with a user ID, contact Firebase support .
Report non-fatal exceptions
In addition to automatically reporting your app's crashes, Crashlytics lets you record non-fatal exceptions and sends them to you the next time your app launches.
You can record non-fatal exceptions by recording NSError
objects with the recordError
method. recordError
captures the thread's call stack by calling [NSThread callStackReturnAddresses]
.
Быстрый
Crashlytics.crashlytics().record(error: error)
Цель-C
[[FIRCrashlytics crashlytics] recordError:error];
When using the recordError
method, it's important to understand the NSError
structure and how Crashlytics uses the data to group crashes. Incorrect usage of the recordError
method can cause unpredictable behavior and may cause Crashlytics to limit reporting of logged errors for your app.
An NSError
object has three arguments:
-
domain: String
-
code: Int
-
userInfo: [AnyHashable : Any]? = nil
Unlike fatal crashes, which are grouped via stack trace analysis, logged errors are grouped by domain
and code
. This is an important distinction between fatal crashes and logged errors. Например:
Быстрый
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)
Цель-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];
When you log the error above, it creates a new issue that is grouped by NSSomeErrorDomain
and -1001
. Additional logged errors that use the same domain and code values are grouped under the same issue. Data contained within the userInfo
object are converted to key-value pairs and displayed in the keys/logs section within an individual issue.
Logs and custom keys
Just like crash reports, you can embed logs and custom keys to add context to the NSError
. However, there is a difference in what logs are attached to crashes versus logged errors. When a crash occurs and the app is relaunched, the logs Crashlytics retrieves from disk are those that were written right up to the time of the crash. When you log an NSError
, the app does not immediately terminate. Because Crashlytics only sends the logged error report on the next app launch and must limit the amount of space allocated for logs on disk, it is possible to log enough after an NSError
is recorded so that all relevant logs are rotated out by the time Crashlytics sends the report from the device. Keep this balance in mind when logging NSErrors
and using logs and custom keys in your app.
Соображения производительности
Keep in mind that logging an NSError
can be fairly expensive. At the time you make the call, Crashlytics captures the current thread's call stack using a process called stack unwinding. This process can be CPU and I/O intensive, particularly on architectures that support DWARF unwinding (arm64 and x86). After the unwind is complete, the information is written to disk synchronously. This prevents data loss if the next line were to crash.
While it is safe to call this API on a background thread, remember that dispatching this call to another queue loses the context of the current stack trace.
What about NSExceptions?
Crashlytics doesn't offer a facility for logging and recording NSException
instances directly. Generally speaking, the Cocoa and Cocoa Touch APIs are not exception-safe. That means the use of @catch
can have very serious unintended side-effects in your process, even when used with extreme care. You should never use @catch
statements in your code. Please refer to Apple's documentation on the topic.
Customize stack traces
If your app runs in a non-native environment (such as C++ or Unity), you can use the Exception Model API to report crash metadata in your app's native exception format. Reported exceptions are marked as non-fatals.
Быстрый
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)
Цель-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];
Custom stack frames can also be initialized with just addresses:
Быстрый
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)
Цель-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];
Get breadcrumb logs
Breadcrumb logs give you a better understanding of the interactions that a user had with your app leading up to a crash, non-fatal, or ANR event. These logs can be helpful when trying to reproduce and debug an issue.
Breadcrumb logs are powered by Google Analytics, so to get breadcrumb logs, you need to enable Google Analytics for your Firebase project and add the Firebase SDK for Google Analytics to your app. Once these requirements are met, breadcrumb logs are automatically included with an event's data within the Logs tab when you view the details of an issue.
The Analytics SDK automatically logs the screen_view
event which enables the breadcrumb logs to show a list of screens viewed before the crash, non-fatal, or ANR event. A screen_view
breadcrumb log contains a firebase_screen_class
parameter.
Breadcrumb logs are also populated with any custom events that you manually log within the user's session, including the event's parameter data. This data can help show a series of user actions leading up to a crash, non-fatal, or ANR event.
Note that you can control the collection and use of Google Analytics data , which includes the data that populates breadcrumb logs.
Enable opt-in reporting
By default, Crashlytics automatically collects crash reports for all your app's users. To give users more control over the data they send, you can enable opt-in reporting by disabling automatic reporting and only sending data to Crashlytics when you choose to in your code:
Turn off automatic collection by adding a new key to your
Info.plist
file:- Key:
FirebaseCrashlyticsCollectionEnabled
- Value:
false
- Key:
Enable collection for select users by calling the Crashlytics data collection override at runtime. The override value persists across launches of your app so Crashlytics can automatically collect reports.
To opt out of automatic crash reporting, pass
false
as the override value. When set tofalse
, the new value does not apply until the next run of the app.Быстрый
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Цель-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
Manage Crash Insights data
Crash Insights helps you resolve issues by comparing your anonymized stack traces to traces from other Firebase apps and letting you know if your issue is part of a larger trend. For many issues, Crash Insights even provides resources to help you debug the crash.
Crash Insights uses aggregated crash data to identify common stability trends. If you'd prefer not to share your app's data, you can opt-out of Crash Insights from the Crash Insights menu at the top of your Crashlytics issue list in the Firebase console .