O Google tem o compromisso de promover a igualdade racial para as comunidades negras. Saiba como.

Personalizar relatórios de erros do Firebase Crashlytics

Este guia descreve como personalizar seus relatórios de erros usando o SDK do Firebase Crashlytics. Por padrão, o Crashlytics coleta automaticamente relatórios de erros para todos os usuários do seu app. Se quiser, desative os relatórios de falhas automáticos e ative os relatórios de permissão para os usuários. O Crashlytics fornece quatro mecanismos de geração de registros prontos para uso: chaves personalizadas, registros personalizados, identificadores de usuários e exceções capturadas.

Adicionar chaves personalizadas

As chaves personalizadas ajudam você a saber o estado específico do seu app que está gerando uma falha. Você tem a opção de associar pares de chave/valor arbitrários aos seus relatórios de erros e vê-los no Console do Firebase.

Use o método setCustomValue para definir pares de chave-valor. Exemplo:

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

Ao definir números inteiros, booleanos ou flutuantes, defina o valor como @(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"];

Para modificar o valor de uma chave atual, chame a chave e defina-a com um valor diferente. Exemplo:

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"];

Adicionar mensagens de registro personalizadas

Para dar mais contexto aos eventos que geram uma falha, adicione registros personalizados do Crashlytics ao seu app. O Crashlytics associa os registros aos dados de falhas e os exibe na página do Crashlytics do Console do Firebase, na guia Registros.

Swift

Use log() ou log(format:, arguments:) para ajudar a identificar problemas. Se você quiser receber uma saída de registro útil com mensagens, o objeto que você passar para log() precisará estar em conformidade com a propriedade CustomStringConvertible. log() retorna a propriedade de descrição definida para o objeto. Exemplo:

Crashlytics.crashlytics().log("Higgs-Boson detected! Bailing out…, \(attributesDict)")

.log(format:, arguments:) formata valores retornados da chamada getVaList(). Exemplo:

Crashlytics.crashlytics().log(format: "%@, %@", arguments: getVaList(["Higgs-Boson detected! Bailing out…", attributesDict]))

Para mais detalhes sobre como usar log() ou log(format:, arguments:), consulte a documentação de referência de funções do Crashlytics.

Objective-C

Use log ou logWithFormat para ajudar a identificar problemas. Se você quiser receber uma saída de registro útil com mensagens, o objeto que você passar para qualquer método precisará modificar a propriedade da instância description. Exemplo:

[[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];

Para mais detalhes sobre como usar log e logWithFormat, consulte a documentação de referência de funções do Crashlytics.

Definir identificadores de usuários

Para diagnosticar um problema, muitas vezes é útil saber quais usuários observaram uma determinada falha. O Crashlytics inclui uma maneira de identificar anonimamente os usuários nos relatórios de erros.

Para adicionar IDs de usuários aos seus relatórios, atribua a cada usuário um identificador exclusivo na forma de um número de ID, token ou valor de hash:

Swift
Crashlytics.crashlytics().setUserID("123456789")
Objective-C
[[FIRCrashlytics crashlytics] setUserID:@"123456789"];

Se você precisar apagar um identificador de usuário depois de configurá-lo, redefina o valor deixando uma string em branco. Limpar um identificador de usuário não remove os registros atuais do Crashlytics. Se você precisar excluir registros associados a um ID de usuário, entre em contato com o suporte do Firebase.

Reportar exceções não fatais

Além de reportar automaticamente as falhas do seu app, o Crashlytics permite registrar exceções não fatais e enviá-las para você na próxima vez que o app for iniciado.

Para registrar exceções não fatais, grave objetos NSError com o método recordError. recordError captura a pilha de chamadas da linha de execução ao chamar [NSThread callStackReturnAddresses].

Swift

Crashlytics.crashlytics().record(error: error)

Objective-C

[[FIRCrashlytics crashlytics] recordError:error];

Ao usar o método recordError, é importante entender a estrutura NSError e como o Crashlytics usa os dados para agrupar falhas. O uso incorreto do método recordError pode causar um comportamento imprevisível e fazer com que o Crashlytics limite os relatórios de erros registrados para seu app.

Um objeto NSError tem três argumentos:

  • domain: String
  • code: Int
  • userInfo: [AnyHashable : Any]? = nil

Ao contrário das falhas fatais, que são agrupadas por meio da análise de rastreamento de pilha, os erros registrados são agrupados por domain e code. Esta é uma distinção importante entre falhas fatais e erros registrados. Exemplo:

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];

Quando você registra o erro acima, ele cria um novo problema agrupado por NSSomeErrorDomain e -1001. Outros erros registrados que usam os mesmos valores de domínio e código são agrupados no mesmo problema. Os dados contidos no objeto userInfo são convertidos em pares de chave-valor e exibidos na seção de chaves/registros em um problema individual.

Aviso: evite usar valores exclusivos, como ID do usuário, ID do produto e carimbos de data/hora nos campos de domínio e código. O uso de valores exclusivos nesses campos causa uma alta cardinalidade de problemas e pode fazer com que o Crashlytics precise limitar o relatório de erros registrados no seu app. Valores únicos devem ser adicionados ao objeto de dicionário userInfo.

Registros e chaves personalizadas

Assim como os relatórios de erros, é possível incorporar registros e chaves personalizadas para dar mais contexto ao NSError. No entanto, há uma diferença entre registros anexados a falhas e erros registrados. Quando ocorre uma falha e o app é reiniciado, os registros do Crashlytics recuperados do disco são os que foram gravados até o momento da falha. Quando você registra um NSError, o app não é encerrado imediatamente. Como o Crashlytics só envia o relatório de erros registrado na próxima inicialização do app e precisa limitar a quantidade de espaço alocado para os registros no disco, é possível registrar o suficiente depois que um NSError é gravado para que todos os registros relevantes sejam substituídos no momento em que o Crashlytics enviar o relatório do dispositivo. Lembre-se desse equilíbrio ao registrar NSErrors e usar registros e chaves personalizadas no seu app.

Considerações sobre desempenho

Lembre-se de que registrar um NSError pode ser bastante caro. No momento em que você faz a chamada, o Crashlytics captura a pilha de chamadas da linha de execução atual usando um processo chamado desenrolamento de pilha. Esse processo pode consumir muita CPU e E/S, principalmente em arquiteturas compatíveis com desenrolamento DWARF (arm64 e x86). Quando o desenrolamento estiver finalizado, as informações serão gravadas em disco de maneira síncrona. Isso evita a perda de dados se a próxima linha falhar.

Embora seja seguro chamar essa API em uma linha de execução em segundo plano, lembre-se de que o envio dessa chamada para outra fila perde o contexto do rastreamento de pilha atual.

E as NSExceptions?

O Crashlytics não oferece um recurso para registrar e gravar instâncias NSException diretamente. De modo geral, as APIs Cocoa e Cocoa Touch não são seguras contra exceções. Isso significa que o uso de @catch pode ter efeitos indesejados muito graves no seu processo, mesmo quando usado com muito cuidado. Nunca use instruções @catch no seu código. Consulte a documentação da Apple (em inglês) sobre o assunto.

Personalizar stack traces

Se o app for executado em um ambiente não nativo, como C ++ ou Unity, será possível usar a API Exception Model para reportar metadados de falha no formato de exceção nativa do app. As exceções reportadas são consideradas não fatais.

Swift

var  ex = ExceptionModel.init(name:"FooException", reason:"There was a foo.")
ex.stackTrace = [
  StackFrame.init(symbol:"makeError" fileName:"handler.js" lineNumber:495),
  StackFrame.init(symbol:"then" fileName:"routes.js" lineNumber:102),
  StackFrame.init(symbol:"main" fileName:"app.js" lineNumber:12),
]

crashlytics.record(exceptionModel:ex)

Objective-C

FIRExceptionModel *model =
    [FIRExceptionModel exceptionModelWithName:@"FooException" reason:@"There was a foo."];
model.stackTrace = @[
  [FIRStackFrame stackFrameWithSymbol:@"makeError" fileName:@"handler.js" lineNumber:495],
  [FIRStackFrame stackFrameWithSymbol:@"then" fileName:@"routes.js" lineNumber:102],
  [FIRStackFrame stackFrameWithSymbol:@"main" fileName:@"app.js" lineNumber:12],
];

Ative a permissão para geração de relatórios

Por padrão, o Crashlytics coleta automaticamente relatórios de erros para todos os usuários do seu app. Para permitir que os usuários tenham mais controle sobre os dados que enviam, ative a geração de relatórios para seus usuários com a desativação da coleta automática e a inicialização do Crashlytics apenas para usuários selecionados:

  1. Para desativar a coleção automática, adicione uma nova chave ao arquivo Info.plist:

    • Chave: FirebaseCrashlyticsCollectionEnabled
    • Valor: false
  2. Para ativar a coleta para usuários selecionados, chame a modificação da coleta de dados do Crashlytics no ambiente de execução. O valor de modificação continua entre os lançamentos do seu app. Assim, o Crashlytics possa coletar relatórios automaticamente. Para desativar o relatório automático de falhas, transmita false como o valor de modificação. Quando definido como false, o novo valor não se aplica até a próxima execução do app.

    Swift
    Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true)
    Objective-C
    [[FIRCrashlytics crashlytics] setCrashlyticsCollectionEnabled:YES];

Gerencie dados do Crash Insights

Com o Crash Insights, você soluciona problemas quando compara rastreamentos anônimos de pilhas com os de outros aplicativos do Firebase. Você será informado se o problema fizer parte de uma tendência maior. Para muitos problemas, o Crash Insights também oferece recursos para ajudá-lo a depurar a falha.

Ele usa dados de falhas agregados para identificar tendências de estabilidade comuns. Caso prefira não compartilhar os dados do app, é possível desativar o Crash Insights no menu com o mesmo nome na parte superior da lista de problemas do Crashlytics no Console do Firebase.