| Выберите платформу: | iOS+ Android Flutter Unity |
Чтобы посмотреть подробный отчет о событии, нажмите на проблему на панели управления DevOps и вовлечение > Crashlytics в Firebase Console. Вы можете настраивать эти отчеты, чтобы лучше понимать, что происходит в вашем приложении и при каких обстоятельствах происходят события, о которых сообщается в Crashlytics.
Настройте приложение так, чтобы в нем регистрировались специальные ключи, специальные сообщения в журнале и идентификаторы пользователей.
Сообщайте об исключениях в Crashlytics.
Если в вашем приложении используется Firebase SDK для Google Analytics, вы будете автоматически получать историю действий пользователя. Эти журналы позволяют узнать, какие действия пользователей привели к событию, зарегистрированному Crashlytics в вашем приложении.
Отключите автоматическую отправку отчетов о сбоях и включите отправку отчетов по запросу для пользователей. Обратите внимание, что по умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения.
Добавить специальные ключи
Специальные ключи помогают определить, в каком состоянии находилось приложение перед сбоем. Вы можете связать произвольные пары "ключ-значение" с отчетами о сбоях, а затем использовать специальные ключи для поиска и фильтрации отчетов о сбоях в консоли Firebase на панели управления DevOps & Engagement (DevOps и вовлечение) > Crashlytics.
Вы можете искать проблемы, соответствующие специальному ключу.
При просмотре определенной проблемы в консоли вы можете увидеть связанные пользовательские ключи для каждого события (вложенная вкладка Ключи) и даже отфильтровать события по пользовательским ключам (меню Фильтр вверху страницы).
Чтобы задать пары "ключ-значение", используйте метод setCustomValue. Пример:
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
При установке целых чисел, логических значений или чисел с плавающей запятой упакуйте значение как @(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"];
Вы также можете изменить значение существующего ключа, вызвав его и задав другое значение. Пример:
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"];
Чтобы добавить сразу несколько пар "ключ-значение", используйте метод setCustomKeysAndValues с NSDictionary в качестве единственного параметра:
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];
Как добавить собственные сообщения в журнал
Чтобы лучше понимать, что привело к сбою, вы можете добавить в приложение специальные журналы Crashlytics. Crashlytics связывает журналы с данными о сбоях и показывает их на вкладке Журналы, когда вы просматриваете сведения о проблеме. Все проблемы можно найти в консоли Firebase на панели управления DevOps и вовлечение > Crashlytics.
Swift
Чтобы выявить проблемы, используйте 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 позволяет анонимно идентифицировать пользователей в отчетах о сбоях.
Чтобы добавить идентификаторы пользователей в отчеты, назначьте каждому пользователю уникальный идентификатор в виде номера, токена или значения хеша.
Swift
Crashlytics.crashlytics().setUserID("123456789")
Objective-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];
Если вам потребуется удалить идентификатор пользователя, задайте в качестве значения пустую строку. Очистка идентификатора пользователя не удаляет существующие записи Crashlytics. Если вам нужно удалить записи, связанные с идентификатором пользователя, обратитесь в службу поддержки Firebase.
Как регистрировать некритические исключения
Помимо автоматического создания отчетов о сбоях в приложении, Crashlytics позволяет регистрировать некритические исключения и отправляет их вам при следующем запуске приложения.
Вы можете регистрировать некритические исключения, записывая объекты NSError с помощью метода recordError. recordError фиксирует стек вызовов потока, вызывая [NSThread callStackReturnAddresses].
Swift
Crashlytics.crashlytics().record(error: error)
Objective-C
[[FIRCrashlytics crashlytics] recordError:error];
При использовании метода recordError важно понимать структуру NSError и то, как Crashlytics использует данные для группировки сбоев. Неправильное использование метода recordError может привести к непредсказуемому поведению и ограничению отчетов об ошибках в Crashlytics.
Объект NSError имеет три аргумента:
domain: Stringcode: IntuserInfo: [AnyHashable : Any]? = nil
В отличие от критических сбоев, которые группируются по результатам анализа трассировки стека, зарегистрированные ошибки группируются по domain и code. Это важное различие
между критическими сбоями и зарегистрированными ошибками. Пример:
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];
При регистрации ошибки, указанной выше, создается новая проблема, сгруппированная по 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), вы можете использовать Exception Model API, чтобы передавать метаданные о сбоях в формате нативных исключений приложения. Зарегистрированные исключения помечаются как некритические.
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];
Специальные стековые фреймы также можно инициализировать только с помощью адресов:
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];
Как получить историю действий пользователя
История действий пользователя позволяет лучше понять, что он делал в приложении перед тем, как произошел сбой, ошибка ANR или некритическая ошибка. Эти журналы могут быть полезны при попытке воспроизвести и отладить проблему.
Истории действий пользователей создаются с помощью Google Аналитики. Чтобы получать их, включите Google Аналитику для проекта Firebase и добавьте Firebase SDK для Google Analytics в приложение. После этого истории действий пользователей будут автоматически включаться в данные о событиях на вкладке Журналы при просмотре сведений о проблеме. Все проблемы можно найти в Firebase Console на панели DevOps и вовлечение > Crashlytics.
SDK Analytics автоматически регистрирует событие screen_view, что позволяет показывать в истории действий список экранов, просмотренных до сбоя, некритической ошибки или ошибки ANR. История действий пользователя screen_view содержит параметр firebase_screen_class.
В историю действий также добавляются специальные события, которые вы вручную регистрируете в рамках сеанса пользователя, включая данные параметров событий. Эти данные могут помочь показать серию действий пользователя, приведших к сбою, нефатальному событию или событию ANR.
Обратите внимание, что вы можете управлять сбором и использованием данных Google Analytics, в том числе тех, которые добавляются в историю действий.
Как включить отчеты о согласии
По умолчанию Crashlytics автоматически собирает отчеты о сбоях для всех пользователей вашего приложения. Чтобы предоставить пользователям больше контроля над отправляемыми данными, вы можете включить отправку отчетов по запросу. Для этого отключите автоматическую отправку отчетов и отправляйте данные в Crashlytics только тогда, когда это указано в коде.
Чтобы отключить автоматический сбор, добавьте новый ключ в файл
Info.plist:- Ключ:
FirebaseCrashlyticsCollectionEnabled - Значение:
false
- Ключ:
Включите сбор данных для определенных пользователей, вызвав переопределение сбора данных Crashlytics во время выполнения. Переопределенное значение сохраняется при всех последующих запусках приложения, поэтому Crashlytics может автоматически собирать отчеты для этого пользователя.
Swift
Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
Objective-C
[[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];
Если пользователь позже откажется от сбора данных, вы можете передать значение
false, которое будет применено при следующем запуске приложения и сохранится для всех последующих запусков.
Как управлять данными Crash Insights
Crash Insights помогает устранять проблемы, сравнивая ваши анонимизированные трассировки стека с трассировками из других приложений Firebase и сообщая вам, является ли ваша проблема частью более крупной тенденции. Для многих проблем Crash Insights даже предоставляет ресурсы, которые помогут вам отладить сбой.
Для выявления общих тенденций стабильности в Crash Insights используются агрегированные данные о сбоях. Если вы не хотите делиться данными своего приложения, вы можете отключить Crash Insights в меню Crash Insights в верхней части списка проблем на панели управления DevOps & Engagement (DevOps и вовлечение) > Crashlytics в консоли Firebase.
Дальнейшие действия
- Экспортируйте данные в BigQuery или Cloud Logging, чтобы использовать расширенные функции анализа, например запрашивать данные, создавать собственные сводки и настраивать специальные оповещения.