Falhas do App Center (iOS)
Importante
O Visual Studio App Center está programado para ser desativado em 31 de março de 2025. Embora você possa continuar a usar o Visual Studio App Center até que ele seja totalmente desativado, há várias alternativas recomendadas para as quais você pode considerar a migração.
As falhas do App Center gerarão automaticamente um log de falhas sempre que o aplicativo falhar. O log é gravado pela primeira vez no armazenamento do dispositivo e, quando o usuário iniciar o aplicativo novamente, o relatório de falha será enviado para o App Center. A coleta de falhas funciona para aplicativos beta e dinâmicos, ou seja, aqueles enviados ao App Store. Os logs de falha contêm informações valiosas para ajudar a corrigir a falha.
Siga a seção Introdução se você ainda não configurou o SDK em seu aplicativo.
Além disso, os logs de falha no iOS exigem Simbolização, marcar a documentação diagnóstico do App Center que explica como fornecer símbolos para seu aplicativo.
Observação
O SDK não encaminhará nenhum log de falhas se você estiver conectado ao depurador. Verifique se o depurador não está anexado quando você interromper o aplicativo.
Observação
Para receber rastreamentos de pilha devidamente simbólicos, verifique se o bitcode está desabilitado. Você pode saber mais sobre o bitcode na documentação de Simbolização do iOS do App Center.
Observação
4.0.0
Na versão do App Center, foram introduzidas alterações interruptivas. Siga a seção Migrar para o SDK do App Center 4.0.0 e superior para migrar o App Center de versões anteriores.
O App Center dá suporte a relatórios de falha em extensões do iOS. O uso é o mesmo que no aplicativo de contêiner.
As falhas do App Center fornecem uma API para gerar uma falha de teste para facilitar o teste do SDK. Essa API só pode ser usada em aplicativos de teste/beta e não fará nada em aplicativos de produção.
[MSACCrashes generateTestCrash];
Crashes.generateTestCrash()
O App Center Crashes tem duas APIs que fornecem mais informações caso seu aplicativo tenha falhado.
A qualquer momento após iniciar o SDK, você poderá marcar se o aplicativo recebeu um aviso de memória na sessão anterior:
[MSACCrashes hasReceivedMemoryWarningInLastSession];
Crashes.hasReceivedMemoryWarningInLastSession
Observação
Esse método só deve ser usado depois Crashes
de iniciado, ele sempre retornará NO
ou false
antes de começar.
Observação
Em alguns casos, um dispositivo com memória baixa não pode enviar eventos.
A qualquer momento após iniciar o SDK, você poderá marcar se o aplicativo falhou na inicialização anterior:
[MSACCrashes hasCrashedInLastSession];
Crashes.hasCrashedInLastSession
Isso é útil caso você deseje ajustar o comportamento ou a interface do usuário do aplicativo após uma falha.
Observação
Esse método só deve ser usado depois MSACCrashes
de iniciado, ele sempre retornará NO
ou false
antes de começar.
Se o aplicativo falhou anteriormente, você poderá obter detalhes sobre a última falha.
MSACErrorReport *crashReport = [MSACCrashes lastSessionCrashReport];
var crashReport = Crashes.lastSessionCrashReport
Observação
Esse método só deve ser usado depois Crashes
de iniciado, ele sempre retornará nil
antes de começar.
Há vários casos de uso para essa API, o mais comum são as pessoas que chamam essa API e implementam seu CrashesDelegate personalizado.
O App Center Crashes fornece retornos de chamada para que os desenvolvedores executem ações adicionais antes e ao enviar logs de falha para o App Center.
Para adicionar seu comportamento personalizado, você precisa adotar o CrashesDelegate
-protocol, todos os seus métodos são opcionais.
[MSACCrashes setDelegate:self];
Crashes.delegate = self
Observação
Você deve definir o delegado antes de chamar AppCenter.start
, já que o App Center inicia o processamento de falhas imediatamente após o início.
Implemente o crashes:shouldProcessErrorReport:
método -na classe que adota o CrashesDelegate
-protocol se você quiser decidir se uma falha específica precisa ser processada ou não. Por exemplo, pode haver uma falha no nível do sistema que você gostaria de ignorar e que não deseja enviar para o App Center.
- (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.
}
O App Center também permite que você rastreie erros usando exceções tratadas por meio do trackError
método . Opcionalmente, um aplicativo pode anexar propriedades ou/e anexos a um relatório de erro manipulado para fornecer mais contexto.
@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)
}
Para acompanhar exceções, você pode usar o trackException
método :
@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)
}
Se a privacidade do usuário for importante para você, talvez você queira obter a confirmação do usuário antes de enviar um relatório de falha para o App Center. O SDK expõe um retorno de chamada que informa que o App Center falha para aguardar a confirmação do usuário antes de enviar relatórios de falha.
Se você optar por fazer isso, será responsável por obter a confirmação do usuário, por exemplo, por meio de um prompt de caixa de diálogo com uma das seguintes opções: Sempre enviar, Enviar e Não enviar. Com base na entrada, você informará às Falhas do App Center o que fazer e a falha será tratada de acordo.
Observação
O SDK não exibe uma caixa de diálogo para isso, o aplicativo deve fornecer sua própria interface do usuário para solicitar o consentimento do usuário.
Observação
O aplicativo não deve chamar notifyWithUserConfirmation
explicitamente se não implementar uma caixa de diálogo de confirmação do usuário; o módulo Falhas tratará o envio de logs para você implicitamente.
O seguinte método mostra como configurar um manipulador de confirmação do usuário:
[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.
})
Caso você retorne YES
/true
no bloco do manipulador acima, seu aplicativo deverá obter permissão de usuário e enviar uma mensagem ao SDK com o resultado usando a API a seguir. Se você estiver usando um alerta para isso, como fazemos no exemplo acima, você o chamará de dentro de sua implementação do alertView:clickedButtonAtIndex:
-callback.
// 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)
Às vezes, você deseja saber o status da falha do aplicativo. Um caso de uso comum é que talvez você queira mostrar a interface do usuário que informa aos usuários que seu aplicativo está enviando um relatório de falha ou, caso seu aplicativo esteja falhando rapidamente após a inicialização, você deseja ajustar o comportamento do aplicativo para garantir que os logs de falha possam ser enviados. O CrashesDelegate
-protocol define três retornos de chamada diferentes que você pode usar em seu aplicativo para ser notificado sobre o que está acontecendo:
- (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.
}
Caso tenhamos problemas de rede ou uma interrupção no ponto de extremidade e você reinicie o aplicativo, willSendErrorReport
será disparado novamente após a reinicialização do processo.
- (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.
}
- (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
Receber significa que ocorreu um erro não recuperável, como um código 4xx. Por exemplo, 401 significa que o appSecret
está errado.
Esse retorno de chamada não será disparado se for um problema de rede. Nesse caso, o SDK continua tentando novamente (e também pausa novas tentativas enquanto a conexão de rede está inativa).
Você pode adicionar anexos binários e de texto a um relatório de falha. O SDK os enviará junto com a falha para que você possa vê-los no portal do App Center. O retorno de chamada a seguir será invocado logo antes de enviar a falha armazenada da inicialização do aplicativo anterior. Ele não será invocado quando a falha acontecer. Aqui está um exemplo de como anexar texto e uma imagem a uma falha:
- (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!]
}
Observação
Atualmente, o limite de tamanho é de 7 MB. Tentar enviar um anexo maior disparará um erro.
Você pode habilitar e desabilitar falhas do App Center em runtime. Se você desabilitá-lo, o SDK não fará nenhum relatório de falha para o aplicativo.
[MSACCrashes setEnabled:NO];
Crashes.enabled = false
Para habilitar falhas do App Center novamente, use a mesma API, mas passe YES
/true
como um parâmetro.
[MSACCrashes setEnabled:YES];
Crashes.enabled = true
O estado é persistido no armazenamento do dispositivo entre as inicializações do aplicativo.
Observação
Esse método só deve ser usado depois Crashes
de ter sido iniciado.
Você também pode marcar se falhas do App Center estiverem habilitadas ou não:
BOOL enabled = [MSACCrashes isEnabled];
var enabled = Crashes.enabled
Observação
Esse método só deve ser usado depois Crashes
de ter sido iniciado, ele sempre retornará false
antes de iniciar.
Por padrão, o App Center Crashes usa o manipulador de exceção Mach para capturar sinais fatais, por exemplo, estouros de pilha, por meio de um servidor de exceção Mach.
O disableMachExceptionHandler
método -fornece uma opção para desabilitar a captura de sinais fatais por meio de um servidor de exceção Mach. Se você quiser desabilitar o manipulador de exceção Mach, chame esse método ANTES de iniciar o SDK. Seu código de instalação típico teria esta aparência:
[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])