Crear Dashboard con Grafana y Prometheus para aplicaciones Java

En este manual explicaremos cómo crear un dashboard de monitorización muy básico para monitorizar aplicaciones Java usando Grafana y Prometheus. 

Damos por hecho que el lector tiene unos conocimientos básicos de las 3 tecnologías indicadas y conoce los conceptos básicos de monitorización, para centrarnos en la creación del dashboard.

Construiremos un panel básico donde monitorizaremos: el uso de CPU, la memoria, el estado del Garbage Collector, la disponibilidad y los descriptores de fichero abiertos.


Una vez lo tengamos funcionando, podremos ampliarlo con mejoras como: 
  • Alarmas automáticas que te avisen por correo en caso de problemas, algunas ideas:
    • Si usas certificados, puedes monitorizar los días que faltan para que expiren.
    • Si tu aplicación o una instancia de tu aplicación se cae.
    • Si el consumo de CPU o RAM supera ciertos límites.
    • Si los tiempos de respuesta de tu aplicación superan un tiempo razonable.
  • Métricas personalizadas para medir eventos propios de tu aplicación.
    • Número de veces que se llama a tu API.
    • Tiempos de respuesta de tu aplicación (endpoints HTTP, consultas a base de datos u otras aplicaciones.)



0 - Entorno

  • Hardware: MacBook Pro (13 pulgadas, 2019, cuatro puertos Thunderbolt 3)
  • Necesitas Prometheus y Grafana instalado en tu PC.
    • Si aún no tienes configuradas estas dos herramientas sigue nuestra guía antes de continuar.
  • Damos por hecho que ya tienes creado un DataSource en Grafana, que está conectado a métricas de tu aplicación, por lo que ahora vamos a centrarnos en crear nuestro Dashboard básico.

Decide qué métricas son importantes para ti:

Cada caso es único, pero en nuestro dashboard monitorizaremos cosas básicas que sirve para todas las aplicaciones Java:

  1. Consumo de CPU.
  2. Consumo de RAM.
  3. Comportamiento del Garbage Collector.
  4. Descriptores de fichero abiertos.
  5. Disponibilidad.
Si posteriormente necesitas ampliar tu dashboard para monitorizar 'cosas' propias de tu aplicación, Prometheus te permite exponer métricas personalizadas (por ejemplo, contadores de errores, contadores de llamadas a ciertas partes de tu programa ,etc.)

Aquí puedes ver los tipos de métricas disponibles con los que podrás jugar.


1 - Gráfica para consumo de CPU

Vamos a crear la siguiente gráfica para controlar el gasto de CPU usando la función rate:


En nuestra instancia de Prometheus, podremos buscar las métricas que Java nos da, filtrando por la keyword 'cpu':


Nosotros elegiremos la siguiente métrica:
process_cpu_seconds_total
De tal manera que la gráfica tendrá la siguiente configuración:
  • Panel Options - Title: System CPU Load (%)
  • Query - Metrics: rate(process_cpu_seconds_total[10m])
  • Standard options - Unit: Percent (0.0 - 1.0)
  • Puedes probar con varios valores para el rate: [1m],[5m],[10m] y ver cómo se renderiza mejor la gráfica, si eliges valores muy altos o bajos puede que no se vean correctamente las variaciones.
Al añadir sum(rate()) o rate() conseguimos una gráfica en la que ver cómo el porcentaje de uso de CPU crece y decrece. 

Si tenemos varias instancias de nuestra aplicación, también podremos ver el consumo de todas ellas en la misma gráfica:

Así podríamos identificar si una instancia está funcionando incorrectamente (por ejemplo en la imagen vemos una línea verde demasiado baja que puede indicar un problema en esa instancia concreta).


2 - Gráfica para consumo de RAM

Vamos a crear la siguiente gráfica para controlar el consumo de RAM (heap y no-heap):


En nuestra instancia de Prometheus, podremos buscar por la keyword 'memory':


Nosotros elegiremos la siguiente métrica:
jvm_memory_bytes_used
De tal manera que la gráfica tendrá la siguiente configuración
  • Panel Options - Title: Memory Total/Heap Used
  • Query - Metrics: jvm_memory_bytes_used
  • Standard options - Unit: bytes(SI)
  • Standard options - Max: 2200000000 (2.2 GB aprox)

Opcionalmente puedes añadir 'umbrales', que te ayudan a visualizar rápidamente por ejemplo la memoria máxima que puede consumir la aplicación antes de fallar, para pintar las zonas de diferente color:

Los límites se configuran en la sección "Thresholds":


Aunque siempre será mejor utilizar alarmas (por ejemplo que nos envíen un email superado cierto límite) para monitorizar estos problemas.


3 - Comportamiento del Garbage Collector

Vamos a crear varias gráficas para monitorizar el funcionamiento del GC.

3.1 - Duración del último GC

Con esta gráfica podremos detectar si una ejecución de GC es muy lenta, lo cual puede indicarnos un problema.


En nuestra instancia de Prometheus, podremos buscar por la keyword 'GarbageCollector' o 'gc':

Nosotros elegiremos la siguiente métrica:
java_lang_GarbageCollector_LastGcInfo_duration

De tal manera que la gráfica tendrá la siguiente configuración:
  • Panel Options - Title: Last GC duration
  • Query - Metrics: java_lang_GarbageCollector_LastGcInfo_duration


3.2 - Contador de ejecuciones de GC

Con la siguiente gráfica podremos ver si el número de veces que se ejecuta el GC por segundo. 


En nuestra instancia de Prometheus, podremos buscar por la keyword 'GarbageCollector':


Nosotros elegiremos la siguiente métrica:
rate(java_lang_GarbageCollector_CollectionCount[10m])

De tal manera que la gráfica tendrá la siguiente configuración:
  • Panel Options - Title: GC count
  • Query - Metrics: rate(java_lang_GarbageCollector_CollectionCount[10m])

Con esta gráfica puedes por ejemplo, tunear/modificar tu algoritmo de Garbage Collection y comprobar si vas a mejor o a peor.

En la siguiente imagen se ve un ejemplo de cambio a mejor, donde el número de recolecciones disminuye tras cambiar de un colector de tipo 'ParallelGC' a un 'G1GC' y aumentar un poco la RAM del proceso:


También puedes crear otras gráficas relaciones con el Garbage Collection interesantes:
  • Número de Full GCs.
  • Memoria antes y después de la recolección.

4 - Gráfica para ver descriptores de fichero

A veces utilizamos librerías que abren descriptores de fichero, es bueno tener una gráfica para asegurarnos de que no tenemos un crecimiento descontrolado de estos descriptores, la siguiente gráfica nos permite ver el número de descriptores abierto en tiempo real:

En nuestra instancia de Prometheus, podremos buscar por la keyword 'fd' (file descriptor):

Nosotros elegiremos la siguiente métrica:
process_open_fds
De tal manera que la gráfica tendrá la siguiente configuración
  • Panel Options - Title: Open File descriptors
  • Query - Metrics: process_open_fds


5 - Disponibilidad

Con la siguiente gráfica podremos ver de forma muy rápida si nuestros servicios están ejecutándose o no (color verde o rojo de las barras):

Si nos fijamos, el tipo de Chart que hemos utilizado aquí es un 'State timeline':

Añadiremos una 'Query' por cada instancia de la aplicación que tengamos, con el siguiente valor:

  • Panel Options - Title: Availability
  • Visualization Type: State timeline
  • Query - Metrics: up{instance="<APP_IP:APP_PORT>"}
Reemplazando la IP y el Puerto por las de tus instancias.

Y con esto ya tendrás listo un dashboard muy básico para monitorizar tu aplicación.


Comentarios