Files
OmniRoute/docs/FASE-04-error-handling-observability.md
diegosouzapw 492afc4ff1 refactor: decompose usageDb, handleSingleModelChat, UI components (T-15, T-28, T-29)
T-15 — Decompose usageDb.js (969→40 lines):
- Extract src/lib/usage/migrations.js (legacy + JSON→SQLite migration)
- Extract src/lib/usage/usageHistory.js (tracking, pending, log.txt)
- Extract src/lib/usage/costCalculator.js (pure cost calculation)
- Extract src/lib/usage/usageStats.js (dashboard aggregation)
- Extract src/lib/usage/callLogs.js (structured logs, CRUD, rotation)
- usageDb.js is now a thin facade re-exporting all functions

T-28 — Decompose handleSingleModelChat (183→80 lines):
- Extract handleNoCredentials() — credential error responses
- Extract safeResolveProxy() — proxy resolution with error handling
- Extract safeLogEvents() — fire-and-forget proxy + translation logging
- Also created chatHelpers.js with standalone helper exports

T-29 — Extract shared UI primitives (3230 total lines):
- FilterBar.js — search input + filter chips dropdown
- ColumnToggle.js — table column visibility toggle
- DataTable.js — generic data table with sticky header, loading/empty

Tests: 88/88 pass (no regressions)
2026-02-14 18:53:14 -03:00

6.4 KiB
Raw Blame History

FASE 04 — Error Handling & Observabilidade

Prioridade: 🟠 Importante
Estimativa de Complexidade: Média (46 dias)
Dimensões do Relatório: D5 (Fluxos Ausentes), D8 (LLM Proxy), D9 (Fluxo Ponta a Ponta)
Dependências: FASE-01 (logging corrigido), FASE-03 (domain layer para catálogo de erros)


Objetivo

Implementar tratamento de erros consistente ponta a ponta, observabilidade com correlation IDs, padrões de resiliência (circuit breaker), e telas de erro personalizadas para elevar a maturidade operacional do sistema.


Escopo Detalhado

4.1 — Telas de Erro Personalizadas (404, 500, 403)

Origem no relatório: D5 — Telas de Erro Personalizadas (🟠 Importante)

Especificação Técnica

  • Criar src/app/not-found.js — Página 404 com design do sistema:
    • Mensagem amigável: "Página não encontrada".
    • Link para dashboard, search de documentação.
    • Design consistente com tema do dashboard.
  • Criar src/app/error.js — Boundary de erro para erros de runtime:
    • Botão de "Tentar novamente".
    • Informação mínima do erro (sem stacktrace).
    • Logging do erro completo no server.
  • Criar src/app/global-error.js — Fallback de último recurso.

Critérios de Aceite

  • Navegação para rota inexistente mostra página 404 customizada.
  • Erro de runtime no dashboard mostra error boundary customizado.
  • Todas as páginas de erro seguem o tema visual do sistema.
  • Testes e2e validam renderização das páginas de erro.

4.2 — Catálogo de Error Codes Padronizado

Origem no relatório: D9 — Tratamento de Erro Genérico (🟡 Moderado)

Especificação Técnica

  • Criar src/shared/constants/errorCodes.js:
    export const ERROR_CODES = {
      PROVIDER_UNAVAILABLE: { code: "OMNIROUTE_PROVIDER_UNAVAILABLE", status: 503 },
      AUTH_FAILED: { code: "OMNIROUTE_AUTH_FAILED", status: 401 },
      RATE_LIMITED: { code: "OMNIROUTE_RATE_LIMITED", status: 429 },
      MODEL_NOT_FOUND: { code: "OMNIROUTE_MODEL_NOT_FOUND", status: 404 },
      INVALID_REQUEST: { code: "OMNIROUTE_INVALID_REQUEST", status: 400 },
      TRANSLATION_ERROR: { code: "OMNIROUTE_TRANSLATION_ERROR", status: 502 },
      TIMEOUT: { code: "OMNIROUTE_TIMEOUT", status: 504 },
      INTERNAL_ERROR: { code: "OMNIROUTE_INTERNAL_ERROR", status: 500 },
    };
    
  • Criar helper createErrorResponse(errorCode, details) para respostas padronizadas.
  • Refatorar handlers SSE e API routes para usar o catálogo.
  • Documentar todos os error codes no OpenAPI spec (docs/openapi.yaml).

Critérios de Aceite

  • Todos os erros do proxy retornam formato { error: { code, message, details } }.
  • Error codes documentados no OpenAPI spec.
  • Testes unitários para createErrorResponse.

4.3 — Correlation ID (x-request-id)

Origem no relatório: D8 — Observabilidade Limitada (🟠 Importante)

Especificação Técnica

  • Criar middleware src/shared/utils/requestId.js:
    • Gerar UUID v4 como x-request-id se não presente no request.
    • Propagar em todas as respostas como header.
    • Incluir no logging de pino como campo requestId.
  • Integrar no pipeline:
    • proxy.js — adicionar requestId ao contexto.
    • sse/handlers/chat.js — propagar requestId para providers upstream.
    • usageDb.js / callLogs — armazenar requestId.
  • Expor no dashboard Logger — filtro por requestId.

Critérios de Aceite

  • Responses incluem header x-request-id.
  • Logs do pino incluem campo requestId.
  • Call logs no DB armazenam requestId.
  • Dashboard Logger permite filtro por requestId.

4.4 — Circuit Breaker Pattern

Origem no relatório: D8 — Sem Circuit Breaker (🟠 Importante)

Especificação Técnica

  • Implementar circuit breaker por provider em src/lib/circuitBreaker.js:
    • Estados: CLOSEDOPENHALF_OPEN.
    • Threshold: 5 falhas consecutivas → OPEN.
    • Timeout: 30 segundos em OPEN → tenta HALF_OPEN.
    • Reset: 1 sucesso em HALF_OPEN → CLOSED.
  • Integrar em sse/services/auth.js antes de getProviderCredentials().
  • Expor estado dos circuits no dashboard (endpoint /api/provider-health).

Critérios de Aceite

  • Circuit breaker previne retry storms quando provider está down.
  • Estado OPEN rejeita requests imediatamente com erro PROVIDER_UNAVAILABLE.
  • Transição HALF_OPEN testa provider automaticamente.
  • Dashboard mostra estado de cada circuit.

4.5 — Timeout Padrão Explícito

Origem no relatório: D9 — Request Síncrono sem Timeout (🟠 Importante)

Especificação Técnica

  • Definir valores padrão explícitos:
    const FETCH_TIMEOUT_MS = parseInt(process.env.FETCH_TIMEOUT_MS) || 120_000;
    const STREAM_IDLE_TIMEOUT_MS = parseInt(process.env.STREAM_IDLE_TIMEOUT_MS) || 60_000;
    
  • Aplicar AbortController com timeout em todas as fetch() para providers.
  • Documentar valores padrão em .env.example (não comentado).

Critérios de Aceite

  • Nenhum fetch() para provider sem timeout.
  • Timeout excedido gera erro OMNIROUTE_TIMEOUT (do catálogo).
  • Valores padrão documentados e configuráveis via env.

Pré-Requisitos

  • FASE-01 (logging correto para erros) e FASE-03 (domain layer onde error codes vivem).

Entregáveis

  1. Páginas de erro customizadas (404, 500, 403).
  2. Catálogo de error codes com helper.
  3. Middleware de correlation ID.
  4. Circuit breaker por provider.
  5. Timeouts explícitos em todas as fetch calls.

Critérios de Conclusão da Fase

  • Todas as respostas de erro seguem formato padronizado.
  • Correlation ID presente em 100% dos responses.
  • Circuit breaker ativo e testado por unit tests.

Riscos Identificados

Risco Probabilidade Impacto Mitigação
Circuit breaker muito agressivo bloqueia providers válidos Média Alto Threshold configurável; começar conservador
Correlation ID overhead em high-throughput Baixa Baixo UUID v4 é rápido (~ns)
Timeout default 120s muito longo para alguns endpoints Média Médio Override por provider config