⁉️Utilizando o Sentry

O Sentry é uma plataforma de monitoramento de erros que oferece uma solução completa para rastrear e corrigir problemas em tempo real em aplicativos Flutter.

⁉️ Monitoramento de Erros e Desempenho no Flutter com Sentry

O Sentry é uma plataforma de monitoramento de erros e desempenho que permite rastrear problemas em tempo real e obter insights detalhados sobre a estabilidade e a performance do seu aplicativo Flutter.


✅ Passo 1: Crie uma Conta no Sentry

Acesse https://sentry.io e crie uma conta, caso ainda não tenha.

Configure um novo projeto para o seu app Flutter no painel da plataforma.


✅ Passo 2: Adicione a Dependência

Inclua o sentry_flutter no seu pubspec.yaml:

dependencies:  
	sentry_flutter:  ^5.0.0

Em seguida, execute:

flutter pub get

✅ Passo 3: Inicialização no main()

No main() do seu aplicativo, inicialize o Sentry com a sua DSN (chave fornecida pela plataforma):

import 'package:flutter/material.dart';
import 'package:sentry_flutter/sentry_flutter.dart';

void main() async {
  await SentryFlutter.init(
    (options) {
      options.dsn = 'SUA_CHAVE_DE_API_AQUI';

      // 🔍 Captura de rastros de performance (navegação, async, etc.)
      options.tracesSampleRate = 1.0; // 100% das transações

      // 🧠 Ativa o rastreamento automático de sessões
      options.enableAutoSessionTracking = true;

      // 📌 Inclui automaticamente stacktraces mesmo em logs manuais
      options.attachStacktrace = true;

      // 🧪 Ativa o modo de debug apenas em desenvolvimento
      options.debug = kDebugMode;

      // 🎥 (Opcional) Captura sessões em vídeo quando há erro
      options.experimental.replay.sessionSampleRate = 0.7; // 70% das sessões
      options.experimental.replay.onErrorSampleRate = 1.0; // 100% com erro

      // 🧵 Número máximo de breadcrumbs (ações anteriores ao erro)
      options.maxBreadcrumbs = 100;

      // 🌍 Define o ambiente automaticamente baseado na BASE_URL
      final baseUrl = dotenv.env['BASE_URL'] ?? '';
      if (baseUrl.contains('deve')) {
        options.environment = 'development';
      } else if (baseUrl.contains('stag')) {
        options.environment = 'staging';
      } else if (baseUrl.contains('hmlg')) {
        options.environment = 'homolog';
      } else {
        options.environment = 'production';
      }
    },
    appRunner: () => runApp(MyApp()),
  );
}

💡 Dica: Envolva seu app em runZonedGuarded para capturar exceções não tratadas:

void main() {
  runZonedGuarded(() async {
    // Inicialização do Sentry e app
  }, (error, stack) {
    Sentry.captureException(error, stackTrace: stack);
  });
}

✅ Passo 4: Centralize com um SentryService

Recomenda-se criar uma classe utilitária para facilitar o uso do Sentry em todo o projeto:

class SentryService {
  /// Captura uma exceção manualmente e adiciona contexto personalizado.
  static Future<void> captureException(
    dynamic exception,
    StackTrace? stackTrace, {
    Map<String, dynamic>? extra, // 🔍 Dados adicionais do erro
    String? tag,                 // 🏷️ Tag para agrupar o erro por fluxo (ex: 'checkout', 'login')
    String? level,               // 🔔 Nível de severidade: error, warning, info
  }) async {
    try {
      await Sentry.captureException(
        exception,
        stackTrace: stackTrace,
        withScope: (scope) {
          if (tag != null) {
            scope.setTag('flow', tag); // exemplo: flow: login
          }
          if (extra != null) {
            scope.setContexts('extra_data', extra); // dados como valores de input, status de flags etc.
          }
          if (level != null) {
            scope.level = _getSentryLevel(level); // define o nível de erro
          }
        },
      );
    } catch (e) {
      log('Erro ao capturar exceção no Sentry', error: e);
    }
  }

  /// Converte o nível textual (info, warning, error) para o enum do Sentry.
  static SentryLevel _getSentryLevel(String? level) {
    switch (level?.toLowerCase()) {
      case 'error':
        return SentryLevel.error;
      case 'warning':
        return SentryLevel.warning;
      case 'info':
        return SentryLevel.info;
      default:
        return SentryLevel.error;
    }
  }

  /// Adiciona um breadcrumb (registro de ação do usuário) ao escopo atual.
  static void addBreadcrumb(
    String message, {
    String? category,                 // categoria lógica (ex: "http", "ui", "auth")
    Map<String, dynamic>? data,       // detalhes adicionais (headers, payload, etc.)
  }) {
    Sentry.addBreadcrumb(
      Breadcrumb(
        message: message,             // descrição textual da ação
        category: category ?? 'app',  // categoria da ação
        data: data,                   // map com dados úteis
        level: SentryLevel.info,
      ),
    );
  }

  /// Define o usuário atual, associando erros e eventos a ele.
  static void setUserContext({
    required String email,
    required bool isLogged,     // true se o usuário estiver autenticado
    required bool fetchedUser,  // true se os dados do usuário já foram buscados
    String? clientId,           // ID do cliente
    String? companyId,          // ID da empresa vinculada
  }) {
    Sentry.configureScope((scope) {
      scope.setUser(SentryUser(
        email: email,
        id: clientId,
        data: {
          'isLogged': isLogged,
          'fetchedUser': fetchedUser,
          'companyId': companyId,
        },
      ));
    });
  }
}

Exemplos de Uso

Capturar erro manualmente com contexto:

try {
  // lógica de negócio
} catch (e, st) {
  await SentryService.captureException(
    e,
    st,
    tag: 'checkout',
    extra: {'step': 'confirm_payment'},
    level: 'error',
  );
}

Adicionar uma ação importante como breadcrumb:

SentryService.addBreadcrumb(
  'Usuário pressionou botão de salvar',
  category: 'ui.interaction',
  data: {'form_valid': true},
);

Definir o contexto do usuário:

SentryService.setUserContext(
  email: 'usuario@exemplo.com',
  isLogged: true,
  fetchedUser: true,
  clientId: 'abc123',
  companyId: 'empresa456',
);

✅ Passo 5: Boas Práticas no Uso

  • Utilize SentryService.captureException() sempre que capturar manualmente um erro com try/catch.

  • Registre ações ou eventos importantes com SentryService.addBreadcrumb().

  • Assim que possível, chame SentryService.setUserContext() para associar eventos a usuários específicos.

  • Use Sentry.captureMessage() para registrar ocorrências importantes que não geram exceptions.

  • Inclua informações adicionais no escopo, como versão do app, permissões, device info, etc.

  • Use Sentry.startTransaction() se quiser medir performance manualmente em tarefas críticas.


📊 Monitoramento de Desempenho

O Sentry também permite rastrear a performance do app:

  • Traces automáticos: com tracesSampleRate: 1.0, o Sentry coleta dados de navegação e async tasks.

  • Session Replay: gravações da sessão do usuário em erros críticos.

  • Transações manuais: com startTransaction() para rastrear tarefas específicas.


🎯 Benefícios de uma Integração Completa

  • Rastreabilidade aprimorada: com breadcrumbs e contexto de usuário.

  • Diagnóstico eficiente: stacktrace rico e metadados sobre ambiente, versão, etc.

  • Correções mais rápidas: alertas proativos e session replay ajudam a reproduzir bugs.

  • Melhor experiência para o usuário: menos falhas e melhor performance.


✅ Conclusão

Ao seguir esse padrão de integração com o Sentry no Flutter, você garante um monitoramento robusto, com contexto rico, alertas inteligentes e rastreamento de performance. Use o SentryService como interface principal para padronizar e facilitar a captura de erros, mensagens e contexto de uso.

Last updated