Skip to content

feat(observability): integra Sentry (error tracking) + health check#64

Merged
johnlaff merged 1 commit into
mainfrom
feat/sentry-observability
Jul 10, 2026
Merged

feat(observability): integra Sentry (error tracking) + health check#64
johnlaff merged 1 commit into
mainfrom
feat/sentry-observability

Conversation

@johnlaff

Copy link
Copy Markdown
Owner

O quê e por quê

Fecha a lacuna de observabilidade identificada na auditoria: o 500 do clock-out só foi descoberto porque a usuária reclamou. Agora erros server-side (route handlers, server actions, RSC) e client-side são capturados com alerta — via Sentry no plano patrocinado (Student Pack).

Mudança

Arquivo O quê
src/instrumentation.ts init Sentry (server/edge) + onRequestError, preservando a validação do keyring no boot
src/instrumentation-client.ts init client + onRouterTransitionStart
src/sentry.{server,edge}.config.ts Sentry.initenabled só em produção, sendDefaultPii: false, tracing leve
src/app/global-error.tsx boundary de erro raiz (com <html>/<body> próprios) → captureException
src/lib/hour-bank.ts os recálculos fail-safe engoliam o erro por design; agora reportam ao Sentry sem deixar de engolir (era a classe exata de falha silenciosa que motivou isto)
src/app/api/health/route.ts health check (DB SELECT 1) para o App Service + uptime monitor; await connection() (não force-dynamic, incompatível com cacheComponents)
src/proxy.ts libera api/health e monitoring no matcher (senão o health leva 307 e o tunnel quebra)
next.config.ts withSentryConfig por cima do withSerwist; tunnelRoute same-origin (não mexe na CSP); source maps só com auth token; release = SHA
Dockerfile / build-image.yml DSN como build-arg; SENTRY_AUTH_TOKEN como build secret (não persiste na imagem)

Design validado por 3 lentes independentes antes do código

As decisões não-óbvias (matcher do proxy, connection() vs force-dynamic, composição dos plugins, wiring do source-map secret, captura dos catches do hour-bank) foram levantadas e verificadas em revisão adversarial pré-implementação.

Como verificar

  • Gates locais verdes: tsc, 295 testes, Biome (188 arquivos), react-doctor zerado.
  • Build standalone via container (o que o CI do PR não cobre): imagem builda, sw.js presente, container boota e GET /api/health → 200 (com DB real). O health voltou 200 (não 307) → matcher do proxy correto.
  • CI (verify) roda sem os secrets Sentry → Sentry.init vira no-op e o upload de source maps é pulado; build segue verde.

Pós-merge (não automático)

  1. Setar healthCheckPath=/api/health no App Service (faço via az após o deploy).
  2. Criar o uptime monitor no Sentry apontando pra https://archtime.app/api/health.
  3. Verificar em produção: /api/health 200, disparar um erro de teste e confirmar o evento chegando com release = SHA do commit.

Adiciona observabilidade de producao -- a lacuna que deixou o 500 do clock-out
passar despercebido ate a usuaria reclamar. Erros server-side (route handlers,
server actions, RSC) e client-side passam a ser capturados com alerta.

- @sentry/nextjs no App Router: init server/edge via instrumentation.ts (sem
  quebrar a validacao do keyring no boot), client via instrumentation-client.ts,
  onRequestError e global-error.tsx. sendDefaultPii:false (nao envia dados da
  usuaria). Ligado so em producao.
- hour-bank: os recalculos fail-safe engoliam o erro por design (mutacao ja
  commitada); agora reportam ao Sentry sem deixar de engolir -- era exatamente a
  classe de falha silenciosa que motivou a integracao.
- /api/health: liveness/DB check (SELECT 1) para o health check do App Service e
  o uptime monitor do Sentry. await connection() em vez de force-dynamic
  (cacheComponents). Publico -- proxy.ts libera api/health e o tunnel /monitoring.
- next.config: withSentryConfig por cima do withSerwist; tunnelRoute /monitoring
  (same-origin, nao mexe na CSP); source maps so sobem com auth token; release
  pelo SHA do commit (SENTRY_RELEASE), ja que o .git nao entra no build Docker.
- Dockerfile/build-image: NEXT_PUBLIC_SENTRY_DSN como build-arg; SENTRY_AUTH_TOKEN
  como build secret (nao persiste na imagem).

Validado: gates locais verdes (tsc, 295 testes, biome, react-doctor) e build
standalone via container -- /api/health responde 200 no container.
@johnlaff
johnlaff merged commit 40f0c08 into main Jul 10, 2026
1 check passed
@johnlaff
johnlaff deleted the feat/sentry-observability branch July 10, 2026 20:46
johnlaff added a commit that referenced this pull request Jul 10, 2026
Cobre a nova observabilidade (PR #64) em toda a documentacao viva:

- docs/adr/0006-observabilidade-sentry.md: ADR novo com contexto (o 500 do
  clock-out invisivel), decisao (Sentry server+client, tunnel /monitoring,
  source maps por SHA, sendDefaultPii false, hour-bank reportando, /api/health +
  healthCheckPath), consequencias e alternativas (Datadog/App Insights/self-host).
- AGENTS.md: secao Observabilidade com as regras operacionais (init, tunnel na
  allowlist do proxy, catches silenciosos reportando, connection() no health).
- README.md: feature de observabilidade + Sentry na linha de infra.
- supabase-security-checklist.md: DSN publico vs SENTRY_AUTH_TOKEN segredo.
johnlaff added a commit that referenced this pull request Jul 10, 2026
Cobre a nova observabilidade (PR #64) em toda a documentacao viva:

- docs/adr/0006-observabilidade-sentry.md: ADR novo com contexto (o 500 do
  clock-out invisivel), decisao (Sentry server+client, tunnel /monitoring,
  source maps por SHA, sendDefaultPii false, hour-bank reportando, /api/health +
  healthCheckPath), consequencias e alternativas (Datadog/App Insights/self-host).
- AGENTS.md: secao Observabilidade com as regras operacionais (init, tunnel na
  allowlist do proxy, catches silenciosos reportando, connection() no health).
- README.md: feature de observabilidade + Sentry na linha de infra.
- docs/assets/architecture.svg: caixa Sentry (erros via tunnel + /api/health)
  abaixo do app, e o passo de source maps no CI/CD.
- supabase-security-checklist.md: DSN publico vs SENTRY_AUTH_TOKEN segredo.
johnlaff added a commit that referenced this pull request Jul 10, 2026
Cobre a nova observabilidade (PR #64) em toda a documentacao viva:

- docs/adr/0006-observabilidade-sentry.md: ADR novo com contexto (o 500 do
  clock-out invisivel), decisao (Sentry server+client, tunnel /monitoring,
  source maps por SHA, sendDefaultPii false, hour-bank reportando, /api/health +
  healthCheckPath), consequencias e alternativas (Datadog/App Insights/self-host).
- AGENTS.md: secao Observabilidade com as regras operacionais (init, tunnel na
  allowlist do proxy, catches silenciosos reportando, connection() no health).
- README.md: feature de observabilidade + Sentry na linha de infra; alt do
  diagrama enriquecido (a11y: via <img> o aria-label interno nao e lido).
- docs/assets/architecture.svg: caixa Observabilidade (Sentry via tunnel +
  /api/health) abaixo do app, seta de source maps CI->Sentry, legenda das setas,
  contraste AA, geometria alinhada e fallback de presentation attributes.
- supabase-security-checklist.md: DSN publico vs SENTRY_AUTH_TOKEN segredo.
johnlaff added a commit that referenced this pull request Jul 10, 2026
Cobre a observabilidade (PR #64) em toda a documentacao viva:

- docs/adr/0006: ADR da decisao (Sentry server+client, tunnel /monitoring,
  source maps por SHA, sendDefaultPii false, hour-bank reportando, /api/health +
  healthCheckPath), consequencias e alternativas.
- AGENTS.md: secao Observabilidade com as regras operacionais.
- README.md: feature + Sentry na infra; alt do diagrama enriquecido (a11y).
- docs/assets/architecture.svg: caixa Observabilidade + seta de source maps
  CI->Sentry + legenda das setas; contraste AA, geometria alinhada e fallback de
  presentation attributes (revisado para craft nos dois temas).
- supabase-security-checklist.md: DSN publico vs SENTRY_AUTH_TOKEN segredo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant