日志记录失败时停止Spring Boot应用程序(log4j2)



我有一个标准的Spring Boot微服务,它使用Log4j2进行所有日志记录。

我想在日志记录失败(例如磁盘已满(的情况下优雅地关闭spring引导应用程序。有办法设置它吗?

参考文献:如何在登录logback时处理磁盘已满错误-->这个问题并不能回答这个具体的问题。https://logging.apache.org/log4j/2.x/manual/appenders.html#FailoverAppender-->阅读FailoverAppender的文档,我不确定这是否符合要求。

我想您需要做的是通过其他机制检测剩余磁盘,而不是依靠记录器来检测。弹簧引导执行器用于提供许多指标,包括内存和磁盘。它使外部服务能够通过HTTP端点从正在运行的实例中获取度量。

在这里查看执行器如何获得磁盘空间:https://github.com/spring-projects/spring-boot/blob/v2.3.3.RELEASE/spring-boot-project/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/system/DiskSpaceHealthIndicator.java表明机制很简单:

@Override
protected void doHealthCheck(Health.Builder builder) throws Exception {
long diskFreeInBytes = this.path.getUsableSpace();
if (diskFreeInBytes >= this.threshold.toBytes()) {
builder.up();
}
else {
logger.warn(LogMessage.format("Free disk space below threshold. Available: %d bytes (threshold: %s)",
diskFreeInBytes, this.threshold));
builder.down();
}
builder.withDetail("total", this.path.getTotalSpace()).withDetail("free", diskFreeInBytes)
.withDetail("threshold", this.threshold.toBytes()).withDetail("exists", this.path.exists());
}

在主应用程序类中,您可以定期检查磁盘空间,如果磁盘空间低于特定阈值,则可以使用与上面所示相同的机制关闭应用程序上下文。关闭应用程序可以是这样的:

int exitCode = SpringApplication.exit(ctx, new ExitCodeGenerator() {
@Override
public int getExitCode() {
// return the error code
return 0;
}
});

System.exit(exitCode);

每个Appender都由Log4j2中的AppenderControl包装。AppenderControl捕获Appender抛出的任何异常。它的默认行为是将错误处理程序附加到Appender并调用其error((方法。当该方法返回时,它将检查属性";ignoreExceptions";为false(默认为true(,如果为true,则将重新引发异常。

理想情况下,您可以实现自己的错误处理程序,除非编写代码的人(我(忘记了将其配置。看见https://issues.apache.org/jira/browse/LOG4J2-2927.

FailoverAppender的设计目的是包装一个附加程序,然后在发生错误时故障转移到另一个附加器。这需要在目标appender上将ignoreExceptions设置为false。您可以复制FailoverAppender来创建自己的自定义附加程序,而不是在错误发生时执行关闭。

Spring引导附带一个具有(默认禁用(shutdown端点的执行器。基本上,当启用该端点时,它允许通过JMX或HTTP关闭spring引导应用程序。这是迄今为止我所知道的优雅地关闭spring引导应用程序的最佳方式。

这个端点的源代码在这里可用,您可以很容易地看到,毕竟它在应用程序上下文中调用了close方法。

现在,对于您的问题,我从未使用过log4j2,但作为一种想法,您可以创建自己的appender来包装分配给记录器的实际appender,它可以捕获异常并调用close方法(在这种情况下,它还必须维护对应用程序上下文的引用(,或者通过JMX调用shutdown端点。这可以";补码";由@rgoers提供的答案,他从log4j2的角度解决了这个问题。

相关内容

  • 没有找到相关文章

最新更新