idlePurgePolicy log4j2 не работает в контейнере - PullRequest
0 голосов
/ 19 октября 2018

Ранее я обнаружил, что idlePurgePolicy закроет открытые файлы журнала после периода простоя ( SO вопрос ).

Однако теперь может показаться, что idlePurgePolicy log4j2 не работает внутри контейнера.Я протестировал нижеприведенное в одном java-приложении, и оно работает как положено (закрытие файлов журнала простоя), но в контейнере (в примере ниже) файлы журнала остаются открытыми.

У меня есть пример проекта, который представляет собой Spring Web Service, работающий на Tomcat.Существует api rest, который при вызове записывает один оператор;поскольку это поддерживается файловым приложением, log4j также создает / открывает файл журнала.

Как ни странно (и немного противоречиво), idlePurgePolicy, кажется, работает при первом вызове остальных API-интерфейсов.но после этого никакие файлы журнала никогда не закрываются .Это своего рода предположение, что это может быть проблема с многопоточностью, однако я создал потоки и пулы потоков в своем простом Java-приложении и не смог воспроизвести проблему.Я также зарегистрировал имя и идентификатор потока, который показал, что все потоки, порождаемые пружиной для регистрации, являются новыми (поэтому аспект пула или повторное использование потоков на самом деле не вступают в игру, первый из них работает так же, как и все последующиепотоки).

Примечание: я тестирую на 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");
    }

1 Ответ

0 голосов
/ 19 октября 2018

У меня была точка останова в источнике для 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());
            }
        }
    }
...