micrometer

Micrometer es una librería que actúa como fachada de métricas: permite instrumentar tu aplicación con métricas de forma agnóstica del sistema de monitorización. Entre los registries soportados están Prometheus, InfluxDB, Graphite, Datadog, New Relic, entre otros.

En el ecosistema Spring Boot, Micrometer se integra de manera automática (si tienes la dependencia spring-boot-starter-actuator), y expone métricas en el endpoint /actuator/metrics.
Si usas Prometheus, con spring-boot-starter-actuator y micrometer-registry-prometheus, dispondrás de un endpoint /actuator/prometheus para que Prometheus pueda recoger los datos.

Micrometer ofrece distintos tipos de métricas, cada una diseñada para monitorear un aspecto específico de la aplicación. Aquí te explico las más comunes:


1. Counter (Contador)

Un Counter es una métrica que solo se incrementa (o se reinicia al reiniciar la aplicación). Es ideal para contar eventos que ocurren en la aplicación, como el número de peticiones, errores o elementos procesados.

  • Uso típico:
    • Número de solicitudes HTTP exitosas.
    • Número de errores (excepciones).
    • Elementos procesados en una cola.
  • Ejemplo:
Counter counter = meterRegistry.counter("requests.total");
counter.increment();  // Incrementa en 1
counter.increment(5); // También puedes incrementar en N

2. Gauge (Medidor)

Un Gauge mide un valor que puede subir y bajar en el tiempo. Informa del valor actual en el momento del scrapeo por Prometheus.

  • Uso típico:
    • Tamaño de una lista o cola.
    • Número de usuarios conectados.
    • Uso de memoria o threads activos.
  • Ejemplo:
List<String> myList = new ArrayList<>();
Gauge.builder("queue.size", myList, List::size)
     .register(meterRegistry);

⚠️ Importante: un Gauge mantiene una referencia al objeto. Si el objeto es recolectado por el GC, la métrica dejará de reportarse.


3. Timer (Temporizador)

Un Timer mide la duración y la frecuencia de los eventos. Es ideal para monitorear la latencia de operaciones críticas.

  • Uso típico:
    • Tiempo de respuesta de una API.
    • Duración de consultas a base de datos.
    • Tiempo de ejecución de un método.
  • Ejemplo:
Timer timer = meterRegistry.timer("api.response.time");
timer.record(() -> someApiCall());

O bien, manualmente:

long start = System.nanoTime();
// código a medir
long duration = System.nanoTime() - start;
timer.record(duration, TimeUnit.NANOSECONDS);

En Spring Boot puedes usar anotaciones como @Timed directamente sobre métodos.


4. Distribution Summary (Resumen de Distribución)

Un DistributionSummary registra eventos numéricos y mantiene estadísticas:

  • número de veces que se registró,
  • suma total,
  • valores máximo y mínimo.

Se diferencia de un Counter porque no cuenta solo eventos, sino la distribución de sus valores asociados.

  • Uso típico:
    • Tamaño de archivos subidos.
    • Cantidad de registros procesados por lote.
    • Valor de transacciones.
  • Ejemplo:
DistributionSummary summary = meterRegistry.summary("uploaded.file.size");
summary.record(fileSize);

5. LongTaskTimer

Un LongTaskTimer es una variante de Timer para tareas de larga duración (minutos u horas). Aporta métricas como el número de tareas activas y el tiempo total acumulado.

  • Uso típico:
    • Procesos batch.
    • Importación masiva de datos.
    • Jobs asíncronos que duran varios minutos.
  • Ejemplo:
LongTaskTimer longTaskTimer = meterRegistry.more().longTaskTimer("batch.process.time");
LongTaskTimer.Sample sample = longTaskTimer.start();
try {
    // tarea larga
} finally {
    sample.stop();
}

6. Function Counter (Contador basado en función)

Un FunctionCounter es como un Counter, pero el valor no se incrementa manualmente, sino que se calcula a partir de una función evaluada en cada scrapeo.

  • Uso típico:
    • Número total de tareas procesadas, si el valor está almacenado en otra parte.
  • Ejemplo:
FunctionCounter.builder("tasks.completed", taskService, 
                        service -> service.getCompletedTasks())
               .register(meterRegistry);

7. Function Gauge (Medidor basado en función)

Similar a Gauge, pero el valor se obtiene dinámicamente a través de una función en lugar de mantener referencia a un objeto.

  • Uso típico:
    • Uso de CPU o memoria a través de una función del sistema.
    • Métricas calculadas bajo demanda.
  • Ejemplo:
FunctionGauge.builder("memory.usage", systemMonitor, 
                      monitor -> monitor.getCurrentMemoryUsage())
             .register(meterRegistry);

8. Meter (Medidor Genérico)

El Meter es la interfaz de la que derivan Timer, Counter, etc. No suele usarse directamente, salvo para crear métricas totalmente personalizadas.


Resumen

Tipo de MétricaDescripción
CounterCuenta eventos incrementales (no decrementa).
GaugeMide un valor actual que puede subir o bajar.
TimerMide duración y frecuencia de eventos.
DistributionSummaryRegistra la distribución de valores numéricos.
LongTaskTimerMide tareas largas en ejecución.
FunctionCounterContador dinámico basado en función.
FunctionGaugeMedidor dinámico basado en función.
MeterInterfaz genérica para crear métricas custom.

Alerting

Una vez que tus métricas están disponibles en Prometheus, puedes configurar reglas de alerta en el fichero prometheus.yml.

Ejemplo de alerta:

groups:
  - name: example-alerts
    rules:
      - alert: HighErrorRate
        expr: increase(http_server_requests_seconds_count{outcome="SERVER_ERROR"}[5m]) > 10
        for: 1m
        labels:
          severity: critical
        annotations:
          summary: "Alto número de errores 5xx"
          description: "Se detectaron más de 10 errores en los últimos 5 minutos."

Documentación oficial de alertas en Prometheus

por Alberto

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *