Monitoramento de todas as VPS
API central de leitura para o suporte: CPU, memória, disco, Docker, banco, backups, instâncias, chamadas e webhooks.
O backend do painel de suporte consulta a central, que reúne os servidores já cadastrados no console. Não é necessário distribuir os tokens administrativos das VPS ao painel. Esta API é de leitura; não reinicia serviços nem altera instâncias, limites de chamadas ou webhooks.
Endpoints e autenticação
| Base | Endpoint | Credencial |
|---|---|---|
Central, por exemplo https://wpp.atendro.cloud | GET /api/v1/servers/status | Authorization: Bearer <TOKEN_MONITORAMENTO> |
| Central | GET /api/v1/servers/{server}/status | Mesmo token de monitoramento |
| API de cada VPS | GET /v1/system/status | Header admintoken, usado internamente pela central |
server é o nome cadastrado no console. O cadastro existente determina as VPS consultadas; esta API não aceita URLs arbitrárias. O token da central fica em CONSOLE_MONITORING_TOKEN ou, no Compose, ATENDROZAP_CONSOLE_MONITORING_TOKEN. Use um segredo aleatório de pelo menos 32 caracteres, distinto dos tokens das VPS. Ausente: HTTP 503 monitoring_disabled. Inválido: HTTP 401. Servidor não cadastrado: HTTP 404 server_not_found.
O token é exclusivo destes GETs. Login do console, cookies, token de instância e query string não o substituem. Guarde-o no backend do suporte, nunca no bundle, localStorage ou parâmetros da URL. A API não habilita CORS público.
Exemplo de consumo no backend Node, sem imprimir credenciais:
const response = await fetch(
`${process.env.ATENDROZAP_CENTRAL_URL}/api/v1/servers/status`,
{
headers: { Authorization: `Bearer ${process.env.ATENDROZAP_MONITORING_TOKEN}` },
signal: AbortSignal.timeout(10_000),
redirect: 'error',
},
);
if (!response.ok) throw new Error(`monitoring_http_${response.status}`);
const fleet = await response.json();
// Entregue fleet à rota autenticada do seu painel de suporte.Contrato completo: OpenAPI da central. O endpoint de cada VPS está no OpenAPI principal.
Como ler a resposta
schemaVersion começa em 1. servers inclui também servidores offline, sem suporte à nova versão ou com falhas parciais. A ordem é pelo nome cadastrado.
| Campo | Significado |
|---|---|
generatedAt | Momento da resposta da central, em UTC |
cacheSeconds | Reutilização interna por até 15 segundos |
summary | Contagem total, online, offline, indisponíveis e por saúde |
servers[].server | Nome da VPS no cadastro central |
observedAt | Momento da tentativa mais recente de consultar a VPS |
lastSuccessAt | Última resposta válida observada; null se ainda não houve |
availability | online, offline, unauthorized, unsupported, invalid_configuration, invalid_response, stale, unavailable ou cancelled |
health | ok, warning, critical ou unknown |
latencyMilliseconds | Tempo até os headers HTTP da VPS; null quando indisponível |
dataStale | A resposta de data é uma leitura anterior, não uma medição atual |
data | Snapshot tipado da VPS, ou null sem leitura válida |
alerts[] | Código estável e gravidade, sem erros brutos ou dados privados |
HTTP 200 significa que a consulta central foi executada; não significa que todas as VPS estão saudáveis. Use availability, health, dataStale e os estados de cada seção. Um erro de autenticação da VPS não é ausência de carga. Falhas não propagam corpos, headers, endereços ou tokens do servidor remoto.
As duas rotas compartilham cache. Há no máximo oito consultas simultâneas e cinco segundos por coleta, incluindo a espera por vaga. Muitas consultas de suporte ao mesmo servidor se unem em uma coleta. Novos cadastros aparecem na próxima consulta; alterações de URL/token invalidam o cache correspondente. Leituras anteriores ficam somente em memória e se perdem ao reiniciar a central.
Métricas disponíveis em data
| Seção | Medições e interpretação |
|---|---|
host.snapshot.cpu | CPUs lógicas, uso, espera por I/O e steal, em porcentagem |
host.snapshot.load | Load de 1/5/15 minutos e load dividido por CPUs lógicas |
host.snapshot.memory | RAM total, disponível, usada e percentual; considera MemAvailable |
host.snapshot.swap | Total, livre, usada e percentual |
host.snapshot.rootFilesystem | Disco total, livre, disponível, reservado, ocupado; inodes livres e usados |
host.snapshot.network | Contadores e bytes/s de recepção/transmissão; inclui interfaces virtuais não loopback |
host.snapshot.diskIO | I/O e ocupação do dispositivo da raiz; evita somar disco e partição |
host.snapshot.uptimeSeconds | Tempo ligado da VPS |
host.snapshot.operations.docker | Por papel api/db/backup/console/caddy: containers, em execução, reiniciando, OOM, reinícios e healthcheck |
host.snapshot.operations.storage | Bytes lógicos, quantidade e idade de arquivos de WAL, backups, gravações e diagnóstico; WAL completo cru, gzip, incompleto e auxiliares separados |
host.snapshot.operations.backupVerification | Marcador da última execução de pg_verifybackup; estado e idade da verificação |
database | Disponibilidade, tamanho do banco e pool de conexões da API |
database.archiver | Estado do arquivamento, quantidade pendente, tamanho de pg_wal, sucessos/falhas e timestamps |
workload.instances | Contagens por tipo/estado, leases desta VPS, estados conectados sem lease, vagas de chamadas configuradas e limite de sessões do worker |
workload.calls | Chamadas persistidas abertas, ativas/tocando/conectando/vídeo, excluindo leases expirados ou transferidos do total live |
workload.webhooks | Fila pendente, idade do evento mais antigo, retentativas, eventos mortos e destinos falhando/pausados |
process | Uptime, goroutines e memória do runtime Go da API; não é a RAM da VPS |
host.status pode ser ok/degraded/stale/unavailable. O snapshot traz a hora original de coleta e sua validade. Métricas sem base de comparação, inclusive CPU/rede no primeiro ciclo e após reset, são null. Coleta parcial não converte ausência em zero. Tamanhos dos diretórios são bytes lógicos; disco disponível vem do filesystem. Tráfego agregado inclui interfaces Docker: não serve como fatura de tráfego externo. Falta de healthcheck aparece como tal.
Instâncias e webhooks usam scope: database. Chamadas usam scope: worker e source: database_snapshot; não são uma prova de mídia RTP nem de qualidade da chamada. Se duas VPS compartilham banco, não some as contagens de escopo database. callSlotsConfigured é configuração, não capacidade homologada. A central não estima quantas chamadas uma VPS aguenta a partir desses números.
Um backup verificado não prova cópia fora da VPS nem uma cadeia PITR completa. Sem o marcador de verificação, a situação é desconhecida, mesmo que existam arquivos de backup no diretório. O histórico de falhas do archiver é cumulativo; blocked exige falha mais recente que o sucesso e segmentos pendentes.
Alertas e painel
O painel pode começar com cartões de VPS, barras de CPU/RAM/disco, estado dos serviços, arquivamento do WAL, idade do backup, instâncias e chamadas ativas. Atualize a cada 30 segundos. Preserve indicação de leitura antiga e exiba — para null, em vez de zero. Um erro global da central deve marcar o painel como desatualizado, sem limpar todos os servidores existentes.
Limiares iniciais da central:
| Medida | Aviso | Crítico |
|---|---|---|
| Disco e inodes ocupados | 85% | 95% |
| RAM ocupada | 85% | 95% |
| CPU ocupada | 85% | 98% |
| CPU steal | 10% | 25% |
| Verificação de backup antiga | — | Mais de 36 horas |
Banco indisponível, WAL bloqueado e serviço parado/reiniciando/unhealthy/OOM geram alerta crítico. Dados incompletos, WAL parcial e fila de webhook com mais de cinco minutos geram aviso. Os limiares avaliam snapshots; para notificações, o suporte deve exigir persistência em várias amostras e deduplicar alertas. Esta implementação não envia mensagens nem instala um sistema de notificações.
Para gráficos históricos, armazene as amostras no backend do suporte usando server e a hora original sampledAt; não duplique amostras vindas do cache. A API fornece estado atual e última leitura válida, não séries temporais.
Instalação
- Preparar a revisão pelo fluxo
deploy/ship.sh HOST REV. O build exportahost-healthewal-archiveestáticos para/opt/atendrozap/releases/REV/ops. Ative a revisão comsh deploy/host-health/install-ops.sh REVno host; o preparo do build por si só não troca os executáveis em uso. - Instalar os arquivos de
deploy/host-healthe executarinstall.shno host. O serviço systemd coleta a cada 15 segundos e escreve arquivo privado 0600, dono UID/GID 65532, em/opt/atendrozap/health/status.json. - O Compose monta esse diretório somente para leitura na API. Configure
ATENDROZAP_SYSTEM_STATUS_HOST_FILE=/host-health/status.jsone, opcionalmente,ATENDROZAP_SYSTEM_STATUS_HOST_MAX_AGE=3m(15s a 15m). O prazo efetivo é o menor entre esse teto evalidForSecondsdo snapshot; com coleta a cada 15 segundos, o coletor declara validade de 45 segundos. - Configure o token de monitoramento privado na central. Publique API e console na janela autorizada; recriar a API afeta brevemente as sessões de mensagens e chamadas. Recriar PostgreSQL para usar o novo
archive_commandé um passo distinto e deve ser coordenado. - Confira cada VPS pelo novo endpoint e as ausências parciais antes de considerar o painel operacional. VPS antigas aparecem como
unsupported.
O coletor roda no host Linux, acessa /proc e consulta apenas campos permitidos do Docker. O socket Docker não é montado na API. Reinicie somente o coletor após mudar volumes/papéis para atualizar os diretórios descobertos. macOS e execução do coletor dentro de container são explicitamente indisponíveis.