# 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 30–60s 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: ```ts { 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.