Spring Boot Actuator

Spring Boot Actuator – это библиотека, которая позволяет мониторить приложение в production-среде (хотя не обязательно в ней). С помощью нее можно посмотреть кучу параметров: характеристики системы, на которой  работает приложение,  какие в приложении создаются бины, различные метрики и т.п.

Причем делать для этого ничего не надо, просто включаете библиотеку в проект и готовы конечные точки (end points), выходя на которые можно мониторить данные. Например, по адресу /actuator/beans – список бинов.

Maven- зависимость

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

Примеры конечных точек

Давайте создадим простой веб-проект и посмотрим, что выводит Spring по зарезервированным Actuator адресам по умолчанию. (Проект доступен на GitHub, если делаете с нуля – включите spring-boot-starter-web зависимость, чтоб при запуске приложения стартовал веб-сервер).

GET localhost:8080/actuator
{
   "_links":{
      "self":{
         "href":"http://localhost:8080/actuator",
         "templated":false
      },
      "health":{
         "href":"http://localhost:8080/actuator/health",
         "templated":false
      },
      "info":{
         "href":"http://localhost:8080/actuator/info",
         "templated":false
      }
   }
}

Выше перечислены все доступные конечные точки – enabled и exposed одновременно. Точка enabled – значит существует бин с такими данными, создающийся в контексте приложения. В Spring Boot 2 по умолчанию все точки enabled. Но почему  же мы видим только две в вышеприведенном JSON: health и info?

Потому что для доступа к точке она должна быть еще exposed (видна). В Spring Boot 2 по умолчанию только две точки exposed через http. Чтобы сделать доступными дополнительные точки, надо в файле application.properties прописать:

management.endpoints.web.exposure.include=health,info,beans

Давайте проверим, что точки доступны.

health

Эта точка используется для тестирования: убедиться, что приложение доступно и не упало по какой-то причине:

GET http://localhost:8080/actuator/health
{"status":"UP"}

Если какая-то из баз данных, например, упадет, по этому адресу будет показано сообщение об ошибке.

beans

Выдает список бинов, созданных в контексте приложения (список выдается огромный, в тут JSON сокращен):

GET http://localhost:8080/actuator/beans
{
   "contexts":{
      "application":{
         "beans":{
            "endpointCachingOperationInvokerAdvisor":{
               "aliases":[

               ],
               "scope":"singleton",
               "type":"org.springframework.boot.actuate.endpoint.invoker.cache.CachingOperationInvokerAdvisor",
               "resource":"class path resource [org/springframework/boot/actuate/autoconfigure/endpoint/EndpointAutoConfiguration.class]",
               "dependencies":[
                  "environment"
               ]
            },
            "defaultServletHandlerMapping":{
               "aliases":[

               ],
               "scope":"singleton",
               "type":"org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport$EmptyHandlerMapping",
               "resource":"class path resource [org/springframework/boot/autoconfigure/web/servlet/WebMvcAutoConfiguration$EnableWebMvcConfiguration.class]",
               "dependencies":[

               ]
            },
           .....

            "org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration":{
               "aliases":[

               ],
               "scope":"singleton",
               "type":"org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointAutoConfiguration$$EnhancerBySpringCGLIB$$c9a865f0",
               "resource":null,
               "dependencies":[
                  "org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext@35083305",
                  "management.endpoints.web-org.springframework.boot.actuate.autoconfigure.endpoint.web.WebEndpointProperties"
               ]
            },
          
         }
         "parentId":null
      }
   }
}

info

Эта точка предназначена для вывода информации о приложении, по умолчанию здесь выдается пустой JSON. Давайте добавим сюда информацию:

# Spring Boot Actuator Info Endpoint Customization
info.app.name= Spring Boot Actuator Example
info.app.description=This is an example of Spring Boot Actuator.

  # build properties from maven
info.build.groupId= @project.groupId@
info.build.artifact= @project.artifactId@
info.build.name= @project.name@
info.build.version= @project.version@

  # environment variables
info.env.java.vendor= ${java.specification.vendor}
info.env.java.vm-name= ${java.vm.name}
info.env.java.runtime-version= ${java.runtime.version}

Проверим:

GET http://localhost:8080/actuator/info
{
   "app":{
      "name":"Spring Boot Actuator Example",
      "description":"This is an example of Spring Boot Actuator."
   },
   "build":{
      "groupId":"ru.sysout",
      "artifact":"spring-actuator",
      "name":"spring-actuator",
      "version":"0.0.1-SNAPSHOT"
   },
   "env":{
      "java":{
         "vendor":"Oracle Corporation",
         "vm-name":"Java HotSpot(TM) 64-Bit Server VM",
         "runtime-version":"1.8.0_112-b15"
      }
   }
}

Настройки конечных точек

Уже было показано, как сделать доступной дополнительную конечную точку (помимо трех, доступных по умолчанию).

По умолчанию все точки включены (enabled, то есть создаются в контексте приложения), но доступны только три из них.

Если большинство конечных точек вам не нужны, имеет смысл сделать все по умолчанию выключенными, а включать по отдельности:

management.endpoints.enabled-by-default=false
management.endpoint.info.enabled=true

можно изменить порт, на котором доступны конечные точки:

management.server.port: 9001

Или адрес сервера:

management.server.address: 127.0.0.2

Изменить адрес конечной точки /actuator/health на /healthcheck:

management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck

Тестирование

Давайте протестируем конечную точку (и заодно тут присутствует тест единственного контроллера):

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(properties = { "management.server.port=0" })

public class SpringActuatorApplicationTests {

  @LocalServerPort
  private int port;

  @Value("${local.management.port}")
  private int mgt;

  @Autowired
  private TestRestTemplate testRestTemplate;

  @Test
  public void shouldReturn200WhenSendingRequestToController() throws Exception {
    @SuppressWarnings("rawtypes")
    ResponseEntity<Map> entity = this.testRestTemplate
        .getForEntity("http://localhost:" + this.port + "/hello", Map.class);
    then(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
  }

  @Test
  public void shouldReturn200WhenSendingRequestToManagementEndpoint() throws Exception {
    @SuppressWarnings("rawtypes")
    ResponseEntity<Map> entity = this.testRestTemplate
        .getForEntity("http://localhost:" + this.mgt + "/actuator/info", Map.class);
    System.out.println(this.mgt);
    then(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
  }

}

Эти две строки обнуляют насторки портов основного приложения и актуатора соответственно. В результате контроллер и актуатор будут запускаться на случайных (двух разных) портах:

@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
@TestPropertySource(properties = { "management.server.port=0" })

Есть много способов обратитсья по http в тестовой среде, но мы используем:

@Autowired
private TestRestTemplate testRestTemplate;

Он подходит для тестирования, особенно тогда, когда с его помощью данные с конечной точки и берутся, что вполне вероятно.

Полный код проекта доступен на GitHub.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *