Files
clube67_newwhats.local/clube67/newwhats.local/md/proposta_monitor_sistema.md
T

5.7 KiB
Raw Blame History

Proposta — Monitor de sistema (disco, memória, CPU)

Contexto

Quando o servidor cai ou trava, precisamos de visibilidade sobre o estado de disco, memória e CPU nos minutos anteriores à falha — caso contrário o diagnóstico vira adivinhação. O monitor precisa:

  1. Sobreviver a crash/hang do backend Node (senão não vale nada pós-mortem)
  2. Ter pouca sobrecarga (não queremos o próprio monitor derrubar o servidor)
  3. Ser simples de consultar depois do incidente

Opções

🅰 Post-mortem via log rotativo (mínimo viável)

Script bash standalone + systemd timer coletando snapshot a cada 3060s em /var/log/newwhats-health.log (rotativo por logrotate).

Campos coletados:

  • Uso de disco (df -h /)
  • Memória (free -m — total, usado, livre, cache, swap)
  • CPU / load average (uptime, top -bn1 | head)
  • Processos do newwhats (PID, %CPU, %MEM, comando)
  • Rede (ss -s — conexões TCP ativas)
  • Uptime (uptime -p)

Entregáveis:

  • /opt/newwhats/scripts/collect-health.sh — script bash idempotente
  • /etc/systemd/system/newwhats-health.service — unit oneshot
  • /etc/systemd/system/newwhats-health.timer — timer disparando a cada 30s
  • /etc/logrotate.d/newwhats-health — rotação diária, retenção configurável

Vantagem crítica: roda fora do backend. Sobrevive a crash, hang, OOM killer, e até a kill -9 do processo Node. Quando o servidor cair, basta tail /var/log/newwhats-health.log e aparece exatamente o estado nos últimos minutos.

Desvantagem: sem dashboard — só via terminal.


🅱 Post-mortem + endpoint em tempo real

Tudo do A, mais:

Endpoint /api/admin/system-health no backend que retorna JSON com leitura ao vivo:

{
  uptime:        number,    // os.uptime()
  loadAvg:       [n, n, n], // os.loadavg()
  memory: {
    total:       number,    // os.totalmem()
    free:        number,    // os.freemem()
    usedPct:     number,
    processRss:  number,    // process.memoryUsage().rss
    processHeap: number,    // process.memoryUsage().heapUsed
  },
  disk: {
    total:       number,    // fs.statfs('/')
    free:        number,
    usedPct:     number,
  },
  cpu: {
    cores:       number,
    model:       string,
  },
  node: {
    version:     string,
    pid:         number,
  },
}

Protegido por adminMiddleware.

Vantagem: permite montar dashboard no frontend depois sem re-arquitetar. Útil também pra curl/monitoring externo (UptimeRobot, etc).

Desvantagem: endpoint depende do backend estar vivo. Se o processo travou, só o log bash salva. Por isso sempre acompanha o A, nunca substitui.


🅲 A + B + dashboard frontend + alertas

Tudo do B, mais:

  • Página admin no frontend (/admin/system) com gráficos das últimas 24h
  • Polling do endpoint a cada 5s
  • Histórico persistido em tabela Postgres (system_health_samples) ou stream no Dragonfly (mais leve, TTL de 24h automático)
  • Emit de system:alert via socket.io quando threshold é ultrapassado:
    • Memória > 90%
    • Disco > 85%
    • Load > numCores * 2
  • Toast no frontend mostrando o alerta

Desvantagens:

  • Adiciona chart lib no frontend (recharts, apex, chart.js — ~50KB gzipped)
  • Alertas via socket.io não chegam se o backend estiver morto — falsa sensação de segurança
  • Alertas em tempo real geralmente são feitos com ferramenta externa (Grafana/Prometheus/Netdata) — reinventar dentro do app é trabalho sem ROI claro

Recomendação: A+B

Por quê:

  1. A cobre o caso real que você descreveu ("servidor caiu ou travou"). Post-mortem via log é o que sempre funciona, mesmo no pior cenário.
  2. B dá um hook pra construir dashboard depois sem refatorar — o endpoint é pequeno e vive debaixo do adminMiddleware.
  3. C adiciona complexidade que pode ser feita em sprint futura se você decidir que o ganho vale. Começar sem gráficos é mais barato e mais rápido de entregar.
  4. Alertas em tempo real são complementares, não substitutos: se você quiser notificações robustas, a resposta é integrar com Prometheus / Grafana / Netdata — que foram feitos pra isso — não reescrever a roda dentro do app.

Decisões que precisam de resposta antes de aplicar

# Decisão Opções Default sugerido
1 Intervalo de coleta 30s / 60s 30s (granularidade importa pra detectar spikes)
2 Retenção do log 7 dias / 30 dias 7 dias (rotação diária, arquivo ~10MB/dia)
3 Notificações imediatas email / webhook / nada nada (começar simples)
4 Path do log /var/log/newwhats-health.log (precisa root na criação) / /home/deploy/projetos/newwhats.local/logs/health.log (sem sudo) /var/log/newwhats-health.log (padrão systemd, integra com logrotate global)

Escopo explicitamente fora

  • Monitoramento distribuído (vários hosts)
  • Alertas por SMS/WhatsApp/Slack
  • Dashboard com gráficos históricos (fica na Opção C)
  • Integração com Prometheus/Grafana/Netdata (trabalho separado, fora do scope do app)
  • APM / tracing de requests (é outra categoria de ferramenta)
  • Monitor de health do Postgres / Dragonfly (checar separadamente se houver sintomas — hoje não é gargalo)

Estimativa de entrega (referência, não commitment)

Opção A isolada: script bash + 2 units systemd + logrotate config → 3 arquivos pequenos, baixa superfície.

Opção A+B: adiciona 1 endpoint no backend (~40 linhas TypeScript) e uma chamada em server.ts pra montar a rota. Sem mudança no frontend.

Opção C: soma uma página React com gráficos + migration + lógica de sample + lógica de alerta + toast handler. Bem mais trabalho.