Поделиться через


Сбои Центра приложений (iOS)

Это важно

Центр приложений Visual Studio был прекращен 31 марта 2025 г., за исключением функций аналитики и диагностики, которые будут поддерживаться до 30 июня 2026 г. Подробнее.

Центр приложений Crashes автоматически создаёт журнал сбоев при каждом сбое вашего приложения. Журнал сначала записывается в хранилище устройства, и когда пользователь снова запускает приложение, отчет о сбоях будет отправлен в Центр приложений. Сбор сбоев работает как для бета-, так и для динамических приложений, т. е. отправленных в App Store. Журналы сбоев содержат ценные сведения, которые помогут устранить сбой.

Если вы еще не настроили пакет SDK в приложении, следуйте разделу "Начало работы ".

Кроме того, журналы сбоев в iOS требуют символьного обозначения, ознакомьтесь с документацией по диагностике Центра приложений , которая объясняет, как предоставить символы для приложения.

Замечание

Пакет SDK не перенаправляет журнал сбоев, если вы подключены к отладчику. Убедитесь, что отладчик не подключен при сбое приложения.

Замечание

Чтобы получить правильно символьные трассировки стека, убедитесь, что битовый код отключен. Дополнительные сведения о бит-коде см. в документации по символике iOS в Центре приложений.

Замечание

В версии 4.0.0 Центра приложений были введены критические изменения. Ознакомьтесь с разделом Миграция на SDK App Center 4.0.0 и выше для переноса Центра приложений с предыдущих версий.

Отчеты о сбоях в расширениях

Центр приложений поддерживает отчеты о сбоях в расширениях iOS. Использование совпадает с использованием приложения контейнера.

Создание тестового сбоя

App Center Crashes предоставляет API для генерации тестового сбоя, что упрощает тестирование пакета SDK. Этот API можно использовать только в тестовых и бета-приложениях и не будет делать ничего в рабочих приложениях.

[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()

Дополнительные сведения о предыдущем сбое

App Center Crashes предоставляет два API, которые дают вам больше информации в случае сбоя вашего приложения.

Приложение получило предупреждение о низкой памяти в предыдущем сеансе?

В любое время после запуска пакета SDK можно проверить, получено ли приложение предупреждение о памяти в предыдущем сеансе:

[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession

Замечание

Этот метод должен использоваться только после того как Crashes был запущен, до запуска всегда вернёт NO или false.

Замечание

В некоторых случаях устройство с низкой памятью не может отправлять события.

Произошел сбой приложения в предыдущем сеансе?

В любое время после запуска пакета SDK можно проверить, произошло ли сбой приложения в предыдущем запуске:

[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession

Это удобно, если вы хотите настроить поведение или пользовательский интерфейс приложения после сбоя.

Замечание

Этот метод должен использоваться только после того как MSACCrashes был запущен, до запуска всегда вернёт NO или false.

Сведения о последнем сбое

Если ваше приложение завершилось сбоем, вы можете получить детали о последнем сбое.

MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport

Замечание

Этот метод должен использоваться только после Crashes запуска, он всегда будет возвращать nil до запуска.

Существует множество вариантов использования для этого API, наиболее распространенный — это люди, которые вызывают этот API и реализуют пользовательские crashesDelegate.

Настройте использование функций сбоев в Центре приложений

Сервис сбоев App Center предоставляет обратные вызовы для разработчиков, позволяющие выполнять дополнительные действия перед отправкой журналов сбоев в App Center.

Чтобы добавить пользовательское поведение, необходимо использовать протокол CrashesDelegate, все его методы необязательны.

Регистрация в качестве делегата

[MSACCrashes setDelegate:self];
Crashes.delegate = self

Замечание

Перед вызовомAppCenter.startнеобходимо задать делегат, так как Центр приложений запускает сбои обработки сразу после запуска.

Следует ли обрабатывать аварию?

Реализуйте метод crashes:shouldProcessErrorReport: в классе, который использует протокол CrashesDelegate, если вы хотите определить, нужно ли обрабатывать конкретную ошибку. Например, может произойти сбой на уровне системы, который вы хотите игнорировать и что вы не хотите отправлять в Центр приложений.

- (BOOL)crashes:(MSACCrashes *)crashes shouldProcessErrorReport:(MSACErrorReport *)errorReport {
  return YES; // return YES if the crash report should be processed, otherwise NO.
}
func crashes(_ crashes: Crashes, shouldProcess errorReport: ErrorReport) -> Bool {
  return true; // return true if the crash report should be processed, otherwise false.
}

Обработанные ошибки

Центр приложений также позволяет отслеживать ошибки, используя метод trackError для обработки исключений. Приложение может при необходимости присоединять свойства или вложения к обработанном отчету об ошибке, чтобы предоставить дополнительный контекст.

@try {
  // Throw error.
} @catch (NSError *error) {

  // Init attachments.
  NSArray<MSACErrorAttachmentLog *> attachments = @[ MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"] ]

  // Init properties.
  NSDictionary *properties = @{ "Category" : "Music", "Wifi" : "On" };

  // Track errors.
  [MSACCrashes trackError:error withProperties:properties attachments:attachments];
  [MSACCrashes trackError:error withProperties:properties attachments:nil];
  [MSACCrashes trackError:error withProperties:nil attachments:attachments];
  [MSACCrashes trackError:error withProperties:nil attachments:nil];
}
do {
  // Throw error.
} catch {

  // Init attachments.
  let attachments = [ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")]

  // Init properties.
  let properties:Dictionary<String, String> = ["Category" : "Music", "Wifi" : "On"]

  // Track errors.
  Crashes.trackError(error, properties: properties, attachments: attachments)
  Crashes.trackError(error, properties: properties, attachments: nil)
  Crashes.trackError(error, properties: nil, attachments: attachments)
  Crashes.trackError(error, properties: nil, attachments: nil)
}

Для отслеживания исключений можно использовать trackException метод:

@try {
  // Throw exceptions.
} @catch (NSException *exception) {

  // Init exceptions.
  MSACExceptionModel *customException1 = [MSACExceptionModel initWithType:@"Custom exception" exceptionMessage:"Track custom exception.", stackTrace:exception.callStackSymbols];
  MSACExceptionModel *customException2 = [MSACExceptionModel initWithException:exception];

  // Track exceptions.
  [MSACCrashes trackException:customException1 withProperties:properties attachments:nil];
  [MSACCrashes trackException:customException2 withProperties:properties attachments:nil];
}
do {
  // Throw exception.
} catch {

  // Init exception.
  let exception = ExceptionModel(withType: "Custom exception", exceptionMessage: "Track custom exception.", stackTrace: Thread.callStackSymbols)

  // Track exception.
  Crashes.trackException(exception, properties: properties, attachments: nil)
}

Если конфиденциальность пользователей важна для вас, вы можете получить подтверждение пользователя перед отправкой отчета о сбоях в Центр приложений. Пакет SDK предоставляет обратный вызов, который сообщает Центру приложений Crashes ожидать подтверждения от пользователя перед отправкой отчетов о сбоях.

Если вы решили это сделать, вы несете ответственность за получение подтверждения пользователя, например с помощью диалогового окна с одним из следующих параметров: Always send, Send и Don't send. На основе входных данных вы сообщите App Center Crashes, что делать, и аварийное завершение работы будет обрабатываться соответствующим образом.

Замечание

Пакет SDK не отображает диалоговое окно для этого, приложение должно предоставить собственный пользовательский интерфейс для запроса согласия пользователя.

Замечание

Приложение не должно вызывать notifyWithUserConfirmation явным образом, если оно не реализует диалоговое окно подтверждения пользователя; модуль сбоев будет обрабатывать отправку журналов для вас неявно.

В следующем методе показано, как настроить обработчик подтверждения пользователя:

[MSACCrashes setUserConfirmationHandler:(^(NSArray<MSACErrorReport *> *errorReports) {

  // Your code to present your UI to the user, e.g. an UIAlertController.
  UIAlertController *alertController = [UIAlertController
      alertControllerWithTitle:@"Sorry about that!"
                      message:@"Do you want to send an anonymous crash report so we can fix the issue?"
                preferredStyle:UIAlertControllerStyleAlert];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Don't send"
                                        style:UIAlertActionStyleCancel
                                      handler:^(UIAlertAction *action) {
                                        [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
                                      }]];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Send"
                                        style:UIAlertActionStyleDefault
                                      handler:^(UIAlertAction *action) {
                                        [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
                                      }]];

  [alertController
      addAction:[UIAlertAction actionWithTitle:@"Always send"
                                        style:UIAlertActionStyleDefault
                                      handler:^(UIAlertAction *action) {
                                        [MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
                                      }]];
  // Show the alert controller.
  [self.window.rootViewController presentViewController:alertController animated:YES completion:nil];
  return YES; // Return YES if the SDK should await user confirmation, otherwise NO.
})];
Crashes.setUserConfirmationHandler({ (errorReports: [ErrorReport]) in

  // Your code to present your UI to the user, e.g. an UIAlertController.
  let alertController = UIAlertController(title: "Sorry about that!",
                                          message: "Do you want to send an anonymous crash report so we can fix the issue?",
                                          preferredStyle:.alert)

  alertController.addAction(UIAlertAction(title: "Don't send", style: .cancel) {_ in
    Crashes.notify(with: .dontSend)
  })

  alertController.addAction(UIAlertAction(title: "Send", style: .default) {_ in
    Crashes.notify(with: .send)
  })

  alertController.addAction(UIAlertAction(title: "Always send", style: .default) {_ in
    Crashes.notify(with: .always)
  })

  // Show the alert controller.
  self.window?.rootViewController?.present(alertController, animated: true)
  return true // Return true if the SDK should await user confirmation, otherwise return false.
})

Если вы вернеесь YES/true в блоке обработчика выше, приложение должно получить разрешение пользователя и сообщение пакета SDK с результатом с помощью следующего API. Если вы используете оповещение для этого, как мы делаем в приведенном выше примере, вы будете вызывать его из реализации обратного вызова alertView:clickedButtonAtIndex:.

// Depending on the users's choice, call notifyWithUserConfirmation: with the right value.
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationDontSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationSend];
[MSACCrashes notifyWithUserConfirmation:MSACUserConfirmationAlways];
// Depending on the user's choice, call notify(with:) with the right value.
Crashes.notify(with: .dontSend)
Crashes.notify(with: .send)
Crashes.notify(with: .always)

Получите информацию о статусе отправки для журнала сбоев

Иногда необходимо знать состояние сбоя приложения. Распространенный вариант использования заключается в том, что может потребоваться показать пользовательский интерфейс, который сообщает пользователям, что ваше приложение отправляет отчет о сбоях или, если ваше приложение завершает работу быстро после запуска, необходимо настроить поведение приложения, чтобы убедиться, что журналы сбоев можно отправить. Протокол CrashesDelegateопределяет три разных обратных вызова, которые можно использовать в приложении, чтобы получать уведомления о том, что происходит:

Функция обратного вызова будет вызвана перед тем, как SDK отправит журнал сбоя.

- (void)crashes:(MSACCrashes *)crashes willSendErrorReport:(MSACErrorReport *)errorReport {
  // Your code, e.g. to present a custom UI.
}
func crashes(_ crashes: Crashes, willSend errorReport: ErrorReport) {
  // Your code, e.g. to present a custom UI.
}

Если у нас возникли проблемы с сетью или сбой в конечной точке, и вы перезапустите приложение, willSendErrorReport активируется снова после перезапуска процесса.

Следующий обратный вызов будет вызван после успешного отправки журнала сбоя пакета SDK

- (void)crashes:(MSACCrashes *)crashes didSucceedSendingErrorReport:(MSACErrorReport *)errorReport {
  // Your code, e.g. to hide the custom UI.
}
func crashes(_ crashes: Crashes, didSucceedSending errorReport: ErrorReport) {
  // Your code goes here.
}

Следующий коллбэк будет вызван, если SDK не удалось отправить отчет о сбое.

- (void)crashes:(MSACCrashes *)crashes didFailSendingErrorReport:(MSACErrorReport *)errorReport withError:(NSError *)error {
  // Your code goes here.
}
func crashes(_ crashes: Crashes, didFailSending errorReport: ErrorReport, withError error: Error) {
  // Your code goes here.
}

Получение didFailSendingErrorReport означает, что произошла невосстановимая ошибка, например код 4xx . Например, 401 означает, что appSecret это неправильно.

Этот обратный вызов не активируется, если это проблема с сетью. В этом случае пакет SDK продолжает повторную попытку (а также приостанавливает повторные попытки при отключении сетевого подключения).

Добавление вложений в отчет о сбое

Двоичные и текстовые вложения можно добавить в отчет о сбое. Пакет SDK отправит их вместе с сбоем, чтобы их можно было увидеть на портале Центра приложений. Следующий обратный вызов будет вызван непосредственно перед отправкой сохранённого отчёта о сбое из предыдущих запусков приложения. Он не будет вызываться, когда произойдет сбой. Вот пример того, как прикрепить текст и изображение к отчету о сбое:

- (NSArray<MSACErrorAttachmentLog *> *)attachmentsWithCrashes:(MSACCrashes *)crashes
                                             forErrorReport:(MSACErrorReport *)errorReport {
  MSACErrorAttachmentLog *attachment1 = [MSACErrorAttachmentLog attachmentWithText:@"Hello world!" filename:@"hello.txt"];
  MSACErrorAttachmentLog *attachment2 = [MSACErrorAttachmentLog attachmentWithBinary:[@"Fake image" dataUsingEncoding:NSUTF8StringEncoding] filename:@"fake_image.jpeg" contentType:@"image/jpeg"];
  return @[ attachment1, attachment2 ];
}
func attachments(with crashes: Crashes, for errorReport: ErrorReport) -> [ErrorAttachmentLog]? {
  let attachment1 = ErrorAttachmentLog.attachment(withText: "Hello world!", filename: "hello.txt")
  let attachment2 = ErrorAttachmentLog.attachment(withBinary: "Fake image".data(using: String.Encoding.utf8), filename: nil, contentType: "image/jpeg")
  return [attachment1!, attachment2!]
}

Замечание

Ограничение размера в настоящее время составляет 7 МБ. Попытка отправить большее вложение приведет к ошибке.

Включение или отключение сбоев Центра приложений во время выполнения

Вы можете включать и отключать App Center Crashes в процессе работы. Если отключить его, пакет SDK не будет выполнять отчеты о сбоях для приложения.

[MSACCrashes setEnabled:NO];
Crashes.enabled = false

Чтобы снова включить аварийное завершение работы Центра приложений, используйте тот же API, но передайте YES/true его в качестве параметра.

[MSACCrashes setEnabled:YES];
Crashes.enabled = true

Состояние сохраняется в хранилище устройства во время запуска приложения.

Замечание

Этот метод должен использоваться только после того, как Crashes был запущен.

Проверка включения аварийного сбоя Центра приложений

Кроме того, можно проверить, включена ли функция отслеживания сбоев в Центре приложений.

BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled

Замечание

Этот метод должен использоваться только после Crashes запуска, он всегда будет возвращать false до запуска.

Отключение обработки исключений Mach

По умолчанию в Центре приложений Crashes используется обработчик исключений Mach для перехвата фатальных сигналов, таких как переполнение стека, через сервер исключений Mach.

Метод disableMachExceptionHandler-предоставляет возможность отключить перехват смертельных сигналов через сервер исключений Mach. Если вы хотите отключить обработчик исключений Mach, необходимо вызвать этот метод ПЕРЕД запуском пакета SDK. Типичный код установки будет выглядеть следующим образом:

[MSACCrashes disableMachExceptionHandler];
[MSACAppCenter start:@"{Your App Secret}" withServices:@[[MSACAnalytics class], [MSACCrashes class]]];
Crashes.disableMachExceptionHandler()
AppCenter.start(withAppSecret: "{Your App Secret}", services: [Analytics.self, Crashes.self])