java - log4j2 的 idlePurgePolicy 在容器中不起作用
问题描述
以前我发现 idlePurgePolicy 将在空闲期后关闭打开的日志文件(SO问题)。
但是现在看来 log4j2 的 idlePurgePolicy 在容器中不起作用。我在单个 java 应用程序中测试了以下内容,它按预期工作(关闭空闲日志文件),但在容器中(在下面的示例中),日志文件保持打开状态。
我有一个示例项目,它是在 Tomcat 上运行的 Spring Web Service。有一个 rest api 调用时会记录一条语句;因为这是由文件附加程序支持的,所以 log4j 也会创建/打开一个日志文件。
奇怪的是(这里有点矛盾)idlePurgePolicy 在第一次调用 rest api 时似乎确实有效。但在那之后,没有任何日志文件被关闭。这有点暗示这可能是一个线程问题,但是我确实在我的简单 Java 应用程序中创建了线程和线程池,并且无法复制该问题。我还记录了线程名称和 id,这表明 spring 为日志记录生成的所有线程都是新的(因此池方面或重用线程并没有真正发挥作用,第一个工作的线程与所有后续线程相同线程)。
旁注:我在 Windows 上进行测试并使用OpenedFilesView查看打开的文件(如果测试/复制此文件是必需的)
log4j2.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE xml>
<Configuration monitorInterval="180">
<Properties>
<!-- change the path to conference logs below to fit your system -->
<Property name="LOG_DIR">C:\CodeRepos\logs</Property>
<Property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level
%logger{36} - %msg%n</Property>
</Properties>
<Appenders>
<Console name="Console" target="SYSTEM_OUT">
<PatternLayout pattern="${PATTERN}" />
</Console>
<Routing name="ConferenceLog">
<Routes pattern="${ctx:logFileName}">
<Route>
<File name="ConferenceLog"
fileName="${LOG_DIR}/conferences/ConferenceLog.log">
<PatternLayout pattern="${PATTERN}" />
</File>
</Route>
</Routes>
<IdlePurgePolicy timeToLive="5" timeUnit="seconds"/>
</Routing>
</Appenders>
<Loggers>
<Root level="debug">
</Root>
<Logger name="com.avispl" level="debug" additivity="false">
<AppenderRef ref="Console" />
</Logger>
<Logger name="conference.logger" level="debug" additivity="false">
<AppenderRef ref="ConferenceLog" />
</Logger>
</Loggers>
</Configuration>
命令控制器.java
private static final String LOG_FILE_NAME = "logFileName";
private static final String CONFERENCE_LOGGER = "conference.logger";
private static final Logger conferenceLogger = Logger.getLogger(CONFERENCE_LOGGER);
@RequestMapping(method = RequestMethod.GET, value = "log_test")
public @ResponseBody void logTest(@RequestParam(required = true) long duration) {
conferenceLogger.debug("test");
}
解决方案
我在 log4j 的源代码中设置断点;IdlePurgePolicy 类,特别是下面的方法 (purge())
我注意到我的断点只会在第一个日志被关闭时被击中,并且在此之后永远不会被击中(解释了上面问题中描述的行为)。我没有走得太深,但我相信它删除了 appender 并且它永远不会被重新添加
然而,真正的修复是将我的 log4j2 版本从 2.5 更新到 2.11.1
public void purge() {
long createTime = System.currentTimeMillis() - timeToLive;
for (Entry<String, Long> entry : appendersUsage.entrySet()) {
if (entry.getValue() < createTime) {
LOGGER.debug("Removing appender " + entry.getKey());
appendersUsage.remove(entry.getKey());
routingAppender.deleteAppender(entry.getKey());
}
}
}
推荐阅读
- react-native - 警告:尝试呈现
上 这已经在呈现 - javascript - 如何在主题js中放置cookie同意?
- ios - 为什么默认的 UIWindowSceneDelegate 类继承自 UIResponder?
- c++ - 显示字符串的集合和子集
- python - 如何在 AWS CDK 中创建自定义资源
- go - 将值分配给变量,同时将其传递给 Go 中的函数
- javascript - 如何将 JSON 数据显示为矩阵(如 SSRS 中的矩阵)?
- python-3.x - 没有名为“bayesian_bandit”的模块
- node.js - Node/React 应用程序在本地运行良好,但在互联网上出现 502 错误
- jquery - 数据对象更改后的DataTable重绘表