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.