Stack completa de observabilidade baseada em Docker Compose, com uma aplicação de exemplo instrumentada (NestJS + Next.js) e toda a pipeline de coleta, armazenamento e visualização de métricas, traces e logs.
- Arquitetura
- Serviços e Portas
- Fluxo de Dados
- Pilares de Observabilidade
- Como Rodar
- Scripts
- Variáveis de Ambiente
- API — Endpoints
- Autenticação
- Dashboard Web
- Testes
- Documentação
┌─────────────────────────────────────────────────────────────────┐
│ Aplicação Exemplo │
│ │
│ ┌──────────────┐ ┌──────────────────────────────┐ │
│ │ web (Next.js│──API──→ │ api (NestJS + OpenTelemetry │ │
│ │ port 3000) │ │ port 8088 / metrics 9465) │ │
│ └──────────────┘ └──────────┬─────────────────--┘ │
│ │ OTLP/gRPC │
└────────────────────────────────────────│──────────────────────--┘
▼
┌──────────────────────────┐
│ otel-collector │
│ gRPC :4317 / HTTP :4318 │
└────┬──────────┬───────────┘
Traces/Logs │ │ Métricas
┌──────────────────┤ ├──────────────────────┐
▼ ▼ ▼ ▼ │
┌────────────────┐ ┌──────┐ ┌──────────┐ │
│ data-prepper │ │Tempo │ │Prometheus│ │
│ :21890 │ │:3200 │ │ :9292 │ │
└───────┬────────┘ └──────┘ └────┬─────┘ │
│ Traces │ scrape │
▼ ▼ │
┌────────────────────────────────────┐ │
│ OpenSearch :9200 │ │
│ índices: traces / logs / métricas │ │
└────────────────────────────────────┘ │
▲ │
│ logs (docker) │
┌──────────────┐ │
│ Fluent Bit │◄── todos os containers │
│ :24224 │ │
└──────────────┘ │
│
┌──────────────────────────────────────┐ │
│ Grafana :3001 │ │
│ datasources: Prometheus + OpenSearch │ │
│ + Tempo │ │
└──────────────────────────────────────┘ │
| Serviço | Porta(s) no host | Descrição |
|---|---|---|
| web | 3000 |
Frontend Next.js (dashboard + CRUD de usuários) |
| api | 8088 / 9465 |
API NestJS (app em :8082 interno, métricas :9464) |
| otel-collector | 4317, 4318, 8889 |
OTel Collector (gRPC, HTTP, Prometheus scrape) |
| tempo | 3200 |
Backend de traces distribuídos (Grafana Tempo) |
| data-prepper | 21890 |
Processa traces OTLP → OpenSearch |
| opensearch | 9200, 9600 |
Motor de busca/armazenamento de observabilidade |
| opensearch-dashboards | 5601 |
UI do OpenSearch |
| prometheus | 9292 |
Banco de séries temporais de métricas |
| grafana | 3001 |
Dashboards (acesso anônimo, role Admin) |
| fluent-bit | 24224 |
Agregador de logs de todos os containers |
| postgres | 5432 |
Banco de dados da aplicação |
| cadvisor | 8080 |
Métricas de containers Docker |
| postgres-exporter | 9187 |
Métricas do PostgreSQL para o Prometheus |
api ──OTLP/gRPC──► otel-collector:4317
│
┌───────────────┬───────────────┐
▼ ▼ ▼
data-prepper Tempo:3200 OpenSearch
:21890 (Grafana)
│
▼
OpenSearch (ss4o_traces-otel-application-example-api)
api:9464 ──scrape──► Prometheus:9292 ◄──scrape── cadvisor, postgres-exporter
otel-collector:8889 ──scrape──►/
│
▼
Grafana:3001
todos os containers ──fluentd driver──► fluent-bit:24224 ──► OpenSearch (docker-logs)
api ──OTLP logs──► otel-collector ──► OpenSearch (ss4o_logs-otel-application-example)
| Pilar | Ferramenta | URL |
|---|---|---|
| Traces | Grafana Tempo | http://localhost:3200 |
| Traces | OpenSearch Dashboards | http://localhost:5601 |
| Logs | OpenSearch Dashboards | http://localhost:5601 |
| Métricas | Grafana | http://localhost:3001 |
| Métricas | Prometheus | http://localhost:9292 |
Leia mais:
docs/pilares-observabilidade.md
- Docker e Docker Compose v2+
- Node.js >= 20 e npm
- Mínimo 6 GB de RAM disponível para o Docker
git clone <repo>
cd docker-observabilidade
# 1. Configura .envs, instala dependências e cria banco de testes
./scripts/setup.sh
# 2. Sobe toda a stack de observabilidade
docker compose up -dNa primeira execução:
opensearch-initcria índices e templates necessáriosopensearch-dashboards-initimporta dashboards automaticamente- A API roda as migrations do banco de dados na inicialização
cd api
# Sobe apenas as dependências necessárias
docker compose up -d postgres otel-collector
npm run start:devdocker compose ps # status dos containers
docker compose logs -f api # logs da API em tempo real
docker compose logs -f web
docker compose down # para tudo (mantém volumes)
docker compose down -v # para tudo e remove volumesO projeto tem dois scripts em scripts/ que automatizam as tarefas mais comuns.
Prepara o ambiente local do zero:
./scripts/setup.sh| Etapa | O que faz |
|---|---|
| Pré-requisitos | Valida docker, node (≥ 20) e npm |
Arquivos .env |
Cria .env e api/.env a partir dos .env.example se não existirem |
| Dependências | Executa npm install em api/ e web/ |
| Postgres | Sobe o container via docker compose up -d postgres se necessário |
| Banco de testes | Cria o banco postgres_test se não existir |
Roda todas as suites de testes com sumário final:
./scripts/test.sh # roda tudo (API + Web)
./scripts/test.sh api # todas as suites da API
./scripts/test.sh web # só o Web
./scripts/test.sh api:unit # só unitários da API
./scripts/test.sh api:integration
./scripts/test.sh api:e2e
./scripts/test.sh api:stressRequer postgres em execução. Execute ./scripts/setup.sh antes se necessário.
Obrigatório: os arquivos
.envprecisam existir antes de subir qualquer serviço. Osetup.shcria automaticamente. Para criar manualmente:cp .env.example .env cp api/.env.example api/.env
POSTGRES_USER=postgres
POSTGRES_PASSWORD=postgres
POSTGRES_DB=observability
API_KEY=api-secret-key
OPENSEARCH_INITIAL_ADMIN_PASSWORD=ChangeMe_OpenSearch_2026!9PORT=8082
NODE_ENV=development
APP_NAME=application-example-api
OTEL_SERVICE_NAME=application-example-api
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4317
OTEL_EXPORTER_OTLP_PROTOCOL=grpc
DB_HOST=localhost
DB_PORT=5432
DB_USER=postgres
DB_PASSWORD=postgres
DB_NAME=observability
API_KEY=api-secret-keyOTEL_SERVICE_NAME=application-example-web
OTEL_EXPORTER_OTLP_ENDPOINT=http://localhost:4318
OPENSEARCH_URL=http://localhost:9200
API_URL=http://localhost:8082
NODE_OPTIONS=--max-old-space-size=1024Documentação Swagger interativa disponível em http://localhost:8088/docs.
| Método | Rota | Descrição |
|---|---|---|
GET |
/users |
Listar com paginação (?page=1&limit=10) |
GET |
/users/:id |
Buscar por UUID |
POST |
/users |
Criar usuário |
PUT |
/users/:id |
Atualizar usuário |
DELETE |
/users/:id |
Remover usuário |
| Método | Rota | Descrição |
|---|---|---|
GET |
/appointments |
Listar todos |
GET |
/appointments/:id |
Buscar por UUID |
POST |
/appointments |
Criar agendamento |
PUT |
/appointments/:id |
Atualizar agendamento |
DELETE |
/appointments/:id |
Remover agendamento |
| Método | Rota | Descrição |
|---|---|---|
GET |
/ |
Health check da API |
GET |
/health |
Health check detalhado (db, memória, disco) |
GET |
/debug/error/500 |
Força erro 500 (para testes de observabilidade) |
GET |
/debug/error/502 |
Força erro 502 (para testes de observabilidade) |
Leia mais:
docs/health-check.md·docs/domain.md
Todas as rotas (exceto /, /health e /docs) exigem o header x-api-key:
curl -H "x-api-key: api-secret-key" http://localhost:8088/usersO valor padrão é api-secret-key. Para alterar, defina API_KEY no .env.
Acesse em http://localhost:3000.
Dados consultados diretamente do OpenSearch via SSR (Next.js Server Components):
| Seção | O que mostra |
|---|---|
| KPIs | Total de requests, erros, latência média, p95, taxa de erros |
| Requests ao longo do tempo | Volume de requests por serviço |
| Latência | Percentis p50, p95, p99 ao longo do tempo |
| Status HTTP | Distribuição 2xx / 4xx / 5xx |
| Throughput por método | GET / POST / PUT / DELETE ao longo do tempo |
| Latência por rota | Top 5 rotas por latência média |
| Top Endpoints | Ranking por volume, latência avg e p95 |
| Logs por container | Volume de logs de cada container |
| Operações de agendamentos | Criações, visualizações, atualizações, remoções |
Filtros: intervalo de tempo (15m até 30d), seleção de serviço e auto-refresh configurável.
Leia mais:
docs/decisao-arquitetura-nextjs-ssr.md
CRUD completo com paginação.
./scripts/test.sh # roda tudo e exibe o sumário| Suite | Comando | Descrição | Testes |
|---|---|---|---|
| Unitários | npm test |
Serviços e guards com mocks | 71 |
| Integração | npm run test:integration |
Pipeline NestJS com banco mockado | 55 |
| E2E | npm run test:e2e |
Endpoints reais contra postgres_test |
61 |
| Stress | npm run test:stress |
Carga concorrente (50–100 req/s) | 8 |
| Suite | Comando | Descrição | Testes |
|---|---|---|---|
| Unitários | npm test |
Componentes React e server actions | 50 |
# API
cd api
npm test # unitários
npm run test:integration # integração
npm run test:e2e # e2e
npm run test:stress # stress
# Web
cd web
npm testLeia mais:
docs/testes.md
| Documento | Descrição |
|---|---|
docs/testes.md |
Estratégia de testes da API: ferramentas, camadas, mocks e como executar |
docs/domain.md |
Entidades, regras de negócio, camadas e fluxos da API e do frontend |
docs/pilares-observabilidade.md |
Conceitos dos três pilares (traces, métricas, logs), Grafana Tempo e como estão implementados |
docs/opentelemetry-config.md |
Configuração do OpenTelemetry na API e no Web: variáveis, SDK e instrumentação |
docs/health-check.md |
Endpoints de health check, indicadores verificados e integração com orquestradores |
docs/decisao-arquitetura-nextjs-ssr.md |
ADR-001: decisão de usar SSR (Server Components) para acessar o OpenSearch |
stress-test/README.md |
Guia de testes de estresse com k6 |