Monitorizar una aplicación Java de Spring Boot con Micrometer, Prometheus y Grafana
Escrito por
el .
java
planeta-codigo
programacion
software
spring
Enlace permanente
Comentarios
Los proyectos de Spring no son tan conservadores como Java EE o ahora Jakata EE y se desarrollan a una velocidad mayor cubriendo de forma más temprana las necesidades de los programadores según evolucionan las tecnologías y se adoptan nuevos modelos de arquitectura.
Con el advenimiento de los microservicios, contenedores, la nube y aplicaciones autocontenidas Spring se ha adaptado con proyectos como Spring Boot y Spring Cloud. En el asunto que ocupa este artículo de métricas con la versión 2 de Spring Boot se ha adoptado Micrometer como librería para proporcionar las métricas.
Micrometer permite exportar a cualquiera de los más populares sistemas de monitorización los datos de las métricas. Usando Micrometer la aplicación se abstrae del sistema de métricas empleado pudiendo cambiar en un futuro si se desea. Uno de los sistemas más populares de monitorización es Prometheus que se encarga de recoger y almacenar los datos de las métricas expuestas por las aplicaciones y ofrece un lenguaje de consulta de los datos con el que otras aplicaciones pueden visualizarlos en gráficas y paneles de control. Grafana es una de estas herramientas que permite visualizar los datos proporcionados por Prometheus. Estos sistemas de monitorización ofrecen un sistema de alertas que se integran entre otros con Slack.
En el artículo Información y métricas de la aplicación con Spring Boot Actuator mostraba como configurar Spring Boot y Spring Boot Actuator para exponer métricas en el endpoint /actuator/metrics, con estas herramientas solo se exponen la clave y valor de cada métrica y solo en un momento dado. Pueden ser métricas del servicio como cantidad de CPU usada, memoria consumida y libre, espacio en almacenamiento, etc… o métricas de aplicación como número de peticiones realizadas al servicio, tiempo de respuesta, etc… Una de las funcionalidades de Prometheus es recolectar cada cierto tiempo los valores de estas métricas que da lugar a una colección de datos que varía en el tiempo y que Grafana puede visualizar en gráficas para una mucha mayor facilidad de comprensión que la enorme cantidad de datos en crudo.
Usando Spring Boot 2 exportar los datos para Prometheus es realmente sencillo, basta con incluir la dependencia io.micrometer:micrometer-registry-prometheus mediante la herramienta de construcción, por ejemplo Gradle, y automáticamente se expone en el endpoint /actuator/prometheus con la información de las métricas en el formato que espera Prometheus para recolectarla.
|
|
Micrometer y Prometheus ofrecen varios tipos de métricas:
- Counter: representa un valor que se va incrementando a lo largo del tiempo. Puede ser el número de invocaciones recibidas por servicio.
- Gauge: representa un valor que arbitrariamente puede subir o bajar. Puede ser la cantidad de memoria usada.
- Timer: mide periodos de tiempo. Puede ser el tiempo de respuesta empleado para atender una petición de un servicio.
- Distribution summaries: recolecta la distribución de una serie de datos con los que se pueden obtener percentiles.
Ejemplo de microservicio con Spring Boot, Micrometer, Prometheus y Grafana
Utilizando el ejemplo que hice para la serie de artículos sobre Spring Cloud he añadido al micro servicio service un contador con el número de invocaciones que se le ha realizado. Este dato se expone en el endpoint con la clave service.invocations como se ha definido al registrar el contador en Micrometer con la clase MeterRegistry. Además de esta métrica propia del servicio Spring Boot Actuator añade otras muchas más del uso de la CPU, memoria, …
Una clase de una aplicación de Spring Boot que utiliza un Counter.
|
|
Las claves de las métricas por defecto exportadas por Spring Boot Actuator.
|
|
Los datos de una métrica en el endpoint /actuator/metrics/service.invocations.
|
|
Y las mismas métricas en el formato que espera Prometheus.
|
|
Para iniciar el ejemplo de Spring Cloud que consta de un servicio de registro y descubrimiento, un servicio de configuración, un servicio del que se pueden iniciar varias instancias y un cliente que hace peticiones hay que utilizar la siguiente serie de comandos.
|
|
Una vez expuestas las métricas en el formato que espera Prometheus este ya puede recolectarlas. Para usar Prometheus y posteriormente Grafana de forma fácil evitando tener que instalar y configurar nada se puede usar Docker, en este caso con Docker Compose. En la serie de artículos sobre Docker explico que proporciona Docker y como usar las varias herramientas que ofrece.
El archivo de Docker Compose contiene dos contenedores uno para Prometheus y otro para Grafana, con sus archivos de configuración. En la configuración de Prometheus se crean un job que recolecta las métricas cada pocos segundos del servicio a través del endpoint de métricas. En la configuración de Grafana se añade como una fuente de datos Prometheus, se puede añadir otras varias.
|
|
|
|
|
|
|
|
Prometheus posee la funcionalidad básica de crear gráficas con las métricas recogidas pero no tiene la habilidad de crear paneles que recogen una colección de gráficas relacionadas o un editor de consultas más avanzado como tiene Grafana.
Una vez que Prometheus recolecta los datos de las métricas al introducir las expresiones se proporciona asistencia de código. Por otro lado, en la sección Status > Targets de Prometheus se puede ver el estado de los servicios de los que recolecta métricas.
Como Spring Boot Actuator exporta muchas métricas del funcionamiento del servicio Grafana puede crear gráficas de todas ellas. No hace falta crear un dashboard desde cero, se pueden descargar e importar dashboards. Este ejemplo para Micrometer recoge la memoria de la JVM (heap y no heap), uso de CPU, carga, hilos, estado de hilos, descriptores de archivos, recolector de basura, classloader y entrada/salida básica.
Grafana tiene plugins para añadir como fuentes de datos bases de datos relacionales para extraer mediante sentencias SQL y visualizar datos almacenados en MySQL, PostgreSQL u Oracle.
Con la información de las métricas se conoce más en detalle cual es el comportamiento normal de una aplicación y observar de forma rápida cuando se introducen cambios como afectan al comportamiento de la misma tanto de forma negativa como de forma positiva. En cualquier aplicación que ofrece un servicio es importante conocer su estado y actuar incluso antes de que ofrezca un mal comportamiento e incluso deje de prestar su servicio. La monitorización no sustituye sino que complementa un sistema de trazas que en una aplicación Java es común que se realice con SLF4J o Log4j.
Aún quedan algunas preguntas por responder ¿como agregar los datos de múltiples instancias? ¿si se crean nuevas instancias del servicio como puede conocer Prometheus los nuevos targets que se han creado? En el ejemplo solo hay una instancia del servicio y la configuración de Prometheus es proporcionada por un archivo estático. Aún desconozco las respuestas, no lo he investigado en detalle, hay alguna pregunta sobre este tema en StackOverflow y por la respuesta Prometheus no tiene un adaptador para Eureka entre los varios servicios de descubrimiento que sí soporta en su configuración.
El código fuente completo del ejemplo puedes descargarlo del repositorio de ejemplos de Blog Bitix alojado en GitHub y probarlo en tu equipo ejecutando siguiente comando:./gradlew-run.sh, docker-compose up