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.