⚠️ Este é um projeto de Prova de Conceito (POC)
Este repositório serve como referência para implementar uma stack completa de observabilidade (métricas, logs e traces) usando OpenTelemetry, similar ao New Relic, mas com ferramentas open-source.
- Visão Geral
- Arquitetura
- Tecnologias Utilizadas
- Pré-requisitos
- Instalação e Execução
- Como Usar em Outros Projetos
- Acessando as Interfaces
- Estrutura do Projeto
- Troubleshooting
Esta POC demonstra como implementar uma stack completa de observabilidade para aplicações FastAPI, incluindo:
- ✅ Métricas (Prometheus)
- ✅ Logs Estruturados em JSON (Loki + Promtail) com correlação automática via TraceID/SpanID
- ✅ Traces Distribuídos (Tempo)
- ✅ Visualização Unificada (Grafana)
- ✅ Alertas (Alertmanager)
- ✅ Correlação entre métricas, logs e traces
- ✅ Middleware HTTP para logging automático de requisições
A stack é totalmente containerizada com Docker Compose e pronta para uso em desenvolvimento ou como base para produção.
┌─────────────────┐
│ FastAPI App │
│ (Instrumentado)│
└────────┬────────┘
│ OTLP (gRPC/HTTP)
▼
┌─────────────────┐
│ OTel Collector │◄─── Recebe telemetria
└────────┬────────┘
│
┌────┴────┬──────────┬──────────┐
▼ ▼ ▼ ▼
┌─────────┐ ┌──────┐ ┌────────┐ ┌──────────┐
│Prometheus│ │ Tempo│ │ Loki │ │ Debug │
│(Métricas)│ │(Traces)│ │ (Logs) │ │ (Log) │
└────┬────┘ └──────┘ └────┬───┘ └──────────┘
│ │
│ │
▼ ▼
┌─────────────────────────────────┐
│ Grafana │
│ (Visualização Unificada) │
└─────────────────────────────────┘
│
▼
┌─────────────────┐
│ Alertmanager │
│ (Alertas) │
└─────────────────┘
- Aplicação FastAPI envia telemetria (traces, métricas) via OTLP para o OpenTelemetry Collector
- Aplicação FastAPI gera logs estruturados em JSON (com TraceID/SpanID injetados automaticamente)
- OTel Collector processa e roteia os dados:
- Traces → Tempo
- Métricas → Prometheus (via endpoint
/metrics)
- Promtail coleta logs dos containers Docker (formato JSON) → Loki
- Grafana consome todos os dados para visualização unificada com correlação automática
- Prometheus avalia regras de alerta e envia para Alertmanager
| Componente | Tecnologia | Função |
|---|---|---|
| Aplicação | FastAPI + Python 3.14 | API REST instrumentada |
| Instrumentação | OpenTelemetry SDK | Geração de telemetria |
| Coletor | OpenTelemetry Collector | Hub central de telemetria |
| Métricas | Prometheus | Armazenamento e query de métricas |
| Logs | Loki + Promtail | Agregação e coleta de logs |
| Traces | Tempo | Armazenamento de traces distribuídos |
| Visualização | Grafana | Dashboards e correlação |
| Alertas | Alertmanager | Gerenciamento de alertas |
- Docker >= 20.10
- Docker Compose >= 2.0
- Python >= 3.14 (apenas para desenvolvimento local, não necessário para Docker)
- uv (gerenciador de pacotes Python) - instalado automaticamente no Dockerfile
O projeto utiliza um arquivo .env para configurar variáveis de ambiente de forma centralizada e segura.
Copie o arquivo de exemplo e ajuste os valores conforme necessário:
cp .env_example .env| Variável | Descrição | Valor Padrão | Valores Possíveis |
|---|---|---|---|
OTEL_SERVICE_NAME |
Nome do serviço para OpenTelemetry (aparece em traces, métricas e logs) | poc-fastapi-service |
Qualquer string |
OTEL_EXPORTER_OTLP_ENDPOINT |
Endpoint do OpenTelemetry Collector | http://otel-collector:4318 |
URL HTTP/HTTPS ou host:port |
LOG_LEVEL |
Nível de log da aplicação | INFO |
DEBUG, INFO, WARNING, ERROR, CRITICAL |
- O arquivo
.envé carregado automaticamente pelo Pydantic Settings (src/config.py) - As variáveis podem ser sobrescritas por variáveis de ambiente do sistema
- No Docker Compose, variáveis definidas em
environmenttêm prioridade sobre o.env - O arquivo
.envestá no.gitignoree não será commitado
OTEL_SERVICE_NAME=minha-aplicacao
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
LOG_LEVEL=DEBUGgit clone <seu-repositorio>
cd poc-fastapi-otelcp .env_example .env
# Edite o .env conforme necessário (opcional, valores padrão já funcionam)docker compose up --buildEste comando irá:
- Construir a imagem da aplicação FastAPI
- Iniciar todos os serviços (Prometheus, Grafana, Tempo, Loki, etc.)
- Configurar automaticamente os data sources no Grafana
Aguarde alguns segundos para todos os serviços iniciarem. Você pode verificar o status com:
docker compose ps# Endpoint raiz
curl http://localhost:8000/
# Endpoint de exemplo (simula financiamento)
curl http://localhost:8000/simular-financiamentodocker compose downPara remover também os volumes (dados persistentes):
docker compose down -vNo seu pyproject.toml ou requirements.txt, adicione:
dependencies = [
"opentelemetry-distro>=0.59b0",
"opentelemetry-sdk>=1.38.0",
"opentelemetry-exporter-otlp>=1.38.0",
"opentelemetry-instrumentation-fastapi>=0.59b0",
"opentelemetry-instrumentation-logging>=0.59b0",
"opentelemetry-instrumentation-requests>=0.59b0",
# ... suas outras dependências
]Opção A: Estrutura modular (recomendado)
Copie os módulos de configuração de src/:
config.py- Configuração centralizada de variáveis de ambiente (Pydantic Settings)logging_config.py- Configura logging estruturado em JSONotel.py- Configura OpenTelemetry (traces, métricas)middleware.py- Middleware para logging automático de requisições HTTP
No seu arquivo principal (main.py):
from fastapi import FastAPI
from config import settings # Configuração centralizada
from otel import setup_telemetry
from middleware import HTTPLoggingMiddleware
# Criar aplicação FastAPI
app = FastAPI(
title="Minha Aplicação",
description="Aplicação instrumentada com OpenTelemetry",
version="1.0.0"
)
# Instrumentar com OpenTelemetry (configura logging JSON + traces + métricas)
setup_telemetry(app)
# Adicionar middleware de logging HTTP
app.add_middleware(HTTPLoggingMiddleware)
# Seus endpoints aqui
@app.get("/")
def root():
return {"status": "ok", "service": settings.service_name}Benefícios desta estrutura:
- Logs estruturados em JSON com correlação automática via TraceID/SpanID
- Logging automático de todas requisições HTTP (método, path, status, duração, IP, user agent)
- Filtragem inteligente de health checks
- Contexto de negócio pode ser adicionado via
extradict nos logs
Opção B: Configuração inline
Se preferir tudo no mesmo arquivo, configure o OpenTelemetry antes de criar os endpoints, mas após criar a instância do FastAPI.
Opção A: Usar arquivo .env (recomendado)
- Copie o arquivo
src/config.pypara seu projeto - Crie um arquivo
.envna raiz do projeto:
OTEL_SERVICE_NAME=seu-servico-nome
OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
LOG_LEVEL=INFO- No seu
docker-compose.yml, adicioneenv_file:
services:
sua-aplicacao:
env_file:
- .env
depends_on:
- otel-collectorOpção B: Variáveis diretas no docker-compose.yml
services:
sua-aplicacao:
environment:
- OTEL_SERVICE_NAME=seu-servico-nome
- OTEL_EXPORTER_OTLP_ENDPOINT=http://otel-collector:4318
- LOG_LEVEL=INFO
depends_on:
- otel-collectorNota: O arquivo src/config.py centraliza todas as configurações usando Pydantic Settings, proporcionando type safety e validação automática.
Copie os seguintes diretórios/arquivos para seu projeto:
├── docker-compose.yml # Adicione os serviços de observabilidade
├── otel/
│ └── otel-collector-config.yml
├── prometheus/
│ ├── prometheus.yml
│ └── alerts.yml
├── tempo/
│ └── tempo.yml
├── loki/ # (opcional, se usar Loki)
├── promtail/
│ └── promtail.yml
├── alertmanager/
│ └── alertmanager.yml
└── grafana/
└── provisioning/
└── datasources/
└── datasources.yml
No docker-compose.yml, atualize o nome do serviço da sua aplicação e ajuste as dependências do otel-collector se necessário.
docker compose up --buildApós iniciar a stack, acesse:
| Serviço | URL | Credenciais | Descrição |
|---|---|---|---|
| Grafana | http://localhost:3000 | (sem login - anônimo habilitado) | Visualização unificada de métricas, logs e traces |
| Prometheus | http://localhost:9090 | - | Query de métricas e alertas |
| Tempo | http://localhost:3200 | - | API de traces (use Grafana para visualização) |
| Loki | http://localhost:3100 | - | API de logs (use Grafana para visualização) |
| Alertmanager | http://localhost:9093 | - | Gerenciamento de alertas |
| FastAPI App | http://localhost:8000 | - | Aplicação principal |
| FastAPI Docs | http://localhost:8000/docs | - | Documentação Swagger |
-
Explorar Métricas:
- Vá em Explore → Selecione Prometheus
- Digite queries como:
http_server_duration_milliseconds_count
-
Explorar Logs:
- Vá em Explore → Selecione Loki
- Use queries como:
{service="app-fastapi"}ou{container="poc-fastapi-otel-app-fastapi-1"} - Filtre por nível:
{container="..."} |= "level":"ERROR" - Busque por trace_id:
{container="..."} |= "trace_id":"abc123..." - Os logs são estruturados em JSON, facilitando queries e correlação com traces
-
Explorar Traces:
- Vá em Explore → Selecione Tempo
- Use busca simples:
{ service.name = "poc-fastapi-service" } - Ou cole um TraceID diretamente
-
Correlação:
- Ao visualizar um trace, você pode clicar em spans para ver logs e métricas relacionados
- Os data sources estão configurados para correlação automática
poc-fastapi-otel/
├── src/
│ ├── __init__.py
│ ├── main.py # Aplicação FastAPI com endpoints
│ ├── config.py # Configuração centralizada (Pydantic Settings)
│ ├── otel.py # Configuração OpenTelemetry
│ ├── logging_config.py # Configuração de logging estruturado em JSON
│ └── middleware.py # Middleware HTTP para logging automático
├── .env_example # Template de variáveis de ambiente
├── .env # Variáveis de ambiente (não commitado)
├── otel/
│ └── otel-collector-config.yml # Configuração do OTel Collector
├── prometheus/
│ ├── prometheus.yml # Configuração do Prometheus
│ └── alerts.yml # Regras de alertas
├── tempo/
│ └── tempo.yml # Configuração do Tempo
├── promtail/
│ └── promtail.yml # Configuração do Promtail (coleta logs)
├── alertmanager/
│ └── alertmanager.yml # Configuração do Alertmanager
├── grafana/
│ └── provisioning/
│ └── datasources/
│ └── datasources.yml # Data sources automáticos do Grafana
├── docker-compose.yml # Orquestração de todos os serviços
├── Dockerfile # Build da aplicação FastAPI
├── pyproject.toml # Dependências Python
└── README.md # Esta documentação
Estrutura Modular:
src/config.py: Configuração centralizada de variáveis de ambiente usando Pydantic Settingssrc/otel.py: Configuração OpenTelemetry isolada e reutilizávelsrc/logging_config.py: Formatter JSON customizado com suporte a TraceID/SpanIDsrc/middleware.py: Middleware para logging automático de requisições HTTPsrc/main.py: Aplicação FastAPI focada apenas em endpoints
Causa: O Grafana está tentando executar queries de métricas de traces que ainda não foram geradas.
Solução:
- Use busca simples de traces no Grafana (deixe o campo vazio ou use
{ service.name = "seu-servico" }) - Aguarde 2-3 minutos após gerar traces para o
metrics_generatordo Tempo processar - Faça algumas requisições à aplicação para gerar mais dados:
for i in {1..10}; do curl http://localhost:8000/simular-financiamento; done
Verificações:
- Verifique se o OTel Collector está recebendo dados:
docker compose logs otel-collector | grep -i "traces"
- Verifique se o Tempo está rodando:
docker compose ps tempo curl http://localhost:3200/ready
- Verifique se há traces no Tempo:
curl "http://localhost:3200/api/search?limit=10"
Verificações:
- Verifique se o Prometheus está coletando do OTel Collector:
curl http://localhost:9090/api/v1/targets
- Verifique se o endpoint de métricas do Collector está acessível:
curl http://localhost:8889/metrics
- No Prometheus UI, vá em Status → Targets e verifique se
otel-collectorestá UP
Verificações:
- Verifique se o Promtail está rodando:
docker compose ps promtail
- Verifique os logs do Promtail:
docker compose logs promtail
- Verifique se os logs da aplicação estão em formato JSON:
Você deve ver logs em formato JSON com campos como
docker compose logs app-fastapi --tail 5
trace_id,span_id,http, etc. - No Grafana, use queries como:
{container="poc-fastapi-otel-app-fastapi-1"}{container="..."} |= "level":"ERROR"(filtrar por nível){container="..."} |= "trace_id":"abc123"(buscar por trace_id)
Causa: A aplicação não consegue conectar ao OTel Collector.
Solução:
- Verifique se o
otel-collectorestá rodando:docker compose ps otel-collector
- Verifique se a variável
OTEL_EXPORTER_OTLP_ENDPOINTestá correta nodocker-compose.yml - Verifique se a aplicação está no mesmo network Docker que o collector (usando
depends_on)
Causa: O collector não está configurado para SSL.
Solução: Certifique-se de que insecure=True está configurado nos exporters (já está no código desta POC).
- Documentação OpenTelemetry
- Documentação Prometheus
- Documentação Grafana
- Documentação Tempo
- Documentação Loki
-
⚠️ Esta é uma POC para desenvolvimento. Para produção, considere:- Configurar autenticação no Grafana
- Habilitar SSL/TLS entre componentes
- Configurar retenção de dados adequada
- Implementar backup dos dados
- Configurar notificações reais no Alertmanager (email, Slack, etc.)
- Ajustar nível de log via variável
LOG_LEVEL(DEBUG, INFO, WARNING, ERROR)
-
🔒 Segurança: O modo anônimo do Grafana está habilitado apenas para facilitar testes. Desabilite em produção.
-
💾 Persistência: Os dados são armazenados em volumes Docker. Use
docker compose down -vcom cuidado (remove todos os dados). -
📝 Logs Estruturados: Os logs são gerados em formato JSON com:
- Correlação automática via
trace_idespan_id(injetados pelo OpenTelemetry) - Informações HTTP automáticas (método, path, status, duração, IP, user agent)
- Contexto de negócio via
extradict - Filtragem automática de health checks (
/,/health,/docs, etc.)
- Correlação automática via
Este é um projeto de referência. Sinta-se livre para adaptar e melhorar conforme suas necessidades!
Este projeto é uma POC de referência e pode ser usado livremente como base para outros projetos.