Supervisión con actuador Spring Boot

En este artículo, analizaremos Spring Boot Actuator, que proporciona puntos finales integrados listos para producción que se utilizan para monitorear y controlar sus aplicaciones Spring Boot.

Visión general

En este artículo, analizaremos el Actuador de bota de resorte, que proporciona puntos finales integrados listos para la producción que se pueden usar para monitorear y controlar su aplicación.

Las aplicaciones de monitoreo pueden incluir algo tan simple como conocer la Salud y la Información hasta algunos datos complejos como comprender el Tráfico y las Métricas de nuestra aplicación. Por ejemplo, cuántos recursos (CPU, RAM, etc.) utiliza la aplicación.

Puede optar por interactuar con actuadores con puntos finales HTTP o con beans JMX. En este tutorial, usaríamos los puntos finales HTTP.

En Spring Boot 1, el actuador solo se podía usar con Spring MVC. Pero con Spring Boot 2 y la introducción de WebFlux, su compatibilidad se ha ampliado y también puede usarse con el marco Jersey sin necesidad de Spring MVC en el classpath.

Actuador de arranque con resorte

Para demostrar el funcionamiento del actuador, usaremos un servicio simple basado en Spring REST, que se ejecuta en el puerto predeterminado (8080) con un único punto final de /hello que devuelve un mensaje de cadena.

Para agregar un actuador, simplemente agregamos la dependencia a nuestro archivo pom.xml:

1
2
3
4
5
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>${VERSION}</version>
</dependency>

Todos los puntos finales caen bajo un prefijo común de /actuador. Para verificar, naveguemos nuestro navegador a http://localhost:8080/actuator:

spring boot actuator default endpoints

Nota: En Spring Boot 1, todos los puntos finales del actuador estaban en la ruta base raíz, es decir, /, pero en Spring Boot 2, todos ellos están agrupados de manera predeterminada en /actuator.

Puede cambiar la ruta base de los puntos finales del actuador agregando las siguientes propiedades en application.properties:

1
2
management.endpoints.web.base-path=/admin
management.server.port=8090

Ahora, todos los puntos finales del actuador estarán bajo el prefijo /admin, lo cual tiene sentido ya que solo un administrador debería tener acceso a métricas como estas. Para este tutorial, lo dejaremos en el /actuador predeterminado.

De manera predeterminada, los puntos finales de administración están disponibles en el mismo puerto que el de su aplicación, pero puede optar por exponerlos en un puerto HTTP diferente configurando management.server.port en un puerto HTTP de su elección.

No lo cambiaremos ya que es preferible el comportamiento predeterminado, especialmente si está ejecutando en la nube.

Puntos finales del actuador

Se puede ver una lista completa de puntos finales disponibles en la [documentación oficial](https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-features.html#production-ready- puntos finales). Es posible que haya notado que, aunque hay muchos puntos finales disponibles, el resultado de http://localhost:8080/actuator muestra solo /health e /info.

Dado que los puntos finales del actuador contienen información confidencial, hemos tenido que exponer explícitamente cada uno de ellos; de lo contrario, solo podremos ver información rudimentaria que ya es evidente.

Navegue nuestro navegador a http://localhost:8080/actuator/health:

spring boot actuator health

Ahora, verifiquemos /info de manera similar y notará que devuelve una respuesta vacía.

Esto se debe a que no hemos proporcionado ninguna información al respecto a Spring. Esto se puede hacer agregando propiedades al prefijo info en application.properties:

1
2
info.name= Test Spring Service
info.more.detail= This is a demo for Spring Actuator

spring boot actuator info

Puede estructurar la clave JSON según sus necesidades.

Exponer puntos finales

Para exponer puntos finales, Spring proporciona 2 propiedades que podemos usar individualmente o en combinación:

  • management.endpoints.web.exposure.exclude: Se utiliza para excluir una lista de puntos finales que no queremos exponer. El valor predeterminado para él está vacío.
  • management.endpoints.web.exposure.include: Se utiliza para incluir una lista de puntos finales que queremos exponer. El valor predeterminado es info, health. Esta es la razón por la que ambos puntos finales estaban disponibles de forma predeterminada.

Nota: exclude tiene prioridad sobre include

Por lo tanto, modifiquemos la configuración para que queramos exponer todos los puntos finales excepto info y health:

1
2
management.endpoints.web.exposure.include=*
management.endpoints.web.exposure.exclude=info,health

Nota: Si está utilizando un archivo de propiedades basado en YAML, * tiene un significado especial y solo se puede usar con comillas:

1
2
3
4
5
management:
  endpoints:
    web:
      exposure:
        exclude: "*"

Para este tutorial, expondremos todos los puntos finales de nuestros actuadores. Así que agreguemos el siguiente punto final en nuestra application.properties:

1
management.endpoints.web.exposure.include= *

Ahora, revisemos el punto final del actuador nuevamente abriendo http://localhost:8080/actuator:

spring boot actuator all

Habilitación de puntos finales {#habilitación de puntos finales}

Además de exponer puntos finales, también podemos habilitarlos y deshabilitarlos. Mientras que exponer solo regula si podemos verlos o no, habilitar regula si existen como un frijol en el contexto de Spring.

De forma predeterminada, todos los puntos finales están habilitados excepto uno, el punto final shutdown. Puede habilitar/deshabilitar cada punto final configurando la propiedad management.endpoint.<id>.enabled:

1
2
management.endpoint.shutdown.enabled=true
management.endpoint.beans.enabled=false

También puede deshabilitar todos los puntos finales configurando management.endpoints.enabled-by-default en false y luego habilitar individualmente las propiedades que desee. Para este tutorial, usaríamos la configuración predeterminada.

Nota: Deshabilitar los puntos finales los eliminará como beans del contexto por completo y no importará si los ha expuesto.

Compatibilidad con almacenamiento en caché

Todos los puntos finales (que son operaciones READ y no toman ningún parámetro) también tienen soporte básico de almacenamiento en caché.

Cada punto final tiene una propiedad de cache.time-to-live que se genera automáticamente y que se puede usar para especificar el tiempo de caché:

1
management.endpoint.beans.cache.time-to-live=10s

Protección de puntos finales del actuador

A estas alturas, habría quedado claro que estos puntos finales almacenan información confidencial sobre nuestra aplicación y sería una buena idea asegurarlos.

Para hacerlo, simplemente podemos agregar Spring Security a nuestra aplicación agregando la dependencia spring-boot-starter-security en nuestro pom.xml:

1
2
3
4
5
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
    <version>${VERSION}</version>
</dependency>

De forma predeterminada, con solo importarlo, todos los puntos finales de nuestra aplicación estarán protegidos.

Pero supongamos que queremos que nuestro punto final /health esté disponible para todos, pero que el resto sea seguro. Esto garantiza un filtro personalizado para dejar pasar a ciertos usuarios y retener a otros.

Para eso tenemos que agregar una clase @Configuration que extienda el WebSecurityConfigurerAdapter, como con cualquier otra aplicación Spring Boot que queramos asegurar con Spring Security.

Luego necesitamos anular el método .configure() donde definimos la configuración de seguridad para nuestra aplicación:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()
            .authorizeRequests()
            .requestMatchers(EndpointRequest.to(HealthEndpoint.class)).permitAll()
            .requestMatchers(EndpointRequest.toAnyEndpoint()).authenticated()
            .and()
            .httpBasic();
    }
}

El código anterior se explica por sí mismo, donde permitimos que cualquier HealthEndpoint esté disponible públicamente, mientras que otros requieren una autenticación básica. Además, tenga en cuenta que EndpointRequest.to() es un método práctico que se ocupa automáticamente de la URL final de los puntos finales de su actuador porque es posible que haya cambiado la ruta base en su aplicación.

Reiniciemos de nuevo y verifiquemos los registros:

spring boot actuator security

Debido a que Spring Security está en el classpath, crea automáticamente un nombre de usuario de “usuario” y una contraseña que se genera aleatoriamente al inicio de la aplicación, como se muestra en los registros.

Verifiquemos el punto final /salud y verá la salida sin ningún cuadro de autenticación. Ahora probemos cualquier otro punto final, diga /env y se le pedirá que se autentique:

spring boot actuator security authenticate

Introduzca el nombre de usuario y la contraseña y podrá ver la respuesta adecuada:

spring boot actuator security authenticate env

Si desea definir su propio nombre de usuario y contraseña, puede hacerlo fácilmente a través de application.properties:

1
2
spring.security.user.name=user
spring.security.user.password=password

Creación de puntos finales personalizados

Esto se puede lograr agregando la anotación @Endpoint y @Component a su clase. Después de eso, puede crear métodos y anotarlos con @ReadOperation, @WriteOperation o @DeleteOperation según corresponda. Por supuesto, puede tener múltiples métodos con diferentes operaciones.

La idea de tener múltiples operaciones es mapear a diferentes métodos de solicitud HTTP:

  • @ReadOperation se asigna a HTTP GET
  • @WriteOperation se asigna a HTTP POST
  • @DeleteOperation se asigna a HTTP DELETE

Vamos a crear un punto final personalizado simple:

1
2
3
4
5
6
7
8
9
@Component
@Endpoint(id = "details")
public class DetailsEndpoint {

    @ReadOperation
    public String details() {
        return "My App Details";
    }
}

Reinicie la aplicación y vaya a su navegador a http://localhost:8080/actuator/details:

spring boot actuator custom

Conclusión

Las aplicaciones de monitoreo pueden incluir algo tan simple como conocer la Salud y la Información hasta algunos datos complejos como comprender el Tráfico y las Métricas de nuestra aplicación. Por ejemplo, cuántos recursos (CPU, RAM, etc.) utiliza la aplicación.

Spring Boot Actuator proporciona puntos finales integrados listos para producción que se pueden usar para monitorear y controlar su aplicación, como /info, /health, /scheduledTasks, etc.

También podemos definir nuestros propios puntos finales para cumplir con ciertos requisitos simplemente anotando clases con la anotación @Endpoint.

Como siempre, el código de los ejemplos utilizados en este artículo se puede encontrar en GitHub.