Personalizar relatórios de erros do Firebase Crashlytics

ios
android
unity [beta]

Para o Firebase Crashlytics funcionar, você praticamente não precisa configurá-lo. Assim que você adiciona o SDK, o Crashlytics começa a funcionar enviando relatórios de falhas para o Console do Firebase.

Para fornecer mais informações sobre relatórios de erros, o Firebase Crashlytics oferece quatro mecanismos de registro: chaves personalizadas, registros personalizados, identificadores de usuários e exceções capturadas.

Adicionar chaves personalizadas

As chaves personalizadas ajudam você a chegar ao estado específico do seu aplicativo que está gerando uma falha. Você pode associar pares chave/valor arbitrários aos seus relatórios de erros e vê-los no Console do Firebase.

ios

Comece com [CrashlyticsKit setObjectValue:forKey:] ou um dos métodos relacionados:

- (void)setObjectValue:(id)value forKey:(NSString *)key;

// calls -description on value, perfect for NSStrings!
- (void)setIntValue:(int)value forKey:(NSString *)key;

- (void)setBoolValue:(BOOL)value forKey:(NSString *)key;

- (void)setFloatValue:(float)value forKey:(NSString *)key;

Às vezes, você precisa alterar o valor da chave existente. Chame a mesma chave, mas substitua o valor, por exemplo:

Objective-C
[CrashlyticsKit setIntValue:3 forKey:@"current_level"];
[CrashlyticsKit setObjectValue:@"logged_in" forKey:@"last_UI_action"];
Swift
Crashlytics.sharedInstance().setIntValue(42, forKey: "MeaningOfLife")
Crashlytics.sharedInstance().setObjectValue("Test value", forKey: "last_UI_action")
Android

Há cinco métodos para definir as chaves. Cada um lida com um tipo de dados diferente:

Java
Android

Crashlytics.setString(key, "foo" /* string value */);

Crashlytics.setBool(key, true /* boolean value */);

Crashlytics.setDouble(key, 1.0 /* double value */);

Crashlytics.setFloat(key, 1.0f /* float value */);

Crashlytics.setInt(key, 1 /* int value */);

Kotlin
Android

Crashlytics.setString(key, "foo" /* string value */)

Crashlytics.setBool(key, true /* boolean value */)

Crashlytics.setDouble(key, 1.0 /* double value */)

Crashlytics.setFloat(key, 1.0f /* float value */)

Crashlytics.setInt(key, 1 /* int value */)

Reajustar uma chave atualiza o valor dela. Por exemplo:

Java
Android

Crashlytics.setInt("current_level", 3);
Crashlytics.setString("last_UI_action", "logged_in");

Kotlin
Android

Crashlytics.setInt("current_level", 3)
Crashlytics.setString("last_UI_action", "logged_in")
unity [beta]

Quando chamado várias vezes, as chaves existentes são atualizadas com valores novos, e somente o valor mais atual é capturado quando uma falha é registrada.

Crashlytics.SetCustomKey(string key, string value);

Adicionar mensagens de registro personalizadas

Para que você tenha mais contexto sobre os eventos que causam falha, é possível adicionar registros personalizados do Crashlytics ao seu aplicativo. O Crashlytics associa os registros aos seus dados de falha e os torna visíveis no Console do Firebase.

ios
Objective-C

No Objective-C, use CLS_LOG para ajudar a identificar problemas. Ele inclui automaticamente informações sobre a classe, o método e o número da linha do Objective-C associados ao registro.

O comportamento do CLS_LOG muda caso ele esteja registrando uma versão de depuração ou de lançamento:

  • Versões de depuração: o CLS_LOG é transmitido para o NSLog. Assim, é possível ver o resultado em Xcode e no dispositivo ou no simulador.
  • Versões de lançamento: para melhorar o desempenho, o CLS_LOG silencia todos os outros resultados e não é transmitido para o NSLog.

Use o CLS_LOG(format, ...) para registrar com o CLS_LOG. Por exemplo:

CLS_LOG(@"Higgs-Boson detected! Bailing out... %@", attributesDict);

Navegue no arquivo de cabeçalho Crashlytics/Crashlytics.h para ver mais detalhes sobre como usar o CLS_LOG.

Swift

Em Swift, use CLSLogv ou CLSNSLogv para ajudar a identificar problemas.

Ao gerar registros com CLSLogv e CLSNSLogv, considere os seguintes pontos:

  • Seu argumento de formato precisa ser uma string constante de tempo de compilação. Isso é executado pelo compilador no Objective-C, mas essa proteção está perdida na transição para o Swift.
  • Armazene os valores do registro em uma matriz e chame o getVaList nessa matriz para recuperá-los.

Por exemplo:

func write(string: String) {
    CLSLogv("%@", getVaList([string]))
}
A interpolação de string Swift não resultará em uma string constante de tempo de compilação. Assim como com printf e NSLog, usar uma string não constante com CLSLog pode resultar em uma falha.

Avançado

Para ter mais controle, você pode usar diretamente CLSLog(format, ...) e CLSNSLog(format, ...). O último é passado até o NSLog de modo que você veja a saída no Xcode ou no dispositivo ou simulador. CLSLog(format, ...) e CLSNSLog(format, ...) são thread-safe. CLSLog destina-se a registrar informações importantes para solucionar falhas. Não deve ser usado para rastrear eventos no aplicativo.

Android

No Android, use o Crashlytics.log para ajudar a identificar problemas.

O Crashlytics.log pode gravar registros em um relatório de erros e com o Log.println() ou apenas no próximo relatório de erros:

  • Relatório de erros e Log.println:

    Java
    Android

    Crashlytics.log(Log.DEBUG, "tag", "message");

    Kotlin
    Android

    Crashlytics.log(Log.DEBUG, "tag", "message")
  • Apenas relatório de erros:

    Java
    Android

    Crashlytics.log("message");

    Kotlin
    Android

    Crashlytics.log("message")
unity [beta]

As mensagens registradas são associadas aos dados da falha e são visíveis no painel do Firebase Crashlytics quando você visualiza uma falha específica.

Crashlytics.Log(string message);

Definir identificadores de usuários

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

ios

Para adicionar códigos do usuário aos seus relatórios, atribua a cada usuário um identificador exclusivo na forma de um número de identificação, token ou hash:

Objective-C
[CrashlyticsKit setUserIdentifier:@"123456789"];
Swift
Crashlytics.sharedInstance().setUserIdentifier("123456789")

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

Android

Para adicionar códigos do usuário aos seus relatórios, atribua a cada usuário um identificador exclusivo na forma de um número de identificação, token ou hash:

Java
Android

Crashlytics.setUserIdentifier("user123456789");

Kotlin
Android

Crashlytics.setUserIdentifier("user123456789")

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

unity [beta]

É possível usar um código, um token ou um valor com hash para identificar exclusivamente o usuário final do seu app sem divulgar ou transmitir qualquer informação pessoal. Também é possível limpar o valor ao defini-lo como uma string em branco. Esse valor é exibido no painel do Firebase Crashlytics ao visualizar uma falha específica.

Crashlytics.SetUserId(string identifier);

Registrar exceções não fatais

Além de registrar automaticamente falhas do seu aplicativo, o Crashlytics permite que você registre exceções não fatais.

ios

No iOS, isso é possível por meio do registro de objetos NSError, que o Crashlytics registra e agrupa como falhas:

Objective-C
[CrashlyticsKit recordError:error];
Swift
Crashlytics.sharedInstance().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 pode exigir que o Crashlytics limite relatórios de erros registrados para seu aplicativo.

Um objeto NSError tem três argumentos: domain: String, code: Int e userInfo: [AnyHashable : Any]? = nil

Ao contrário de falhas fatais, que são agrupadas através de análise de rastreamento de pilha, os erros registrados são agrupados pelo domain e o code do NSError. Esta é uma distinção importante entre falhas fatais e erros registrados. Por exemplo, registrando um erro como:

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";
    UserID: @"Jane Smith"
};

NSError *error = [NSError domain:NSSomeErrorDomain
                          code:-1001
                          userInfo:userInfo];

Cria um novo problema que é agrupado por NSSomeErrorDomain e -1001. Demais erros registrados que usam o mesmo domínio e valores de código serão agrupados nesse problema.

Evite usar valores exclusivos como códigos do usuário, 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 os relatórios de erros registrados no seu aplicativo. Os valores exclusivos devem, em vez disso, ser adicionados ao objeto userInfo do dicionário.

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.

O Crashlytics apenas armazena as oito exceções mais recentes em uma determinada sessão do aplicativo. Se o aplicativo lançar mais de oito exceções em uma sessão, as antigas serão perdidas.

Registros e chaves personalizadas

Assim como os relatórios de erros, você pode incorporar registros e chaves personalizadas para adicionar contexto ao NSError. No entanto, há uma diferença em quais registros são anexados a falhas ou em erros registrados. Quando ocorre uma falha e o aplicativo é relançado, os registros do Crashlytics recuperados do disco são os que foram escritos até o momento da falha. Quando você registra um NSError, o aplicativo não é encerrado imediatamente. Como o Crashlytics envia apenas o relatório de erro registrado na próxima inicialização do aplicativo e precisa limitar a quantidade de espaço alocada para 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. Tenha em mente esse equilíbrio ao registrar NSErrors e usar o CLSLog e chaves personalizadas em seu aplicativo.

Considerações sobre desempenho

Atente-se ao fato 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 thread atual usando um processo chamado desenrolar de pilha. Esse processo pode ser intenso para CPU e E/S, particularmente em arquiteturas compatíveis com desenrolamento DWARF (arm64 e x86). Quando o desenrolamento estiver finalizado, as informações são gravadas em disco de maneira síncrona. Isso evita a perda de dados se a próxima linha falhar.

É seguro chamar essa API em uma thread de segundo plano, mas lembre-se de que despachar essa chamada para outra fila fará com que o contexto do rastreamento da pilha atual seja perdido.

E as NSExceptions?

O Crashlytics não oferece uma instalação para registrar ou gravar instâncias de 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 causar grandes efeitos colaterais no seu processo, mesmo quando usado com muito cuidado. Você nunca deve usar as instruções @catch no seu código. Consulte a documentação da Apple (em inglês) sobre o assunto.

Android

No Android, isso significa que você pode registrar as exceções captadas nos blocos de captura do seu app:

Java
Android

try {
    methodThatThrows();
} catch (Exception e) {
    Crashlytics.logException(e);
    // handle your exception here
}

Kotlin
Android

try {
    methodThatThrows()
} catch (e: Exception) {
    Crashlytics.logException(e)
    // handle your exception here
}

Todas as exceções registradas aparecem como problemas não fatais no Console do Firebase. O resumo do problema contém todas as informações de estado que você normalmente recebe com as falhas, além de desdobramentos por versão do Android e dispositivo de hardware.

O Crashlytics processa exceções em uma thread em segundo plano dedicado, de modo que o impacto no desempenho em seu aplicativo é mínimo. Para reduzir o tráfego de rede dos seus usuários, o Crashlytics lança exceções registradas e as envia na próxima vez que o aplicativo for iniciado.

O Crashlytics apenas armazena as oito exceções mais recentes em uma determinada sessão do aplicativo. Se o aplicativo lançar mais de oito exceções em uma sessão, as antigas serão perdidas.
unity [beta]

Registre exceções personalizadas em C# usando os seguintes métodos:

Crashlytics.LogException(Exception ex);

É possível incluir exceções personalizadas nos blocos try/catch do seu app:

try {
    myMethodThatThrows();
} catch (Exception e) {
   Crashlytics.LogException(e);
   // handle your exception here!
}

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

Por padrão, o Firebase Crashlytics coleta automaticamente relatórios de falhas de todos os usuários do seu aplicativo. Para dar aos usuários mais controle sobre os dados que enviam, você pode ativar a permissão para geração de relatórios.

Para tal, você deve desativar a coleta automática e inicializar o Crashlytics somente para os usuários que tiverem permitido a geração de relatórios.

ios
  1. Desative a coleta automática com uma nova chave no arquivo Info.plist:
    • Chave: firebase_crashlytics_collection_enabled
    • Valor: false
  2. Ative a coleta para usuários selecionados inicializando o Crashlytics no tempo de execução:
    Objective-C
    [Fabric with:@[[Crashlytics class]]];
    Swift
    Fabric.with([Crashlytics.self])
Android
  1. Desative a coleta automática com uma tag meta-data no seu arquivo AndroidManifest.xml:
    <meta-data
        android:name="firebase_crashlytics_collection_enabled"
        android:value="false" />
    
  2. Ative a coleta para usuários selecionados inicializando o Crashlytics em uma das atividades do seu app:

    Java
    Android

    Fabric.with(this, new Crashlytics());

    Kotlin
    Android

    Fabric.with(this, Crashlytics())
Observação: não é possível interromper a geração de relatórios do Crashlytics depois iniciar esse processo em uma sessão do app. Para desativar a geração de relatório depois de inicializar o Crashlytics, os usuários devem reiniciar o aplicativo.
unity [beta]
Crashlytics.IsCrashlyticsCollectionEnabled = false;

Veja um exemplo de como anexar isso a um elemento da interface do usuário:

public class DataCollectionToggleScript : MonoBehaviour {

  public Toggle DataCollectionToggle;

  void Start () {
    Toggle toggle = DataCollectionToggle.GetComponent<Toggle>();
    toggle.isOn = Crashlytics.IsCrashlyticsCollectionEnabled;
    toggle.onValueChanged.AddListener(delegate {
      ToggleValueChanged(toggle);
    });
  }

  void ToggleValueChanged(Toggle toggle){
    Crashlytics.IsCrashlyticsCollectionEnabled = toggle.isOn;
  }
}

Não consegue encontrar um equivalente no Fabric Crashlytics? Confira nossa página de alterações da API do Unity para saber como o Crashlytics evoluiu do Fabric Crashlytics para o Firebase Crashlytics.

Gerenciar 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 agregadas para identificar tendências de estabilidade comuns. Caso prefira não compartilhar os dados do app, será 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.

Enviar comentários sobre…

Precisa de ajuda? Acesse nossa página de suporte.