| Выберите платформу: | iOS+ Android Flutter Unity |
На панели управления 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 , преобразуются в пары ключ-значение и отображаются в разделе keys/logs в рамках отдельной задачи.
Журналы и пользовательские ключи
Как и в случае с отчетами о сбоях, вы можете встраивать логи и пользовательские ключи для добавления контекста к 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];
Получите хлебные крошки
Журналы "хлебных крошек" позволяют лучше понять взаимодействие пользователя с вашим приложением, предшествовавшее сбою, некритической ошибке или событию ANR. Эти журналы могут быть полезны при попытке воспроизвести и отладить проблему.
Отслеживание событий с помощью Google Analytics осуществляется на основе навигационной цепочки, поэтому для получения таких данных необходимо включить Google Analytics для вашего проекта Firebase и добавить SDK Firebase для Google Analytics в ваше приложение. После выполнения этих требований данные автоматически будут добавляться к данным события на вкладке «Журналы» при просмотре подробностей проблемы.
Analytics SDK автоматически регистрирует событие screen_view , что позволяет отображать в навигационной цепочке список экранов, просмотренных до сбоя, некритического события или события ANR. В навигационной цепочке screen_view содержится параметр firebase_screen_class .
В журналы "хлебных крошек" также добавляются любые пользовательские события , которые вы регистрируете вручную в рамках сеанса пользователя, включая данные параметров события. Эти данные могут помочь отобразить последовательность действий пользователя, приведших к сбою, некритическому событию или событию 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 .