以前,我发现idlePurgePolicy将在空闲时间(SO question)之后关闭打开的日志文件。
但是现在看来,log4j2的idlePurgePolicy在容器中不起作用。我已经在单个Java应用程序中测试了以下内容,它可以按预期工作(关闭空闲日志文件),但是在容器(在下面的示例中)中,日志文件保持打开状态。
我有一个示例项目,该项目是在Tomcat上运行的Spring Web Service。有一个rest api,当被调用时会记录一条语句。由于此操作由文件附加程序支持,因此log4j还会创建/打开日志文件。
奇怪的是,在第一次调用rest api时,idlePurgePolicy似乎确实起作用。但此后再也没有关闭日志文件。有点暗示这可能是线程问题,但是我确实在简单的Java应用程序中创建了线程和线程池,因此无法复制该问题。我还记录了线程名称和ID,这表明弹簧为记录生成的所有线程都是新的(因此,池方面或重用线程并没有真正发挥作用,第一个起作用的线程与随后的所有线程相同)线程)。
侧面注意:我正在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>
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");
}
答案 0 :(得分:0)
我在log4j的源代码中断点了; IdlePurgePolicy类,特别是下面的方法(purge())
我注意到,只有在关闭第一个日志时才会击中我的断点,而在此之后不会击中(解释上述问题的行为)。我并没有做得太深,但是我相信它会删除附加程序,并且永远不会重新添加
但是真正的解决方法是将我的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());
}
}
}