El cliente Prometheus expone métricas en un formato que el servidor recolecta. Una métrica útil responde una pregunta operativa, como tasa de errores o duración, sin incluir datos personales.

Prometheus utiliza normalmente un modelo pull: en intervalos configurados solicita un endpoint HTTP y registra una muestra de cada serie. El nombre de la métrica más el conjunto completo de labels identifica una serie. Cambiar cualquier valor crea otra serie. Esta propiedad permite consultas expresivas, pero también explica por qué debes diseñar la cardinalidad antes de publicar la instrumentación.

from prometheus_client import Counter, Histogram

PETICIONES = Counter(
    "app_peticiones_total", "Total de peticiones", ["metodo", "resultado"]
)
DURACION = Histogram(
    "app_peticion_duracion_segundos", "Duración", ["ruta"]
)


def procesar() -> None:
    with DURACION.labels(ruta="/pedidos").time():
        ejecutar()
    PETICIONES.labels(metodo="POST", resultado="exito").inc()

Counter registra eventos acumulados, Gauge representa valores actuales e Histogram distribuye observaciones en buckets. Elige buckets acordes con latencias reales.

Un Counter representa eventos acumulativos, como peticiones o fallos. El cliente expone el sufijo _total cuando corresponde. No lo uses para un valor que disminuye. Un Gauge sirve para trabajos activos, temperatura o profundidad actual de una cola, aunque su agregación entre réplicas puede ser engañosa si el significado no está claro.

Un Histogram mantiene conteos acumulativos por límite, además de suma y cantidad de observaciones. PromQL puede calcular cuantiles y agregar instancias. Un Summary calcula estadísticas en el cliente; sus cuantiles de distintas instancias no se combinan igual. Para latencia distribuida, Histogram suele ser más flexible.

Diseñar la métrica desde la pregunta

Empieza por la pregunta operativa y la consulta que la responderá. Una tasa de errores HTTP necesita un counter agrupado por un resultado pequeño o familia de estados. La latencia necesita un histogram con límites alrededor del objetivo del servicio. El atraso de una cola puede usar un gauge actual, mientras counters de entradas y salidas explican su evolución.

Los nombres deben incluir unidad y tipo claros:

  • _seconds para duración en segundos;
  • _bytes para tamaño;
  • _total para contadores;
  • un prefijo de aplicación o subsistema para evitar colisiones.

No codifiques labels en nombres como pedidos_post_exito_total si una dimensión pequeña y útil las modela mejor. Tampoco añadas labels que nunca aparecerán en consultas o alertas. Cada dimensión multiplica las series posibles.

Elegir buckets alrededor del objetivo

Los buckets predeterminados no encajan con todos los servicios. Si un endpoint debe responder en 300 ms, incluye límites alrededor de ese valor y cubre la cola esperada:

from prometheus_client import Histogram

LATENCIA = Histogram(
    "checkout_duracion_segundos",
    "Duración del checkout",
    ["resultado"],
    buckets=(0.05, 0.1, 0.2, 0.3, 0.5, 1.0, 2.0, 5.0),
)

Demasiados buckets multiplican series; muy pocos ocultan la distribución. Analiza datos reales y ajusta mediante un cambio planificado. Modificar límites interrumpe la continuidad lógica de las series, así que coordina dashboards y reglas.

Para medir la fracción por debajo de 300 ms, divide la tasa del bucket le="0.3" por la tasa de _count. Para percentiles aproximados, histogram_quantile opera sobre tasas de buckets. La resolución depende de los límites porque el servidor interpola y no conserva valores individuales.

Exponer el endpoint con seguridad

El paquete ofrece start_http_server para scripts y workers sencillos:

from prometheus_client import start_http_server

start_http_server(8000, addr="127.0.0.1")

Las aplicaciones web deberían usar la integración de su servidor WSGI o ASGI y exponer un único /metrics. No inicies un listener adicional en cada worker sin entender el modo multiprocess. Restringe la interfaz y permite solo al scraper o a la red de monitorización. Un proxy o service mesh puede aportar TLS y autenticación según la infraestructura.

No hagas público el endpoint por comodidad. Incluso sin credenciales, las métricas revelan rutas, dependencias y patrones de tráfico. Nunca incluyas secrets en labels o descripciones y evita que parámetros de una petición se conviertan en nombres.

Considerar procesos y workers

En un proceso único, el registry predeterminado reúne métricas de aplicación y runtime. En un servidor multiproceso cada worker tiene memoria independiente. Consultar solo uno o sumar valores sin criterio produce datos incompletos. El modo multiprocess del cliente guarda estado en archivos de un directorio compartido y requiere integración con el ciclo del servidor.

Lee la documentación antes de habilitarlo: configura el directorio antes de importar la aplicación, límpialo al iniciar el despliegue y marca procesos muertos mediante los hooks del servidor. No lo compartas entre instancias distintas. Algunas métricas y funciones tienen limitaciones. Si la arquitectura lo permite, procesos de un worker recolectados individualmente pueden ser más simples.

Los jobs muy cortos desaparecen antes del scrape. Pushgateway está destinado a una clase restringida de procesos batch a nivel de servicio. No sustituye de forma general al modelo pull ni debería recibir una serie única por ejecución. Agrupa por la identidad estable del job y permite que refleje su último resultado significativo.

Limitar labels y cardinalidad

Las labels deben tener pocos valores previsibles. No uses URL completa, mensaje de error, correo, token o ID. Normaliza rutas como /pedidos/{id}. Protege el endpoint porque nombres y tráfico son información operativa.

Estima el máximo antes de publicar: métodos × rutas × resultados × réplicas × buckets. Diez rutas, cuatro resultados, cinco réplicas y diez buckets ya producen cientos de series para un instrumento. Los identificadores de usuario y errores libres hacen que el conjunto sea prácticamente ilimitado.

Inicializa combinaciones previstas cuando una serie ausente pueda confundir una alerta. Un counter con labels no existe hasta observar el valor. Crear un conjunto pequeño como resultado="exito" y resultado="error" hace explícito el cero. No inicialices combinaciones grandes.

Evita repetir labels de infraestructura que Prometheus ya asigna al target, como host o entorno, salvo necesidad concreta. Las dimensiones estáticas del despliegue suelen pertenecer a la configuración de scrape o al descubrimiento de servicios.

Probar el comportamiento de la instrumentación

Usa un CollectorRegistry aislado para no mezclar coletores globales:

from prometheus_client import CollectorRegistry, Counter, generate_latest

registry = CollectorRegistry()
eventos = Counter("test_eventos_total", "Eventos", registry=registry)
eventos.inc()

texto = generate_latest(registry).decode("utf-8")
assert "test_eventos_total 1.0" in texto

Prueba el comportamiento, no solo la existencia del nombre. Confirma que éxito y fallo incrementan exactamente una vez, que el temporizador termina ante excepciones y que las labels pertenecen al conjunto permitido. Una prueba del endpoint también debería comprobar content type y política de acceso.

Revisa dónde empieza y termina la instrumentación. Incrementar antes de completar una operación puede contar éxito tras una excepción. Medir solo una llamada interna puede omitir espera relevante. Explica el límite medido en la descripción y mantén el código coherente.

Combina métricas con traces de OpenTelemetry y logs estructurados.

La documentación oficial del cliente Prometheus y las prácticas oficiales para nombres de métricas, consultadas el 22 de julio de 2026, cubren tipos, exportación, integraciones y convenciones. La cardinalidad es la principal restricción de diseño.