PDM · DAW 2

Aula 26 · Semana 11 · Quarta, 18 de novembro de 2026 · 16:00 às 18:00

Observabilidade e review da sprint 2

Teoria (30 minutos): observabilidade em produção: relatórios de crashes, analytics, feature flags e remote config, métricas a acompanhar. Prática: review da sprint 2, retrospetiva e planeamento da sprint 3.

Sprint 3: 19/11 a 02/12

No fim desta aula consegues

Sem observabilidade não sabes que a app está partida

Para os testes: sem símbolos um crash report de release é ilegível; sem a versão da app não sabes se o bug ainda existe.

Analogia Crash reports e métricas são a caixa negra e o painel de instrumentos do avião. Sem eles, só se sabe que o avião caiu quando alguém telefona, e sem os dados do voo (versão, dispositivo, breadcrumbs) não se sabe porquê. A caixa negra regista o que aconteceu; o painel mostra, em voo, se está tudo dentro dos limites.

Crashlytics vs Sentry, e os dois pontos de captura

Firebase CrashlyticsSentry
CustoGrátis, dentro do FirebaseGrátis até 5 mil erros por mês; self-hosted possível
Integraçãofirebase_crashlytics, precisa do projeto Firebase e do google-services.jsonsentry_flutter, só precisa de um DSN
Pontos fortesLiga-se ao Analytics e ao Remote Config; deteta ANR no AndroidPerformance tracing, releases, breadcrumbs de navegação, backend na mesma conta
Erros não fataisrecordErrorcaptureException
FlutterError.onError = (details) {
  FlutterError.presentError(details);                 // continua a aparecer na consola
  crash.registar(details.exception, details.stack);   // erros de build, layout e paint
};
PlatformDispatcher.instance.onError = (error, stack) {
  crash.registar(error, stack, fatal: true);          // Futures sem catch, fora da árvore
  return true;                                        // tratado: a app não morre
};

Para os testes: FlutterError.onError apanha erros do framework; PlatformDispatcher.instance.onError apanha os assíncronos. Os dois SDKs ligam ambos por ti.

Analytics: eventos com sentido

Para os testes: analytics regista eventos de produto, não dados pessoais; um funil mostra onde os utilizadores desistem.

Feature flags e remote config

Para os testes: uma feature flag liga ou desliga funcionalidades sem passar pela loja; o forced update bloqueia versões abaixo da mínima.

Analogia Uma feature flag é um interruptor no painel de instrumentos que se pode desligar em voo, sem aterrar. Uma correção pela loja é aterrar, reparar e voltar a descolar: demora dias, e há passageiros que nunca apanham o voo seguinte. O interruptor desliga a funcionalidade partida em minutos, na versão que já está instalada.

Métricas, alertas e logs

MétricaO que éValor saudável
Crash-free usersPercentagem de utilizadores sem nenhum crash no períodoAcima de 99,5%
ANR (Android)"App Not Responding": a UI thread bloqueada 5 segundosAbaixo de 0,47% das sessões, o limiar do Play
Tempo de arranqueDo toque no ícone ao primeiro frame útilAbaixo de 2 s a frio (aula 30)
Adoção por versãoPercentagem de utilizadores em cada versãoMaioria na última ao fim de duas semanas

Para os testes: crash-free users e ANR são as métricas que as lojas vigiam; acima dos limiares, a visibilidade da app cai.

Review da sprint 2

Se a demo falhar Diz o que devia acontecer e passa à frente. Ninguém é penalizado por um crash na demo; é penalizado por não o saber explicar.

Retro e planeamento da sprint 3

Retro (15 min)

  • Cada membro escreve três post-its: começar, parar, continuar.
  • O grupo escolhe um de cada e partilha com a turma em um minuto.
  • Tema típico: "parar de deixar PRs abertos três dias"; "começar a testar no telemóvel do colega".

Sprint 3, a última (19/11 a 02/12)

  • Entra: os requisitos mínimos em falta, no máximo um extra por grupo, testes e CI, o polish e a distribuição de sexta.
  • Fica de fora: funcionalidades novas sem os mínimos feitos, refactors grandes, trocar de arquitetura.
  • Pronto na sprint 3: instalável por um tester fora do grupo, README com screenshots, CI verde.

Backlog da sprint 3 em issues até sexta. Review da sprint 3 a 02/12; freeze a 09/12.

Demo do docente: Sentry num projeto Flutter em 5 minutos

  1. Projeto no sentry.io do tipo Flutter; copia o DSN. Depois flutter pub add sentry_flutter.
  2. Inicialização a envolver o runApp:
    Future<void> main() async {
      await SentryFlutter.init(
        (options) {
          options.dsn = const String.fromEnvironment('SENTRY_DSN');
          options.environment = kReleaseMode ? 'production' : 'dev';
          options.tracesSampleRate = 0.2;   // 20% das sessões com performance
        },
        appRunner: () => runApp(const TempoApp()),
      );
    }
  3. Correr com flutter run --dart-define=SENTRY_DSN=https://... e carregar num botão que faz throw StateError('teste de crash').
  4. Ver a issue no Sentry: stack trace legível, dispositivo, breadcrumbs com os ecrãs visitados. Marcar como resolvida na versão seguinte.
O DSN não é um segredo crítico Só permite enviar eventos, mas vai por --dart-define na mesma: o que fica no repositório é a ausência dele.

Até sexta

Para fazer

  • Backlog da sprint 3 fechado até sexta: issues com critérios de aceitação, quem faz o quê, e o que fica de fora escrito no README.
  • Sexta é workshop de 4 horas (08:30): traz o telemóvel com espaço livre, cabo, e uma conta Google para receber o build dos colegas.
  • Opcional: liga o Sentry ou o Crashlytics ao projeto num PR de um membro. É um extra barato e conta.

Para ler