log4j2 的 idlePurgePolicy 在容器中不起作用
log4j2's idlePurgePolicy doesnt work within a container
之前我发现 idlePurgePolicy 会在空闲期 () 后关闭打开的日志文件。
但是现在看来 log4j2 的 idlePurgePolicy 在容器中不起作用。我已经在单个 java 应用程序中测试了以下内容,它按预期工作(关闭空闲日志文件)但在容器中(在下面的示例中)日志文件保持打开状态。
我有一个示例项目,它是 Tomcat 上的 Spring Web 服务 运行。剩下的 api 被调用时会记录一条语句;因为这是由文件附加程序 log4j 支持的,也是 creates/opens 日志文件。
奇怪的是(这里有点矛盾)idlePurgePolicy 似乎在第一次调用 rest api 时起作用。但在那之后没有日志文件被关闭。这有点表明它可能是一个线程问题,但我确实在我的简单 java 应用程序中创建了线程和线程池,但无法复制该问题。我还记录了线程名称和 ID,这表明所有为日志生成的线程 spring 都是新的(因此池方面或重新使用线程并没有真正发挥作用,第一个起作用的是与所有后续线程相同)。
旁注:我正在 windows 上进行测试,并使用 OpenedFilesView 查看打开的文件(如果 testing/reproducing 是必需的)
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>
CommandsController.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 class,特别是下面的方法 (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());
}
}
}
之前我发现 idlePurgePolicy 会在空闲期 (
但是现在看来 log4j2 的 idlePurgePolicy 在容器中不起作用。我已经在单个 java 应用程序中测试了以下内容,它按预期工作(关闭空闲日志文件)但在容器中(在下面的示例中)日志文件保持打开状态。
我有一个示例项目,它是 Tomcat 上的 Spring Web 服务 运行。剩下的 api 被调用时会记录一条语句;因为这是由文件附加程序 log4j 支持的,也是 creates/opens 日志文件。
奇怪的是(这里有点矛盾)idlePurgePolicy 似乎在第一次调用 rest api 时起作用。但在那之后没有日志文件被关闭。这有点表明它可能是一个线程问题,但我确实在我的简单 java 应用程序中创建了线程和线程池,但无法复制该问题。我还记录了线程名称和 ID,这表明所有为日志生成的线程 spring 都是新的(因此池方面或重新使用线程并没有真正发挥作用,第一个起作用的是与所有后续线程相同)。
旁注:我正在 windows 上进行测试,并使用 OpenedFilesView 查看打开的文件(如果 testing/reproducing 是必需的)
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>
CommandsController.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 class,特别是下面的方法 (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());
}
}
}