README
¶
🎯 Gordon Watcher
Production-ready file system monitoring and processing pipeline with enterprise-grade observability
📖 Overview
Gordon Watcher é um sistema robusto de monitoramento de sistema de arquivos, projetado para detectar, processar e enfileirar arquivos de forma confiável e escalável. Ideal para pipelines de processamento de documentos, integração de sistemas, ETL e automação de workflows.
🌟 Principais Características
- 🔍 Monitoramento em Tempo Real: Detecta novos arquivos instantaneamente usando
fsnotify - 🚀 Alta Performance: Worker pool concorrente com rate limiting configurável
- 🛡️ Resiliência Total: Circuit breaker, retry automático e reconciliação de órfãos
- 📊 Observabilidade Completa: Métricas Prometheus, tracing OTLP/Jaeger e logs estruturados
- 🔒 Idempotência: Previne processamento duplicado com hashing SHA256
- 🐰 Message Queue: Integração RabbitMQ com Dead Letter Queue (DLQ)
- 🔴 Distributed Locks: Redis para coordenação em ambientes multi-instância
- 🐳 Cloud Native: Docker, Kubernetes-ready, health checks e graceful shutdown
🎨 Arquitetura
graph LR
A[📁 Incoming] -->|fsnotify| B[🔍 Watcher]
B -->|Stability Check| C[⚡ Worker Pool]
C -->|Hash + Lock| D[🔴 Redis]
C -->|Process| E[📦 Processing]
E -->|Success| F[🐰 RabbitMQ]
E -->|Failure| G[❌ Failed]
F -->|DLQ| H[☠️ Dead Letter Queue]
F -->|Worker| I[✅ Processed]
B -.->|Metrics| J[📊 Prometheus]
B -.->|Traces| K[🔍 Jaeger]
📂 Fluxo de Processamento
- 📥 Detecção: Arquivos são detectados na pasta
incoming - ⏱️ Estabilização: Aguarda até o arquivo parar de ser escrito
- 🔐 Hash: Calcula SHA256 para idempotência
- 🔒 Lock: Adquire lock distribuído no Redis
- 📦 Movimentação: Move para
processing - 🐰 Enfileiramento: Publica no RabbitMQ com retry + circuit breaker
- ✅ Finalização: Arquivo fica em
processingaté o worker externo processar
🚀 Quick Start
Pré-requisitos
- 🐳 Docker & Docker Compose
- 🐹 Go 1.21+ (para desenvolvimento)
🏃 Rodando com Docker Compose
# 1. Clone o repositório
git clone https://github.com/fabyo/gordon-watcher.git
cd gordon-watcher
# 2. Configure o ambiente
cp .env.example .env
cp docker-compose.override.yml.example docker-compose.override.yml
# 3. Descubra o IP do servidor (para Samba)
make discover-ip
# Anote o "IP do WSL" que aparecer
# 4. Suba o stack completo
docker compose up -d
# 5. Verifique o status
docker compose ps
# 6. Abra o Dashboard no navegador
open web/dashboard.html
# Ou: firefox web/dashboard.html
# Ou: google-chrome web/dashboard.html
# 7. Monitore os logs
docker compose logs -f watcher
🪟 Acesso Windows (Samba)
O Docker Compose já inclui compartilhamento Samba para você jogar arquivos do Windows!
1. Descobrir o IP do Servidor
No Linux/WSL, rode:
make discover-ip
Saída esperada:
🔍 Descobrindo IPs...
📍 IP do WSL (Docker): 172.24.123.45
🪟 IP do Windows: 192.168.1.100
Para conectar do Windows ao Samba:
\\172.24.123.45\incoming
Credenciais:
Usuário: gordon
Senha: (definida no .env)
2. Conectar do Windows
Opção A: Acesso Direto
- Abra o Explorador de Arquivos
- Digite na barra de endereço:
(Use o IP que apareceu no\\172.24.123.45\incomingmake discover-ip) - Digite as credenciais:
- Usuário:
gordon - Senha: (definida no
.env)
- Usuário:
Opção B: Mapear Unidade de Rede (Recomendado)
-
Abra o Explorador de Arquivos
-
Clique com botão direito em "Este Computador"
-
Selecione "Mapear unidade de rede"
-
Escolha a letra Z: (ou outra disponível)
-
Pasta:
\\172.24.123.45\incoming -
Marque "Reconectar ao fazer logon"
-
Marque "Conectar usando credenciais diferentes"
-
Clique em "Concluir"
-
Digite:
- Usuário:
gordon(ou conforme definido no.env) - Senha: (definida no
.env)
Exemplo de acesso via Windows: Pressione
Win + Re digite:\\172.24.123.45\incomingOu mapeie via comando:
net use Z: \\172.24.123.45\incoming /user:gordon * /persistent:yes(O Windows pedirá a senha)
- Usuário:
3. Usar
Agora você pode jogar XMLs direto na unidade Z: do Windows! 🎉
Os arquivos serão processados automaticamente pelo Gordon Watcher.
🎯 Testando
# Coloque um arquivo na pasta monitorada
echo "Hello Gordon!" > /opt/gordon-watcher/data/incoming/test.xml
# Acompanhe o processamento
docker compose logs -f watcher
# Verifique as métricas
curl http://localhost:9100/metrics | grep gordon_watcher
📊 Observabilidade
📈 Dashboard de Métricas
Visualize TUDO em tempo real!
O Gordon Watcher inclui um dashboard HTML pratico e funcional que mostra todas as métricas importantes.
🚀 Como Abrir
O dashboard é servido automaticamente pelo Docker na porta 8080.
Acesse no seu navegador: 👉 http://localhost:8080
Dica: Se a porta 8080 estiver ocupada, você pode alterá-la facilmente:
DASHBOARD_PORT=9090 docker compose up --build -d

📊 O Que Você Vê
O dashboard mostra 8 cards principais com atualização automática a cada 5 segundos:
Arquivos:
- 📥 Detectados: Total de arquivos encontrados pelo watcher
- ✅ Enviados: Processados com sucesso e enfileirados no RabbitMQ
- 🔄 Duplicados: Já processados anteriormente (idempotência funcionando!)
- ❌ Rejeitados: Padrão ou tamanho inválido
- 🚫 Ignorados: Arquivos ignorados por regras de exclusão
Sistema:
- ⚡ Goroutines: Threads ativas (para detectar memory leaks)
- 👷 Workers Ativos: Quantos workers estão processando agora
- 📦 Fila de Workers: Arquivos aguardando processamento
Taxa de Processamento:
- 📈 Percentual de sucesso
- 📊 Total processado
🔗 Links Rápidos
O dashboard inclui botões para acessar:
- 📊 Métricas Prometheus (dados brutos)
- 🏥 Health Check (status do serviço)
- 🐰 RabbitMQ Management (filas e mensagens)
- 🔍 Jaeger Tracing (rastreamento distribuído via OTLP)
💡 Exemplo de Uso
- Abra o dashboard
- Jogue um XML na pasta compartilhada (Samba)
- Veja em tempo real:
- "Detectados" aumenta (+1)
- "Enviados" aumenta (+1) após processamento
- "Workers Ativos" mostra 1 durante o processamento
- Se jogar o mesmo arquivo de novo:
- "Duplicados" aumenta (+1)
- Arquivo não é reprocessado (idempotência!)
Atualização automática a cada 5 segundos! 🔄
🏥 Health Checks
# Liveness (está vivo?)
curl http://localhost:8081/health
# Readiness (está pronto para receber tráfego?)
curl http://localhost:8081/ready
📈 Métricas Prometheus
Endpoint: http://localhost:9100/metrics
| Métrica | Tipo | Descrição |
|---|---|---|
gordon_watcher_files_detected_total |
Counter | Total de arquivos detectados |
gordon_watcher_files_sent_total |
Counter | Arquivos enviados para fila |
gordon_watcher_files_duplicated_total |
Counter | Arquivos duplicados (já processados) |
gordon_watcher_files_rejected_total |
Counter | Arquivos rejeitados (padrão/tamanho) |
gordon_watcher_queue_errors_total |
Counter | Erros ao publicar no RabbitMQ |
gordon_watcher_goroutines |
Gauge | Número de goroutines ativas |
gordon_watcher_worker_pool_queue_size |
Gauge | Tamanho da fila de workers |
gordon_watcher_file_processing_seconds |
Histogram | Tempo de processamento |
🔍 Distributed Tracing (Jaeger)
UI: http://localhost:16686
Visualize o fluxo completo de cada arquivo:
- Detecção → Estabilização → Hash → Lock → Queue → Worker
Nota: Usa OpenTelemetry Protocol (OTLP) para enviar traces. Compatible com Jaeger, Tempo, Zipkin, etc.
🐰 RabbitMQ Management
UI: http://localhost:15672
Credenciais: gordon / (senha do .env)
- Monitore filas e exchanges
- Visualize mensagens na DLQ
- Acompanhe throughput
⚙️ Configuração
📝 Arquivo de Configuração
Edite configs/config.yaml:
watcher:
paths:
- /opt/gordon-watcher/data/incoming
file_patterns:
- "*.xml"
- "*.pdf"
- "*.json"
exclude_patterns:
- ".*" # Arquivos ocultos
- "*.tmp" # Temporários
- "*Zone.Identifier" # Windows WSL
min_file_size: 100 # bytes
max_file_size: 104857600 # 100MB
max_workers: 10
max_files_per_second: 100
🔐 Variáveis de Ambiente
Veja .env.example para todas as opções disponíveis.
🛡️ Resiliência e Segurança
🔄 Retry com Backoff Exponencial
// Configuração padrão
MaxAttempts: 3
InitialDelay: 1s
MaxDelay: 30s
Multiplier: 2.0
⚡ Circuit Breaker
Protege contra falhas em cascata:
- Threshold: 5 falhas consecutivas
- Timeout: 30 segundos
- Estados: Closed → Open → Half-Open
🔒 Idempotência
- Hash SHA256 de cada arquivo
- Verificação no Redis antes de processar
- Previne duplicação mesmo em multi-instância
🧹 Reconciliação de Órfãos
Na inicialização, arquivos órfãos em processing são movidos de volta para incoming.
🚨 Dead Letter Queue (DLQ)
Mensagens que falharem após todas as tentativas vão para gordon.files.dlq para análise manual.
🎯 Casos de Uso
📄 Processamento de Documentos XML
watcher:
paths:
- /data/xml/incoming
file_patterns:
- "*.xml"
max_workers: 20
max_files_per_second: 200
📊 ETL de Arquivos CSV
watcher:
paths:
- /data/exports/incoming
file_patterns:
- "*.csv"
- "*.tsv"
min_file_size: 1024 # Ignora CSVs vazios
🖼️ Processamento de Imagens
watcher:
paths:
- /data/uploads/incoming
file_patterns:
- "*.jpg"
- "*.png"
- "*.webp"
max_file_size: 52428800 # 50MB
📦 Integração de Sistemas (EDI)
watcher:
paths:
- /data/edi/incoming
file_patterns:
- "*.edi"
- "*.x12"
stable_attempts: 10 # Arquivos grandes
stable_delay: 500ms
🐳 Deploy
Docker
# Build
docker build -t gordon-watcher:latest -f docker/Dockerfile .
# Run
docker run -d \
-v /opt/gordon-watcher/data:/opt/gordon-watcher/data \
-p 8081:8081 \
-p 9100:9100 \
gordon-watcher:latest
Kubernetes
apiVersion: apps/v1
kind: Deployment
metadata:
name: gordon-watcher
spec:
replicas: 3
selector:
matchLabels:
app: gordon-watcher
template:
metadata:
labels:
app: gordon-watcher
spec:
containers:
- name: watcher
image: gordon-watcher:latest
ports:
- containerPort: 8081
name: health
- containerPort: 9100
name: metrics
volumeMounts:
- name: data
mountPath: /opt/gordon-watcher/data
livenessProbe:
httpGet:
path: /health
port: 8081
readinessProbe:
httpGet:
path: /ready
port: 8081
Ansible
cd ansible
ansible-playbook -i inventory/development.yml deploy.yml
🔧 Desenvolvimento
📦 Instalação
# Clone
git clone https://github.com/fabyo/gordon-watcher.git
cd gordon-watcher
# Instale dependências
go mod download
# Build
make build
# Run
./bin/gordon-watcher
🧪 Testing
# Run all unit tests
make test
# Run unit tests with coverage
make test-coverage
# Run integration tests
make test-integration
# Run all tests (unit + integration)
go test -v ./...
go test -v -tags=integration ./tests/integration/...
# Run specific test
go test -v -run TestCircuitBreaker ./internal/watcher/...
# Generate coverage report
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
Test Coverage
Unit Tests:
- ✅ Circuit Breaker (6 tests)
- ✅ Stability Checker (5 tests)
- ✅ Worker Pool (7 tests)
- ✅ Cleaner (6 tests)
- ✅ Retry Logic (8 tests)
Integration Tests:
- ✅ File Detection & Processing
- ✅ ZIP Extraction
- ✅ Duplicate Handling
- ✅ Rate Limiting
- ✅ Stability Checker
- ✅ Non-matching Files
CI/CD
GitHub Actions roda automaticamente em PRs e pushes:
- ✅ Unit & Integration Tests
- ✅ golangci-lint
- ✅ Multi-platform builds (Linux, macOS, Windows)
- ✅ Docker build & push
- ✅ Security scanning (Trivy)
📝 Makefile Targets
make build # Compila o binário
make test # Roda testes
make lint # Roda linter
make docker-build # Build Docker image
make docker-up # Sobe stack completo
make docker-down # Para stack
make clean # Limpa binários
❓ Troubleshooting
🛑 Parar o Watcher Forçadamente
Se o watcher travar ou você precisar matá-lo rapidamente (especialmente durante testes):
pkill -f gordon-watcher
Isso vai encerrar qualquer processo que tenha "gordon-watcher" no nome.
🔒 Segurança
✅ Boas Práticas Implementadas
- ✅ Usuário não-root: Container roda como
gordon(UID 1000) - ✅ Imagem mínima: Alpine Linux (< 20MB)
- ✅ Secrets externos: Credenciais via env vars, nunca hardcoded
- ✅ Health checks: Liveness e readiness probes
- ✅ Graceful shutdown: Finaliza processamento antes de parar
- ✅ Rate limiting: Previne sobrecarga
- ✅ Input validation: Valida tamanho e padrões de arquivo
🔐 Recomendações para Produção
- TLS/SSL: Use AMQPS para RabbitMQ
- Autenticação: Configure Redis com senha
- Network Policies: Isole pods no Kubernetes
- Resource Limits: Defina CPU/Memory limits
- Secrets Management: Use Vault ou Kubernetes Secrets
- Audit Logs: Habilite logs estruturados em JSON
📚 Documentação Adicional
- 🏗️ Arquitetura - Arquitetura e design do sistema
- ⚙️ Configuração - Guia de configuração detalhado
- 📖 Guia de Deploy - Deploy com Docker Compose e Ansible
- 👨💻 Guia de Desenvolvimento - Guia para contribuidores
- Resiliência e Confiabilidade - Resiliência e Confiabilidade
- 🔧 Troubleshooting - Solução de problemas comuns
- 📚 GoDoc - Como visualizar a documentação da API
🤝 Contribuindo
Contribuições são bem-vindas! Por favor:
- Fork o projeto
- Crie uma branch (
git checkout -b feature/amazing) - Commit suas mudanças (
git commit -m 'Add amazing feature') - Push para a branch (
git push origin feature/amazing) - Abra um Pull Request
📄 Licença
Este projeto está licenciado sob a MIT License - veja o arquivo LICENSE para detalhes.
👨💻 Autor
Fabyo
📧 fabyo.php@gmail.com
🐙 GitHub
🚀 Stacks
- Go - Linguagem principal
- Docker - Containerização
- Caddy - Web Server & Reverse Proxy
- fsnotify - Notificações do sistema de arquivos
- RabbitMQ - Message broker
- Redis - Distributed locks
- Prometheus - Métricas
- Jaeger - Distributed tracing
- OpenTelemetry - Observability framework
⭐ Se este projeto foi útil, deixe uma estrela! ⭐
Made with ❤️ and ☕ by Fabyo