Capturando erros com Firebase Crashlytics no Flutter

Ricarth Lima
Ricarth Lima

Compartilhe

Mesa de trabalho onde uma pessoa está mexendo em um tablet.

Opa! Antes de continuar a leitura, é legal saber que esse artigo é a segunda parte de uma série de artigos sobre o Firebase Crashlytics com Flutter. Caso você ainda não tenha lido Como monitorar erros com Flutter e não tenha instalado o Crashlytics no seu projeto Flutter, recomendamos a leitura!

Então, agora que está tudo configurado, como podemos fazer um melhor uso dessa ferramenta? É sobre isso que vamos falar nesse artigo e, para isso, considere o seguinte código de tratamento de exceções que podem ocorrer quando estamos lidando com um servidor na web:

await _webClient.save(transactionCreated, password).catchError((e) {
      _showFailureMessage(context, message: e.message);
    }, test: (e) => e is HttpException).whenComplete(() {
      setState(() {
        _sending = false;
      });
    });

Esse código é da aplicação que você pode desenvolver na Formação Flutter da Alura. Nesse trecho, vemos uma requisição para salvar uma informação no servidor na nuvem. Perceba que essa situação é muito comum nas aplicações atuais, e que, por serem operações que dependem de um sistema externo (um servidor) que passa por um canal não confiável (a internet), elas estão muito suscetíveis a falhas!

Cada catchError() (no exemplo só há um, mas poderíamos encadear vários) lida com uma categoria de exceção diferente, mostrando uma mensagem diferente na tela para a pessoa usando o aplicativo. Podemos ter esse mesmo nível de cuidado e detalhamento com as mensagens que enviaremos para o Firebase Crashlytics, e para isso usaremos o conceito de chaves.

Como usar chaves no Firebase Crashlytics

No Firebase Crashlytics, temos as chaves que funcionam como um dicionário. Como assim? As chaves são termos curtos que vamos procurar e achar com facilidade quando precisamos deles. Cada chave tem um valor, onde esse é um conceito longo e o máximo esclarecedor possível sobre aquela chave.

Quando lidamos com erros no Crashlytics de forma genérica, às vezes pode ficar difícil de identificar o que gerou de fato esse problema. Qual era o contexto por trás daquela exceção? E é para isso que vamos usar esse conceito de chave-valor, onde no valor vamos mandar as informações sobre o ambiente que podem ter gerado aquela exceção.

Para fazer isso tudo, adicionamos (pelo menos) essas duas linhas dentro de cada catchError que tratamos:

FirebaseCrashlytics.instance.setCustomKey('chave', 'valor');
FirebaseCrashlytics.instance.recordError(e, null);

A primeira linha é responsável por criar uma chave, e até por isso dissemos “pelo menos”, já que você pode criar várias dessas linhas. Em cada chave, você pode guardar algo que você considere relevante para uma análise posterior de um erro, como o Status HTTP, o Corpo da Requisição, ou até mesmo toda a exceção convertida para String.

Vale lembrar que você só pode passar tipos primitivos (String, bool, int, float, double etc) nesse valor. Para passar um objeto inteiro, é válido antes serializar ele para um JSON.

Já a segunda linha é responsável por salvar, de fato, o erro no nosso Crashlytics. No nosso exemplo, poderíamos ter algo como:

await _webClient.save(transactionCreated, password).catchError((e) {
      FirebaseCrashlytics.instance.setCustomKey('http_body', response.body);
      FirebaseCrashlytics.instance.setCustomKey('http_statuscode', response.statusCode);
      FirebaseCrashlytics.instance.setCustomKey('exception', e.toString());
      FirebaseCrashlytics.instance.setCustomKey('transactionJSON', transaction.toJson());
      FirebaseCrashlytics.instance.recordError(e, null);
      _showFailureMessage(context, message: e.message);
    }, test: (e) => e is HttpException).whenComplete(() {
      setState(() {
        _sending = false;
      });
    });

Pronto! Agora você já sabe como usar e configurar as chaves dentro do Firebase Crashlytics no Flutter.

Como rastrear qual usuário sofreu a falha

Agora, imagine a seguinte situação: Existe um erro bem específico que acontece apenas com um número proporcionalmente pequeno de pessoas que usam a aplicação. Da forma que estamos registrando agora, não guardamos nenhuma informação sobre quem sofreu esse erro, temos apenas os dados do aparelho e do contexto.

Na imagem, há a aba de “Dado” de um erro capturado com o Crashlytics. Nela há apenas dados sobre o dispositivo e o contexto da falha, mas nada sobre quem está usando.

O problema é que às vezes essas informações não são suficientes! Vão haver vezes que os dados que você coletou sobre os aparelhos e o contexto não demonstram nenhum padrão. Um exemplo comum são problemas relacionados às ferramentas externas, como entradas inválidas em um banco de dados, falhas na autenticação em APIs de terceiros, etc.

Felizmente, o Crashlytics também pode nos ajudar com isso, e é realmente muito simples! Se você deseja associar todos os erros que aconteçam em certo dispositivo a uma string que represente um usuário, basta usar a seguinte linha, substituindo o “alura123” por um código identificador de quem está usando o aplicativo:

FirebaseCrashlytics.instance.setUserIdentifier("alura123");

Uma dica legal é não sair usando essa linha indiscriminadamente durante o código, para que você não perca a homogeneidade dos dados. O ideal é chamá-la logo após uma autenticação, onde você consiga passar um identificador único como string.

Na imagem, há a aba de “Dado” de um erro capturado com o Crashlytics. Nela está apontado, com o cursor do mouse, que agora há uma categoria “Usuário” que dispõe o código identificador que passamos.

Agora o Crashlytics passa a mostrar essa informação na aba “Dados” e com ela você pode, por exemplo, fazer os cruzamentos que forem necessários com ferramentas externas para identificar padrões que apontem o que esses usuários têm em comum e que pode estar gerando o problema!

Para saber mais

Nesta série de artigos, aprendemos que há erros que estão fora do alcance da pessoa desenvolvedora e, mesmo assim, precisamos aprender a lidar com eles.

Aprendemos, também, que para isso existe uma ferramenta da Google chamada Crashlytics, disponível na plataforma Firebase. E, visto que aprendemos a configurar o ambiente no artigo Como monitorar erros com Flutter, aprendemos aqui como capturar erros que acontecem e como tornar essa informação mais precisa, identificando quem estava usando a aplicação quando a falha aconteceu.

Se você tem interesse em ferramentas Firebase sendo usadas em apps Flutter, uma boa dica é o site do Firebase. Esse site é incrível para quem quer usar as ferramentas do Firebase no Flutter! Nele, temos um “hub” das dependências que devemos adicionar no nosso projeto para podermos conectar sem dificuldades nossa aplicação Flutter às ferramentas do Firebase.

Espero que tenha gostado da leitura e tenha sentido aquela ansiedade boa de colocar a mão na massa para implementar uma nova ferramenta!

Se quiser aprender mais sobre o Firebase Crashlytics com projetos Flutter, assista o curso "Flutter: Firebase Crashlytics, gere relatórios de erro em tempo real" da Formação Flutter da Alura.

Bons estudos e nós nos vemos novamente no maravilhoso mundo do Flutter!

Ricarth Lima
Ricarth Lima

Acredito que educação e computação podem mudar o mundo para melhor, em especial, juntas. Por isso além de fazer parte do Grupo Alura, sou professor, desenvolvedor de jogos educativos e criador de conteúdo! Amo Flutter e Unity!

Veja outros artigos sobre Mobile