Fazer deploy ↗
docs

Métricas customizadas

Exponha as métricas do seu aplicativo em formato Prometheus e visualize na Veloz.

A Veloz já coleta tráfego, CPU, memória e rede de todos os serviços. Métricas customizadas são as que só o seu código conhece: pedidos criados, mensagens na fila, tempo de processamento de um job.

Como funciona

Seu aplicativo expõe um endpoint HTTP no formato de exposição do Prometheus. A Veloz lê esse endpoint a cada 30 segundos e guarda as séries junto com as métricas de plataforma, dentro do espaço isolado da sua organização.

Você não configura endereço, credencial nem coletor. Basta declarar o endpoint no veloz.json.

O endpoint é lido pela rede interna da Veloz. Ele não fica acessível publicamente, mesmo quando a porta é diferente da porta do serviço.

Configuração

{
  "services": {
    "apps/api": {
      "id": "svc_api456",
      "name": "loja-api",
      "type": "web",
      "root": "apps/api",
      "runtime": {
        "command": "node dist/index.js",
        "port": 3000
      },
      "observability": {
        "metrics": { "port": 9090, "path": "/metrics" }
      }
    }
  }
}
Campo Padrão Descrição
enabled true false desliga a coleta sem apagar a configuração
port O valor de runtime.port Porta onde o endpoint responde
path /metrics Caminho do endpoint. Precisa começar com /

Se o seu aplicativo serve as métricas na mesma porta HTTP do serviço, omita port:

{
  "observability": {
    "metrics": {}
  }
}

Depois de editar, rode veloz deploy. A primeira coleta acontece em até 30 segundos depois de o serviço ficar pronto.

Node e TypeScript

npm install prom-client
import express from "express";
import { collectDefaultMetrics, register, Counter } from "prom-client";
 
collectDefaultMetrics();
 
export const pedidosCriados = new Counter({
  name: "pedidos_criados_total",
  help: "Total de pedidos criados",
});
 
const app = express();
 
app.get("/metrics", async (_req, res) => {
  res.set("Content-Type", register.contentType);
  res.end(await register.metrics());
});
 
app.listen(9090);

collectDefaultMetrics() adiciona métricas de processo (uso de CPU, memória, event loop). Incremente o contador onde o evento acontece:

pedidosCriados.inc();

Se você já tem um servidor Express na porta do serviço, registre a rota nele e omita metrics.port no veloz.json. Um segundo listen só é necessário quando você quer as métricas em uma porta separada.

Python

pip install prometheus-client
from prometheus_client import Counter, make_asgi_app
from fastapi import FastAPI
 
pedidos_criados = Counter("pedidos_criados_total", "Total de pedidos criados")
 
app = FastAPI()
app.mount("/metrics", make_asgi_app())

Para aplicativos sem ASGI, sirva as métricas em uma porta própria:

from prometheus_client import start_http_server
 
start_http_server(9090)

Incremente o contador com pedidos_criados.inc().

Go

go get github.com/prometheus/client_golang/prometheus/promhttp
package main
 
import (
	"net/http"
 
	"github.com/prometheus/client_golang/prometheus"
	"github.com/prometheus/client_golang/prometheus/promauto"
	"github.com/prometheus/client_golang/prometheus/promhttp"
)
 
var pedidosCriados = promauto.NewCounter(prometheus.CounterOpts{
	Name: "pedidos_criados_total",
	Help: "Total de pedidos criados",
})
 
func main() {
	http.Handle("/metrics", promhttp.Handler())
	http.ListenAndServe(":9090", nil)
}

Incremente o contador com pedidosCriados.Inc().

Importante: o endpoint precisa escutar em todas as interfaces, não apenas em 127.0.0.1. http.ListenAndServe(":9090", nil) já faz isso. Em outras linguagens, confirme que o endereço de escuta é 0.0.0.0 e não localhost.

Onde ver os dados

No painel, a aba Métricas do serviço traz a seção "Métricas do aplicativo", com um seletor das suas métricas e um gráfico. O seletor Taxa / Valor decide se a série é derivada no tempo: contadores (_total, _count) fazem mais sentido como taxa, gauges como valor.

Pelo terminal:

# Listar as métricas recebidas
veloz metrics list
 
# Consultar uma métrica sua
veloz metrics query 'rate(pedidos_criados_total[5m]) * 60' --start 1h
 
# Estado da coleta
veloz obs status

A sintaxe de consulta é MetricsQL, compatível com PromQL. Veja veloz metrics query-help para a referência completa.

Cardinalidade

Cardinalidade é a quantidade de séries distintas que uma métrica gera. Cada combinação de rótulos é uma série. É o único limite de métricas que costuma ser atingido por acidente, e a causa é sempre a mesma: um rótulo que carrega um valor único por requisição.

Nunca use como rótulo:

  • Identificador de usuário, de sessão ou de requisição
  • URL completa, incluindo query string
  • Endereço de rede, timestamp ou mensagem de erro

Use o molde da rota, não a rota concreta:

// Errado: uma série nova por pedido, sem limite
requisicoes.inc({ rota: "/pedidos/8213" });
 
// Certo: uma série por molde de rota
requisicoes.inc({ rota: "/pedidos/:id" });

Regra prática: um rótulo só entra se você consegue listar todos os valores possíveis. status (200, 404, 500) entra. user_id não.

Se você precisa do valor único para investigar um caso, ele pertence aos logs ou ao rastreamento, não a um rótulo de métrica.

Limites

Limite Valor Observação
Séries ativas por serviço 10.000 O aviso de cardinalidade aparece a partir de 80%
Intervalo de coleta 30 segundos Fixo, não configurável
Tempo limite da coleta 10 segundos Acima disso o diagnóstico é "A coleta expirou"

Respostas muito grandes também são recusadas pela coleta, e a causa é sempre cardinalidade. O painel avisa a partir de 80% do limite de séries, o que dá tempo de sobra para remover o rótulo culpado antes de chegar lá.

Próximos passos