我正在使用Spring Boot执行器API用于我的项目具有健康检查端点,并通过:
启用它management.endpoints.web.base-path=/
management.endpoints.web.path-mapping.health=healthcheck
这里提到的
现在,我想在上述/healthcheck
的状态失败并从此终点打印整个响应时,启用登录我的应用程序日志文件。
实现此目标的正确方法是什么?
最佳方法是用@EndpointWebExtension
扩展执行器端点。您可以做以下;
@Component
@EndpointWebExtension(endpoint = HealthEndpoint.class)
public class HealthEndpointWebExtension {
private HealthEndpoint healthEndpoint;
private HealthStatusHttpMapper statusHttpMapper;
// Constructor
@ReadOperation
public WebEndpointResponse<Health> health() {
Health health = this.healthEndpoint.health();
Integer status = this.statusHttpMapper.mapStatus(health.getStatus());
// log here depending on health status.
return new WebEndpointResponse<>(health, status);
}
}
更多关于执行器端点在此处延伸的 4.8。扩展现有端点
上述答案对我不起作用。我实施了以下操作,并且有效。当您从浏览器查看[myhost:port]/actuator/health
时,下面将执行。您也可以将healthCheckLogger
添加到准备/LINICICES探针中,以便定期执行。
@Slf4j
@Component
public class HealthCheckLogger implements HealthIndicator
{
@Lazy
@Autowired
private HealthEndpoint healthEndpoint;
@Override
public Health health()
{
log.info("DB health: {}", healthEndpoint.healthForPath("db"));
log.info("DB health: {}", healthEndpoint.healthForPath("diskSpace"));
return Health.up().build();
}
}
使用EndpointWebExtension
扩展HealthEndpoint
不适用于较新的弹簧版本。不允许覆盖现有的(Web-)扩展名或重新注册另一个。
另一个解决方案是使用Filter
。如果健康检查失败,则以下实现日志:
public class HealthLoggingFilter implements Filter {
private static final Logger LOG = LoggerFactory.getLogger(HealthLoggingFilter.class);
@Override
public void init(FilterConfig filterConfig) {
// nothing to do
}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
ContentCachingResponseWrapper responseCacheWrapperObject = new ContentCachingResponseWrapper((HttpServletResponse) response);
chain.doFilter(request, responseCacheWrapperObject);
int status = ((HttpServletResponse) response).getStatus();
if (status >= 400) { // unhealthy
byte[] responseArray = responseCacheWrapperObject.getContentAsByteArray();
String responseStr = new String(responseArray, responseCacheWrapperObject.getCharacterEncoding());
LOG.warn("Unhealthy. Health check returned: {}", responseStr);
}
responseCacheWrapperObject.copyBodyToResponse();
}
@Override
public void destroy() {
// nothing to do
}
}
可以使用FilterRegistrationBean
注册actuator/health
路由的过滤器:
@Bean
public FilterRegistrationBean<HealthLoggingFilter > loggingFilter(){
FilterRegistrationBean<HealthLoggingFilter > registrationBean = new FilterRegistrationBean<>();
registrationBean.setFilter(new HealthLoggingFilter ());
registrationBean.addUrlPatterns("/actuator/health");
return registrationBean;
}
如果使用webflux,则适用于我在kotlin中的样本
@Component
@EndpointWebExtension(endpoint = HealthEndpoint::class)
class LoggingReactiveHealthEndpointWebExtension(
registry: ReactiveHealthContributorRegistry,
groups: HealthEndpointGroups
) : ReactiveHealthEndpointWebExtension(registry, groups) {
companion object {
private val logger = LoggerFactory.getLogger(LoggingReactiveHealthEndpointWebExtension::class.java)
}
override fun health(
apiVersion: ApiVersion?,
securityContext: SecurityContext?,
showAll: Boolean,
vararg path: String?
): Mono<WebEndpointResponse<out HealthComponent>> {
val health = super.health(apiVersion, securityContext, showAll, *path)
return health.doOnNext {
if (it.body.status == UP) {
logger.info("Health status: {}, {}", it.body.status, ObjectMapper().writeValueAsString(it.body))
}
}
}
}