Monitoramento — Observabilidade Full-Stack com Prometheus + Grafana
Monitoramento é como o painel de um carro—o velocímetro (QPS), temperatura do óleo (latência) e luz do motor (taxa de erro) mantêm você informado sobre a saúde do carro (sistema) a todo momento. Sem um painel, você só saberia que algo estava errado quando a fumaça começasse a sair do motor.
1. O Que Você Vai Aprender
- Exposição de Métricas Prometheus: Integração com
prometheus-fastapi-instrumentator - Métricas de negócio personalizadas: taxa de atualização de preços, percentil de latência da API, número de usuários ativos
- Design de Dashboard Grafana: Volume de Requisições/Latência/Taxa de Erro (Método RED) + Métricas de Negócio
- Regras de Alerta: latência P99 excede limite, pico na taxa de erro, queda na taxa de hit do cache Redis
- Cenário Alice: Dashboard de Monitoramento do PriceTracker do Charlie
2. A História Real da Alice
(1) Dor: Você Só Percebe o Problema Quando Ele Acontece
Às 3 da manhã, o pool de conexões do banco de dados do PriceTracker se esgotou, e a API começou a retornar erros 500. Alice só descobriu às 8 da manhã, quando os usuários começaram a reclamar. Sem monitoramento em tempo real, Charlie só pôde revisar os logs depois do fato e descobriu que o pool de conexões estava disparando alertas desde as 5 da manhã—se o monitoramento estivesse em vigor, o problema poderia ter sido detectado e resolvido em cinco minutos.
(2) Solução com Prometheus e Grafana
O Prometheus coleta métricas (número de requisições, latência, taxa de erro) a cada segundo; o Grafana as visualiza em tempo real; e o AlertManager envia alertas automaticamente quando as métricas se desviam dos intervalos normais—mudando o processo de "saber dos problemas apenas após reclamações de usuários" para "notificações automáticas em 5 minutos."
(3) Resultado
Picos de latência P99 disparam um alerta em menos de um minuto; notificações automáticas são enviadas antes que o pool de conexões do banco de dados se esgote; o tempo de detecção de problemas foi reduzido de "horas" para "minutos," então Charlie não precisa mais ficar olhando para a tela 24 horas por dia.
3. Expondo Métricas Prometheus
(1) Arquitetura de Monitoramento
flowchart LR
App[FastAPI App] -->|/metrics| Prom[Prometheus]
Prom -->|Query| Grafana[Grafana Dashboard]
Prom -->|Alert| AlertMgr[AlertManager]
AlertMgr -->|Notify| Slack[Slack / Email]
Grafana -->|Visualize| Charlie[Charlie DevOps]
(1) ▶ Exemplo: Integração com prometheus-fastapi-instrumentator
# Instalar: uv add prometheus-fastapi-instrumentator
from fastapi import FastAPI
from prometheus_fastapi_instrumentator import Instrumentator
app = FastAPI()
# Adicionar métricas padrão: contagem de requisições, duração, tamanho, exceções
Instrumentator().instrument(app).expose(app)
# Agora o endpoint /metrics expõe métricas Prometheus
# Incluindo: http_requests_total, http_request_duration_seconds, etc.
Saída:
# Execução Bem-sucedida
(2) ▶ Exemplo: Métricas Personalizadas
from prometheus_client import Counter, Histogram, Gauge
from fastapi import FastAPI
app = FastAPI()
# Métricas de negócio personalizadas
PRICE_UPDATES = Counter(
"pricetracker_price_updates_total",
"Número total de atualizações de preços",
["category", "currency"],
)
REQUEST_LATENCY = Histogram(
"pricetracker_request_latency_seconds",
"Latência de requisição em segundos",
buckets=[0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0],
)
ACTIVE_USERS = Gauge(
"pricetracker_active_users",
"Número de usuários ativos nos últimos 5 minutos",
)
CACHE_HIT_RATE = Gauge(
"pricetracker_cache_hit_rate",
"Porcentagem de taxa de hit do cache Redis",
)
@app.post("/api/v1/prices")
async def create_price(price: PriceCreate):
result = await service.create_price(price)
# Registrar métrica personalizada
PRICE_UPDATES.labels(category="electronics", currency="USD").inc()
return result
Saída:
# Função definida com sucesso
(2) Métricas Chave do Método RED
| Métrica | Tipo | Descrição | PromQL |
|---|---|---|---|
| Rate | Counter | Taxa de Requisição (QPS) | rate(http_requests_total[5m]) |
| Errors | Counter | Taxa de Erro | rate(http_requests_total{status=~"5.."}[5m]) |
| Duration | Histogram | Distribuição de Latência | histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) |
4. Design do Dashboard Grafana
(1) Layout do Dashboard
graph TD
Title[Dashboard de Monitoramento PriceTracker]
Title --> Row1[Linha 1: Visão Geral]
Row1 --> QPS[QPS - Rate]
Row1 --> P50[P50 Latência]
Row1 --> P99[P99 Latência]
Row1 --> ErrRate[Taxa de Erro]
Title --> Row2[Linha 2: Negócio]
Row2 --> PriceUpd[Atualizações de Preço/min]
Row2 --> ActiveUsers[Usuários Ativos]
Row2 --> CacheHit[Taxa de Hit do Cache]
Title --> Row3[Linha 3: Infraestrutura]
Row3 --> DBConns[Conexões DB]
Row3 --> RedisConns[Conexões Redis]
Row3 --> CeleryQ[Tamanho da Fila Celery]
(1) ▶ Exemplo: Configuração JSON do Dashboard Grafana (Trecho)
{
"dashboard": {
"title": "Monitoramento PriceTracker",
"panels": [
{
"title": "Taxa de Requisição (QPS)",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m]))",
"legendFormat": "QPS Total"
}
]
},
{
"title": "Latência P99",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le))",
"legendFormat": "P99"
}
],
"thresholds": {
"steps": [
{ "value": 0, "color": "green" },
{ "value": 0.1, "color": "yellow" },
{ "value": 0.5, "color": "red" }
]
}
},
{
"title": "Taxa de Hit do Cache",
"type": "gauge",
"targets": [
{
"expr": "pricetracker_cache_hit_rate",
"legendFormat": "Taxa de Hit %"
}
]
}
]
}
}
Saída:
{
"dashboard": {
"title": "Monitoramento PriceTracker",
"panels": [
{
"title": "Taxa de Requisição (QPS)",
"type": "timeseries",
"targets": [
{
"expr": "sum(rate(http_requests_total[5m]))",
"legendFormat": "QPS Total"
}
]
},
{
"title": "Latência P99",
"type": "stat",
"targets": [
{
"expr": "histogram_quantile(0.99, sum(rate(http_request_duration_seconds_buck
5. Regras de Alerta
(1) ▶ Exemplo: Regras de Alerta do Prometheus
# prometheus/alert_rules.yml
groups:
- name: pricetracker_alerts
rules:
- alert: HighP99Latency
expr: histogram_quantile(0.99, sum(rate(http_request_duration_seconds_bucket[5m])) by (le)) > 0.5
for: 2m
labels:
severity: warning
annotations:
summary: "Latência P99 excede 500ms"
description: "Latência P99 é {{ $value }}s, limite é 0.5s"
- alert: HighErrorRate
expr: sum(rate(http_requests_total{status=~"5.."}[5m])) / sum(rate(http_requests_total[5m])) > 0.05
for: 1m
labels:
severity: critical
annotations:
summary: "Taxa de erro excede 5%"
description: "Taxa de erro é {{ $value | humanizePercentage }}"
- alert: LowCacheHitRate
expr: pricetracker_cache_hit_rate < 60
for: 5m
labels:
severity: warning
annotations:
summary: "Taxa de hit do cache abaixo de 60%"
description: "Taxa de hit atual é {{ $value }}%"
- alert: DatabaseConnectionPoolExhausted
expr: pricetracker_db_connections_in_use / pricetracker_db_connections_max > 0.9
for: 3m
labels:
severity: critical
annotations:
summary: "Pool de conexões do banco de dados > 90% utilizado"
Saída:
Configuração de monitoramento carregada
Prometheus targets: 3 ativos
Dashboard Grafana: pronto
(2) ▶ Exemplo: Adicionando Stack de Monitoramento ao Docker Compose
# Adicionar ao docker-compose.yml
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./docker/prometheus.yml:/etc/prometheus/prometheus.yml
- ./docker/alert_rules.yml:/etc/prometheus/alert_rules.yml
command:
- '--config.file=/etc/prometheus/prometheus.yml'
- '--alert.rule-files=/etc/prometheus/alert_rules.yml'
grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
environment:
- GF_SECURITY_ADMIN_PASSWORD=admin
volumes:
- grafana_data:/var/lib/grafana
alertmanager:
image: prom/alertmanager:latest
ports:
- "9093:9093"
volumes:
- ./docker/alertmanager.yml:/etc/alertmanager/alertmanager.yml
Saída:
CONTAINER ID IMAGE STATUS PORTS
abc123 nginx:latest Up 2 hours 0.0.0.0:80->80/tcp
(3) ▶ Exemplo: Configuração prometheus.yml
global:
scrape_interval: 15s
evaluation_interval: 15s
scrape_configs:
- job_name: "pricetracker-api"
metrics_path: "/metrics"
static_configs:
- targets: ["api:8000"]
rule_files:
- "alert_rules.yml"
alerting:
alertmanagers:
- static_configs:
- targets: ["alertmanager:9093"]
Saída:
A configuração entrou em vigor.
❓ Perguntas Frequentes
user_id).📖 Resumo
prometheus-fastapi-instrumentatorUma linha de código expõe métricas HTTP padrão- Customize três tipos de métricas de negócio: Counter (contagem), Histogram (distribuição de latência) e Gauge (valor atual)
- Dashboard Grafana organizado usando o método RED: Rate (QPS), Errors (taxa de erro), Duration (latência)
- Configuração de regras de alerta AlertManager: P99 > 500 ms, taxa de erro > 5%, taxa de hit do cache < 60%
- Implantação em Um Clique de Stack de Monitoramento Completa com Docker Compose: Prometheus + Grafana + AlertManager
📝 Exercícios
- Exercício Básico (Dificuldade: ⭐): Adicione
prometheus-fastapi-instrumentatorao FastAPI e verifique se o endpoint/metricsretorna as métricas HTTP padrão (como http_requests_total). Dica:Instrumentator().instrument(app).expose(app) - Exercício Avançado (Dificuldade ⭐⭐): Adicione três métricas personalizadas—PRICE_UPDATES (Counter por categoria), REQUEST_LATENCY (Histogram com buckets de percentil), e CACHE_HIT_RATE (Gauge)—e registre os valores das métricas no endpoint. Dica:
Counter(..., ["category"])+.labels(category="electronics").inc() - Desafio (Dificuldade: ⭐⭐⭐): Adicione Prometheus, Grafana e AlertManager ao Docker Compose; configure
prometheus.ymlpara coletar métricas do FastAPI; escreva duas regras de alerta—uma para P99 > 500 ms e outra para taxa de erro > 5%; e importe o dashboard no Grafana para visualizar métricas em tempo real. Dica:docker/prometheus.yml+alert_rules.yml+ configuração de fonte de dados Grafana
---|



