Pular para o conteúdo principal

Prometheus

Definição

Prometheus é um toolkit open source de monitoramento e alertas de sistemas originalmente construído no SoundCloud e agora um projeto graduado da CNCF. Ele armazena todos os dados como séries temporais: fluxos de valores de ponto flutuante com timestamp identificados por um nome de métrica e um conjunto de labels de chave-valor. Esse modelo é perfeitamente adequado para dados operacionais — uso de CPU, contagens de requisições, taxas de erro — e para sinais específicos de ML, como latência de previsão, throughput e distribuições de valores de features ao longo do tempo.

A escolha arquitetural definidora do Prometheus é seu modelo de scraping pull-based. Em vez de exigir que aplicações instrumentadas enviem métricas para um coletor central, o Prometheus periodicamente faz scraping de endpoints HTTP (por padrão /metrics) expostos pelos alvos. Essa inversão de controle torna a descoberta de serviços, o controle de acesso e a depuração significativamente mais simples: você pode fazer curl no endpoint de métricas de qualquer alvo diretamente para ver o que o Prometheus coletará. Os alvos são descobertos via configuração estática ou descoberta dinâmica de serviços (Kubernetes, Consul, EC2, etc.).

O Prometheus não é uma solução de armazenamento de longo prazo por design. Seu banco de dados de séries temporais local (TSDB) é otimizado para ingestão rápida e consulta de dados recentes, tipicamente retendo 15 dias. Para armazenamento de longo prazo, o Prometheus pode fazer remote-write para sistemas como Thanos, Cortex ou VictoriaMetrics. Em contextos de ML, o Prometheus é a camada de coleta e alertas; o Grafana fornece a camada de visualização e dashboards por cima.

Como funciona

Instrumentação de alvos

As aplicações expõem métricas via um endpoint HTTP /metrics no formato de exposição do Prometheus — um formato de texto simples de linhas nome_metrica{label="valor"} valor_numerico timestamp. Em Python, a biblioteca prometheus_client fornece os tipos Counter, Gauge, Histogram e Summary que lidam com o formato de exposição automaticamente. Um processo de serviço de ML tipicamente expõe contadores para o total de requisições de previsão, histogramas para latência de requisições e gauges para versões de modelos atualmente carregadas e utilização de recursos.

Scraping e armazenamento

O Prometheus avalia seu arquivo de configuração para determinar quais alvos fazer scraping e em qual intervalo (padrão: 15 segundos). Em cada scraping, ele busca o endpoint /metrics, analisa o formato de exposição e grava as amostras em seu TSDB local em blocos comprimidos. O TSDB usa um write-ahead log (WAL) para durabilidade e compacta dados em blocos ao longo do tempo. A cardinalidade de labels é a principal alavanca de desempenho: cada combinação única de valores de label cria uma série temporal separada, então labels ilimitadas (por exemplo, IDs de usuários) devem ser evitadas.

Consultas PromQL e alertas

PromQL (Prometheus Query Language) é uma linguagem de consulta funcional para selecionar e agregar dados de séries temporais. Vetores instantâneos selecionam o valor atual de um conjunto de séries; vetores de intervalo selecionam uma janela de amostras; funções calculam taxas, médias, quantis e previsões sobre esses vetores. As regras de alerta são expressões PromQL avaliadas em um intervalo configurável; quando uma expressão retorna um resultado não vazio, o alerta dispara e é enviado ao Alertmanager.

Alertmanager

O Alertmanager recebe alertas do Prometheus (e outras fontes), os deduplica, aplica regras de agrupamento e roteamento e despacha notificações para receptores (PagerDuty, Slack, email, webhooks). Silêncios e regras de inibição previnem tempestades de alertas durante janelas de manutenção conhecidas ou falhas em cascata. Em sistemas de ML, o Alertmanager roteia alertas de degradação de modelos para o canal Slack da equipe de ML enquanto alertas de infraestrutura (CPU alta, OOM kills) vão para a equipe de plataforma.

Armazenamento remoto e federação

Para cenários multi-cluster ou de longa retenção, o Prometheus faz remote-write de amostras para um backend durável. A federação permite que um Prometheus global faça scraping de métricas agregadas de instâncias regionais do Prometheus. Ambos os padrões são comuns em grandes plataformas de ML onde clusters de treinamento e clusters de serviço cada um executa seu próprio Prometheus, e uma instância central agrega métricas de nível de serviço.

Quando usar / Quando NÃO usar

Usar quandoEvitar quando
Você precisa de métricas operacionais para infraestrutura de serviço de ML (latência, throughput, taxa de erro)Você precisa armazenar logs de previsões brutos ou dados de eventos de alta cardinalidade
Você quer uma stack de monitoramento pull-based e auto-hospedada sem lock-in de fornecedorSua equipe não tem experiência de infraestrutura para operar e ajustar uma stack do Prometheus
Você está rodando no Kubernetes e quer descoberta de serviços nativaVocê precisa de retenção de longo prazo (>15 dias) sem configuração adicional de armazenamento remoto
Você precisa de alertas poderosos com deduplicação e roteamento via AlertmanagerVocê precisa de intervalos de scraping abaixo de um segundo; o Prometheus é projetado para intervalos de 10 a 60 segundos
Você quer um backend padrão para dashboards do GrafanaSua aplicação gera cardinalidade de label ilimitada, o que degradará o desempenho do TSDB

Comparações

O Prometheus e o Grafana são complementares, não ferramentas concorrentes. A tabela abaixo descreve quando usá-los juntos versus alternativas.

CritérioPrometheusGrafana
PapelColetar, armazenar e alertar sobre métricasVisualizar e explorar métricas de qualquer fonte de dados
Linguagem de consultaPromQL (linguagem funcional otimizada para métricas)Por fonte de dados (PromQL para Prometheus, SQL para outros)
AlertasRegras de alerta integradas + AlertmanagerGrafana Alerting (unificado, multi-fontes de dados)
Fontes de dadosApenas si mesmo (TSDB)Prometheus, InfluxDB, Loki, Elasticsearch, bancos de dados, etc.
ArmazenamentoTSDB local, remote-write para longo prazoSem armazenamento — puramente uma camada de consulta e visualização
Quando usar juntosSempre — o Prometheus coleta, o Grafana exibeSempre — use o Grafana como interface para os dados do Prometheus

Vantagens e desvantagens

AspectoVantagensDesvantagens
Arquitetura pull-basedDepuração simples, controle de acesso no nível do alvoRequer que os alvos exponham endpoints HTTP
PromQLExpressivo, composável, projetado especificamente para métricasCurva de aprendizado íngreme em comparação com SQL
TSDB localIngestão rápida e consulta para dados recentesRetenção limitada; precisa de armazenamento remoto para longo prazo
Modelo de labelsFiltragem e agregação multidimensional flexíveisLabels de alta cardinalidade causam problemas de memória e desempenho de consulta
AlertmanagerRoteamento, agrupamento e silenciamento avançadosComponente separado para operar; a configuração pode se tornar complexa
EcossistemaEnorme biblioteca de exporters e bibliotecas clienteSobrecarga operacional para implantações auto-hospedadas

Exemplos de código

# ml_metrics_server.py
# Exposes ML model metrics via prometheus_client for Prometheus scraping.
# Run: pip install prometheus_client flask scikit-learn numpy
# Then configure Prometheus to scrape localhost:8000

import time
import threading
import random
import numpy as np
from prometheus_client import (
Counter,
Histogram,
Gauge,
start_http_server,
REGISTRY,
)
from sklearn.datasets import load_iris
from sklearn.ensemble import RandomForestClassifier

# --- Define metrics ---

PREDICTION_COUNTER = Counter(
"ml_predictions_total",
"Total number of prediction requests",
["model_name", "model_version", "status"], # labels
)

PREDICTION_LATENCY = Histogram(
"ml_prediction_latency_seconds",
"Prediction request latency in seconds",
["model_name", "model_version"],
buckets=[0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5],
)

MODEL_CONFIDENCE = Histogram(
"ml_prediction_confidence",
"Distribution of model prediction confidence scores",
["model_name", "model_version"],
buckets=[0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0],
)

ACTIVE_MODEL_VERSION = Gauge(
"ml_active_model_version",
"Currently active model version (encoded as numeric)",
["model_name"],
)

DATA_DRIFT_SCORE = Gauge(
"ml_data_drift_score",
"Current data drift score (PSI) for the primary feature set",
["model_name", "feature_set"],
)

# --- Load and train a simple model ---
X, y = load_iris(return_X_y=True)
clf = RandomForestClassifier(n_estimators=50, random_state=42)
clf.fit(X, y)

MODEL_NAME = "iris-classifier"
MODEL_VERSION = "1.0.0"
ACTIVE_MODEL_VERSION.labels(model_name=MODEL_NAME).set(1)

def simulate_prediction(features: np.ndarray) -> dict:
"""Run a prediction and record Prometheus metrics."""
start = time.time()
try:
proba = clf.predict_proba(features.reshape(1, -1))[0]
predicted_class = int(np.argmax(proba))
confidence = float(np.max(proba))

# Record latency and confidence
duration = time.time() - start
PREDICTION_LATENCY.labels(
model_name=MODEL_NAME, model_version=MODEL_VERSION
).observe(duration)
MODEL_CONFIDENCE.labels(
model_name=MODEL_NAME, model_version=MODEL_VERSION
).observe(confidence)
PREDICTION_COUNTER.labels(
model_name=MODEL_NAME,
model_version=MODEL_VERSION,
status="success",
).inc()

return {"class": predicted_class, "confidence": confidence}
except Exception as exc:
PREDICTION_COUNTER.labels(
model_name=MODEL_NAME,
model_version=MODEL_VERSION,
status="error",
).inc()
raise exc

def simulate_drift_monitoring():
"""Periodically update a synthetic drift score gauge."""
while True:
# In production this would run a real PSI/KS test
drift_score = random.uniform(0.01, 0.35)
DATA_DRIFT_SCORE.labels(
model_name=MODEL_NAME, feature_set="sepal"
).set(drift_score)
time.sleep(30)

def simulate_traffic():
"""Generate synthetic prediction traffic for demonstration."""
samples = X[np.random.choice(len(X), size=10)]
for sample in samples:
simulate_prediction(sample)
time.sleep(random.uniform(0.05, 0.3))

if __name__ == "__main__":
# Start Prometheus metrics HTTP server on port 8000
start_http_server(8000)
print("Prometheus metrics server running on http://localhost:8000/metrics")
print("Configure Prometheus to scrape this endpoint.")

# Start background drift monitor
drift_thread = threading.Thread(target=simulate_drift_monitoring, daemon=True)
drift_thread.start()

# Simulate continuous prediction traffic
print("Simulating prediction traffic...")
while True:
simulate_traffic()
time.sleep(1)

Recursos práticos

Veja também