Local-to-Cloud Diagnostic Gateway
✓ Concluído — Deploy AWS PendenteAgente de diagnóstico Python local-first para Windows que coleta telemetria de hardware, SO e rede, opera completamente offline e sincroniza com um backend serverless AWS via fila durável com backoff e jitter. Todos os componentes locais implementados e testados — 362 testes passando.
Descrição do Projeto
O Local-to-Cloud Diagnostic Gateway é um agente de diagnóstico de infraestrutura escrito em Python. Ele coleta telemetria de CPU, memória, armazenamento, sistema operacional e rede, avalia regras determinísticas de saúde localmente, persiste cada execução em SQLite e continua funcionando sem internet. A telemetria selecionada é enfileirada localmente e sincronizada com um backend serverless AWS (HTTP API Gateway → Lambda → DynamoDB) com política de retentativa limitada e baseada em backoff com jitter.
O projeto demonstra um design edge-first contra um backend serverless: diagnósticos totalmente funcionais offline, uma fila de sincronização durável que sobrevive a longas quedas sem perder nem duplicar eventos, ingestão idempotente na nuvem, IAM de menor privilégio e infraestrutura validável offline.
Princípio Arquitetural: "Local-First"
Coleta raw de hardware/OS/rede, diagnósticos locais, avaliação de saúde, persistência em SQLite e gerenciamento da fila offline. Funciona sem internet e sem configuração de nuvem.
☁️ Cloud (AWS Serverless):Recebe e valida telemetria, persiste no DynamoDB, expõe API REST versionada e centraliza logs e métricas no CloudWatch. A nuvem é uma extensão do sistema, não uma dependência obrigatória.
Arquitetura do Sistema
Fila de Sincronização Offline
Um dos diferenciais do projeto é a fila durável que garante que nenhum evento seja perdido durante quedas de conectividade. A máquina de estados implementada cobre cinco estados:
PENDING → SYNCING → SYNCED
↓
FAILED → retry (backoff + jitter)
↓ (após limite)
DEAD_LETTER
Retentativas usam backoff exponencial com jitter para evitar thundering herd. Quando a conectividade retorna, a fila drena automaticamente. Eventos com falha definitiva vão para DEAD_LETTER sem bloquear a fila principal. Ingestão na nuvem é idempotente por event_id, eliminando duplicatas em reenvios.
Engenharia & Resiliência
testes passando
estados de sincronização
funções Lambda
dep. de runtime
- Diagnósticos offline completos: hardware, rede e avaliação de saúde funcionam sem rede e sem configuração de nuvem — a nuvem é extensão, não requisito.
- Avaliação de saúde determinística: motor de regras configurável (sem LLM) classifica o estado como HEALTHY / DEGRADED / UNSTABLE / OFFLINE / UNKNOWN com evidências e possíveis causas, nunca uma causa raiz definitiva.
- Falha graceful por coletor: falhas de coleta marcam a seção como indisponível e a execução continua — um coletor de GPU que falha não derruba o diagnóstico inteiro.
- Ingestão idempotente:
event_idgerado antes da sincronização garante exatamente-uma-vez no DynamoDB, mesmo com retentativas. - IAM de menor privilégio: uma role IAM por função Lambda, sem ações curinga. Redirecionamentos e status inesperados tratados como erros de configuração para que a chave de ingestão nunca seja enviada a outro host.
- Testes sem conta AWS: testes unitários, integração com
moto, E2E do cliente de sincronização contra handlers reais sobre servidor HTTP local e portões de qualidade (fronteiras de import, vazamento de segredo, estrutura de ADRs). - Infraestrutura como código: AWS SAM validado com
cfn-lint. Infraestrutura reproduzível com scripts de deploy, teardown e validação.
Exemplo de Código (Fila Offline com Backoff)
# Lógica simplificada da fila de sincronização com backoff e jitter
import time
import random
from enum import Enum
class SyncState(Enum):
PENDING = "PENDING"
SYNCING = "SYNCING"
SYNCED = "SYNCED"
FAILED = "FAILED"
DEAD_LETTER = "DEAD_LETTER"
def backoff_with_jitter(attempt: int, base: float = 1.0, cap: float = 60.0) -> float:
# Backoff exponencial com full jitter — evita thundering herd
delay = min(cap, base * (2 ** attempt))
return random.uniform(0, delay)
def sync_event(event_id: str, payload: dict, max_retries: int = 5) -> SyncState:
for attempt in range(max_retries):
try:
response = api_client.post("/v1/telemetry", json=payload)
if response.status_code == 200:
return SyncState.SYNCED
except Exception as exc:
# Log estruturado com contexto suficiente para diagnóstico
logger.warning("sync_failed", event_id=event_id, attempt=attempt, error=str(exc))
wait = backoff_with_jitter(attempt)
time.sleep(wait)
return SyncState.DEAD_LETTER # Exauriu retentativas