Skip to content

Latest commit

 

History

11 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Network Observer Microservice

Microserviço que expõe, via um único endpoint REST, o uso de CPU e RAM da máquina e a conectividade de rede (latência de ping e status de portas essenciais).

Status: protótipo funcional — coleta de métricas de sistema e rede funcionando e containerizado; sem autenticação, persistência ou testes implementados ainda.


Problema Resolvido

Uma equipe de TI que quer saber rapidamente "esse servidor está saudável?" normalmente precisa entrar na máquina e rodar vários comandos separados: top pra CPU, free pra RAM, ping pra latência, telnet/nc pra ver se uma porta está aberta.

Este microserviço junta essas checagens atrás de uma única chamada HTTP. Um GET /metrics devolve tudo de uma vez, num JSON só, pronto pra ser consumido por qualquer painel ou script de monitoramento.


Como Funciona

flowchart TD
    A[GET /metrics] --> B[Coleta uso de CPU - psutil, bloqueia 1s]
    B --> C[Coleta uso de RAM - psutil]
    C --> D[Ping para google.com - ate 2s]
    D --> E[Verifica porta 80 - HTTP]
    E --> F[Verifica porta 22 - SSH]
    F --> G[Retorna JSON com metricas de sistema e rede]
Loading

Cada chamada ao endpoint dispara as cinco coletas em sequência, uma depois da outra, e só devolve a resposta quando todas terminam.


Arquitetura

  • app/main.py — define o único endpoint, GET /metrics, e orquestra as chamadas aos dois módulos de coleta. Não tem lógica própria além de montar o JSON de resposta.
  • app/core/metrics.py — coleta uso de CPU e RAM do host via psutil.
  • app/core/network.py — verifica latência (ping) e se portas TCP específicas estão abertas.
  • app/models/schemas.py — arquivo criado, reservado para os modelos Pydantic da resposta; hoje está vazio, e /metrics devolve um dicionário Python puro, sem validação de schema de saída.
  • app/tests/test_metrics.py — arquivo de teste criado, ainda sem casos implementados.

Decisões de Arquitetura

Endpoint único (/metrics) — comecei simples, com uma rota que devolve tudo de uma vez, pra não precisar desenhar uma API mais rica antes de validar se as métricas certas estavam sendo coletadas corretamente.

psutil para CPU/RAM — é a biblioteca padrão de fato pra esse tipo de coleta em Python; evita ter que ler /proc na mão e lidar com diferenças entre sistemas operacionais.

pythonping em vez de chamar o ping do sistema via subprocess — preferi uma lib Python nativa a depender do binário ping do SO, que tem flags diferentes entre Linux, Windows e macOS.

Socket cru pra checar porta, em vez de uma lib de scan — só precisava saber "abriu ou não abriu"; um socket TCP com timeout curto resolve isso sem trazer uma dependência maior.

Timeouts curtos (2s no ping, 1s no socket) — decisão consciente pra a checagem nunca ficar pendurada esperando uma rede lenta ou um host fora do ar.

Docker desde o início — pensando em rodar isso em qualquer ambiente de CI ou orquestrador sem depender de ter Python instalado na máquina.


Trade-offs

Rota async chamando funções síncronas e bloqueantes. get_all_metrics é async def, mas as cinco coletas internas (psutil.cpu_percent, ping, dois check_port) são todas síncronas. O próprio psutil.cpu_percent(interval=1) já impõe 1 segundo de bloqueio no event loop por chamada — é o piso de latência do endpoint, não uma exceção. No pior caso, somando o timeout do ping e das duas portas, uma única requisição pode travar o event loop inteiro por vários segundos, e uma segunda requisição simultânea espera a primeira terminar tudo antes de começar. Funciona bem pra uma consulta manual ocasional; não escalaria com clientes fazendo polling frequente.

Alvo de rede fixo em google.com. Prova que a conectividade externa da máquina funciona, mas não monitora nenhum servidor real da infraestrutura de quem usa o serviço — isso ainda está só no roadmap.

Falhas de rede retornam silenciosamente 0/False. Tanto check_ping quanto check_port capturam qualquer exceção e devolvem um valor "neutro". Isso evita que o endpoint quebre, mas também esconde a diferença entre "a rede está realmente ruim" e "a checagem falhou por outro motivo" (por exemplo, falta de permissão para abrir socket ICMP bruto em ambientes sem privilégio).

Sem persistência. Cada chamada a /metrics é uma leitura pontual do momento exato da requisição; não existe histórico.


Estrutura do Projeto

network-microservico/
├── Dockerfile
├── requirements.txt
├── app/
│   ├── main.py                  # endpoint /metrics
│   ├── core/
│   │   ├── metrics.py            # CPU e RAM via psutil
│   │   └── network.py            # ping e checagem de porta
│   ├── models/
│   │   └── schemas.py            # reservado para modelos Pydantic, ainda vazio
│   └── tests/
│       └── test_metrics.py       # criado, ainda sem casos implementados
└── diagramas/
    ├── DUSO.png
    ├── ERD.png
    ├── DiagramaClasse.png
    ├── dockerizado.png
    └── roadmap_melhorias.png

Tecnologias

Tecnologia Papel no projeto
FastAPI Expõe o endpoint GET /metrics
Uvicorn Servidor ASGI usado em desenvolvimento e dentro do container
psutil Coleta uso de CPU e RAM do host
pythonping Mede latência via ICMP
socket (stdlib) Verifica se as portas 80 e 22 estão abertas
Docker Empacota a aplicação para rodar em qualquer ambiente

python-dotenv está no requirements.txt, mas hoje não é importado em nenhum arquivo do projeto — não há .env nem configuração via variável de ambiente ainda. Ainda não fiz essa limpeza.


Como Executar

Local

git clone https://github.com/r0b3rTdk/network-microservico.git
cd network-microservico

python3 -m venv venv
source venv/bin/activate          # Windows: venv\Scripts\Activate.ps1

pip install -r requirements.txt

uvicorn app.main:app --reload

Acesse http://127.0.0.1:8000/metrics.

Docker

docker build -t network-observer-microservice .
docker run -p 8000:8000 network-observer-microservice

Acesse http://localhost:8000/metrics.


Como Testar

app/tests/test_metrics.py existe na estrutura do repositório, mas está vazio — ainda não escrevi os casos de teste.

Hoje a validação é manual:

curl http://127.0.0.1:8000/metrics

A resposta esperada tem dois blocos, system_metrics (CPU e RAM em porcentagem) e network_metrics (latência em ms e status booleano das portas 80 e 22 de google.com).


Limitações Conhecidas

  • A rota é async def, mas todas as coletas internas são bloqueantes — cada requisição trava o event loop por pelo menos 1 segundo (o próprio psutil.cpu_percent(interval=1)), podendo chegar a vários segundos somando ping e portas.
  • Alvo de rede fixo em google.com, sem forma de configurar outro host ou porta.
  • python-dotenv está listado nas dependências, mas não é usado em nenhum lugar do código.
  • Falha de rede e falta de permissão para socket ICMP bruto produzem o mesmo resultado (0), sem diferenciação no retorno.
  • Nenhuma métrica é persistida — sem histórico.
  • Endpoint aberto, sem autenticação.
  • Sem testes automatizados.

O que este projeto ainda NÃO faz

  • Não autentica as chamadas ao endpoint (planejado: API Key).
  • Não monitora múltiplos alvos — só o host fixo usado como teste de conectividade.
  • Não persiste métricas em banco, mesmo já tendo um ERD desenhado para isso.
  • Não envia alertas ou notificações quando uma métrica ultrapassa um limite.
  • Não tem testes automatizados.
  • Não tem pipeline de CI/CD configurado.

Próximos Passos

  • Adicionar autenticação via API Key no /metrics, validando por variável de ambiente.
  • Tornar o host e as portas monitoradas configuráveis, em vez de fixos em google.com.
  • Escrever os casos de teste em test_metrics.py.
  • Mover as coletas bloqueantes para threadpool (run_in_threadpool), pra não travar o event loop a cada chamada.

Evolução para Produção

  • Persistência das métricas coletadas, seguindo o modelo já desenhado no ERD, para permitir consulta histórica.
  • Notificações (e-mail ou Slack) quando uma métrica ultrapassar um limite configurado.
  • Monitoramento de múltiplos alvos numa única chamada, em vez de um host fixo.
  • Métricas em formato Prometheus, para integrar com um Grafana.
  • CI/CD rodando os testes e o build da imagem Docker a cada push.

Aprendizados

A maior surpresa foi perceber, só depois de rodar a aplicação, que o interval=1 do psutil.cpu_percent() sozinho já impõe um segundo de espera em toda chamada — parece um parâmetro pequeno, mas define o piso de latência do endpoint inteiro.

Isso me ensinou na prática o que significa misturar código síncrono dentro de uma rota async do FastAPI: o event loop realmente fica bloqueado, não é só uma preocupação teórica de livro.

Colocar timeout curto no ping e no socket foi uma decisão simples de tomar, mas evitou que uma rede lenta travasse a API inteira por muito mais tempo do que o necessário.

Desenhar o ERD antes de precisar dele ajudou a pensar no roadmap com mais clareza, mesmo sabendo que a implementação da persistência ainda não veio.


Autor

Robert Emanuel

Desenvolvedor Back-end focado em Python, FastAPI, SQL, Docker e APIs REST.

GitHub: https://github.com/r0b3rTdk

LinkedIn: https://www.linkedin.com/in/robert-emanuel/

About

Microserviço voltado para monitoramento de recursos e conectividade de rede em sistemas distribuídos, com acesso via API REST.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages