1. Retomando: de uma métrica a um conjunto completo
No artigo anterior, a mini aplicação em Python expunha uma única métrica — uma contagem de requisições. Na prática, uma aplicação real quer responder perguntas de negócio mais específicas: quantos pedidos foram criados? Quanto tempo cada requisição levou? Quantas conexões estão abertas agora? Cada uma dessas perguntas pede um tipo diferente de métrica. Este artigo cobre os três tipos que cobrem praticamente todo caso de uso — counter, gauge e histogram — com uma segunda mini aplicação, desta vez em PHP puro, expondo métricas de negócio.
2. Counter: só sobe (até o processo reiniciar)
Um counter é um valor que só aumenta (ou zera, se o processo reinicia). É o tipo certo para "quantas vezes algo aconteceu": número de requisições, número de erros, número de pedidos criados. A mini app do artigo anterior já usava um counter (app_requests_total).
O sufixo _total no nome é uma convenção do Prometheus para deixar explícito que a métrica é um counter cumulativo, não um valor instantâneo — vale seguir essa convenção mesmo implementando o texto à mão.
# HELP orders_created_total Total de pedidos criados
# TYPE orders_created_total counter
orders_created_total 187
3. Gauge: sobe e desce livremente
Um gauge representa um valor que pode aumentar ou diminuir a qualquer momento — é o tipo certo para "quanto existe agora": número de conexões abertas, itens numa fila, memória em uso, temperatura. Diferente do counter, não existe uma direção esperada.
# HELP orders_queue_size Numero de pedidos aguardando processamento
# TYPE orders_queue_size gauge
orders_queue_size 4
4. Histogram: distribuição de valores em buckets
Um histogram captura a distribuição de uma medida contínua — o caso mais comum é tempo de resposta. Em vez de guardar cada valor individual (inviável em alta escala) ou só uma média (que esconde outliers), um histogram conta quantas observações caíram dentro de faixas pré-definidas, chamadas buckets.
# HELP orders_duration_seconds Tempo de processamento de um pedido
# TYPE orders_duration_seconds histogram
orders_duration_seconds_bucket{le="0.1"} 120
orders_duration_seconds_bucket{le="0.5"} 180
orders_duration_seconds_bucket{le="1"} 195
orders_duration_seconds_bucket{le="+Inf"} 200
orders_duration_seconds_sum 42.7
orders_duration_seconds_count 200
Cada linha _bucket{le="X"} é cumulativa: "quantas observações foram menores ou iguais a X segundos". _sum é a soma de todos os valores observados, e _count é o total de observações (igual ao último bucket, +Inf). Com essas peças, o Prometheus consegue calcular percentis aproximados (p50, p95, p99) em tempo de consulta, via histogram_quantile — sem que a aplicação precise calcular percentil nenhum sozinha.
5. Mini app em PHP puro com métricas de negócio
Sem nenhum framework, usando apenas o servidor embutido do PHP (php -S), uma aplicação que simula processamento de pedidos e expõe as três métricas vistas acima:
<?php
// app.php
$stateFile = __DIR__ . '/metrics_state.json';
function readState($file) {
if (!file_exists($file)) {
return ['requests_total' => 0, 'queue_size' => 0, 'durations' => []];
}
return json_decode(file_get_contents($file), true);
}
function writeState($file, $state) {
file_put_contents($file, json_encode($state));
}
$state = readState($stateFile);
if ($_SERVER['REQUEST_URI'] === '/metrics') {
$buckets = [0.1, 0.5, 1.0];
$durations = $state['durations'];
$sum = array_sum($durations);
$count = count($durations);
header('Content-Type: text/plain; version=0.0.4');
echo "# HELP orders_created_total Total de pedidos criados\n";
echo "# TYPE orders_created_total counter\n";
echo "orders_created_total {$state['requests_total']}\n";
echo "# HELP orders_queue_size Numero de pedidos aguardando processamento\n";
echo "# TYPE orders_queue_size gauge\n";
echo "orders_queue_size {$state['queue_size']}\n";
echo "# HELP orders_duration_seconds Tempo de processamento de um pedido\n";
echo "# TYPE orders_duration_seconds histogram\n";
$cumulative = 0;
foreach ($buckets as $le) {
$cumulative = count(array_filter($durations, fn($d) => $d <= $le));
echo "orders_duration_seconds_bucket{le=\"{$le}\"} {$cumulative}\n";
}
echo "orders_duration_seconds_bucket{le=\"+Inf\"} {$count}\n";
echo "orders_duration_seconds_sum {$sum}\n";
echo "orders_duration_seconds_count {$count}\n";
exit;
}
// Simula o processamento de um novo pedido
$start = microtime(true);
$state['queue_size']++;
usleep(random_int(20_000, 400_000)); // simula trabalho real, 20-400ms
$state['queue_size']--;
$state['requests_total']++;
$state['durations'][] = round(microtime(true) - $start, 3);
writeState($stateFile, $state);
header('Content-Type: text/plain');
echo "pedido processado\n";
Subindo com o servidor embutido do PHP:
php -S 0.0.0.0:8001 app.php
Gerando alguns pedidos e conferindo as métricas:
for i in $(seq 1 10); do curl -s http://localhost:8001/ > /dev/null; done
curl http://localhost:8001/metrics
O estado é persistido em um arquivo JSON local só para manter o exemplo simples e sem dependências — em uma aplicação real, esses contadores normalmente vivem em memória do próprio processo (e cada worker/processo exporia os seus, deixando a agregação entre réplicas por conta do Prometheus).
6. Adicionando a app PHP à stack
# docker-compose.yml (trecho adicionado)
services:
php-app:
image: php:8.3-cli
working_dir: /app
volumes:
- ./app.php:/app/app.php
command: ["php", "-S", "0.0.0.0:8001", "app.php"]
ports:
- "8001:8001"
# prometheus.yml (job adicionado)
- job_name: "php-app"
static_configs:
- targets: ["php-app:8001"]
7. Consultando um histogram com histogram_quantile
Com dados fluindo, a consulta mais útil sobre um histogram no PromQL é o percentil de latência:
# p95 de tempo de processamento nos ultimos 5 minutos
histogram_quantile(0.95, rate(orders_duration_seconds_bucket[5m]))
# tamanho atual da fila
orders_queue_size
# taxa de pedidos criados por segundo
rate(orders_created_total[1m])
histogram_quantile reconstrói o percentil aproximado a partir da distribuição por buckets — quanto mais granulares os buckets ao redor do percentil de interesse, mais precisa a estimativa. É uma aproximação, não um cálculo exato sobre os valores individuais (que o Prometheus nunca armazena um a um), mas suficiente para a grande maioria dos casos de uso de observação de latência em produção.
8. Conclusão e próximos passos
Cobrimos os três tipos fundamentais de métrica — counter para contagens cumulativas, gauge para valores que sobem e descem, histogram para distribuições como latência — e construímos uma segunda mini aplicação, agora em PHP puro, expondo métricas de negócio reais. Com duas aplicações diferentes já enviando métricas para o Prometheus, o próximo artigo muda de pilar: como enviar logs dessas mesmas aplicações para o Loki, e por que o modelo de indexação dele é tão diferente do Prometheus.
Imagem de capa: Logo oficial do Prometheus — repositório prometheus/prometheus, licença Apache 2.0 (convertido para PNG via wsrv.nl)
Referências:
Top comments (0)