t.me/atinfo_chat Telegram группа по автоматизации тестирования

Удаление лога теста в log4j2 после успешного завершения теста

log4j
execution
logging
java
Теги: #<Tag:0x00007f9c54c43db0> #<Tag:0x00007f9c54c43a68> #<Tag:0x00007f9c54c437c0> #<Tag:0x00007f9c54c435b8>

(Nik Sidorenko) #1

Проблема следующая.
Есть log4j2 конфиг

<?xml version="1.0" encoding="UTF-8" ?>
<Configuration status="DEBUG">
    <Appenders>
        <Console name="ConsoleAppender" target="SYSTEM_OUT">
            <PatternLayout pattern="%highlight{%d{yyyy-MM-dd HH:mm:ss} [%T] %t %-5level %logger{36} - %msg}%n%throwable"/>
        </Console>
        <File name="FileAppender" fileName="${log4j:configParentLocation}/../test-output/logs/all.tests.log" immediateFlush="true" append="true">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%T] %t %-5level %logger{36} - %msg%n%throwable"/>
        </File>
        <Routing name="RoutingAppender">
            <Routes pattern="${ctx:logFilePath}">
                <!-- This route is chosen if ThreadContext has a value for logFileName.
                 The value dynamically determines the name of the log file. -->
                <Route>
                    <File name="TestAppender"
                          fileName="${ctx:logFilePath}"
                          immediateFlush="true"
                          append="true">
                        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%T] %t %-5level %logger{36} - %msg%n%throwable"/>
                    </File>
                </Route>
                 <!--This route is chosen if ThreadContext has no value for key logFileName.-->
                <Route key="${ctx:logFilePath}">
                    <File name="ConfigurationAppender" fileName="${log4j:configParentLocation}/../test-output/logs/configuration.log" immediateFlush="true" append="true">
                        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} [%T] %t %-5level %logger{36} - %msg%n%throwable"/>
                    </File>
                </Route>
            </Routes>
        </Routing>
    </Appenders>
    <Loggers>
        <Root level="DEBUG">
            <AppenderRef ref="RoutingAppender"/>
            <AppenderRef ref="ConsoleAppender"/>
            <AppenderRef ref="FileAppender"/>
        </Root>
    </Loggers>
</Configuration>

C помощью RoutingAppender я пишу логи каждого теста в отдельный файл. Тесты выполняются параллельно.
Хочется, чтобы в случае успешного выполнения теста, его лог файл удалялся. Если тест упал, то файл оставался.

Сейчас удалить файл программно после завершения теста, не получается, т.к. логгер держит файл и отпускает его только после завершения всего Suite и даже после onFinish(ISuite iSuite)

Как можно это сделать или какой другой подход выбрать?


#2

Если TestNg то подключаем TestListenerAdapter и там в onTestSucess удаляем ненужный лог.

Ну или в AfterMethod тоже можно узнать результат прогона


(Nik Sidorenko) #3

Не там не там не удаляется. Файл в этих местах всё ещё залочен логгером.


(Михаил Братухин) #4

Писать в буфер вместо файла и если ошибка, то скидывать буфер на диск?

Ещё я вспомнил проблему когда-то решали с блокировкой файлового ресурса, там на stackoverflow нашелся совет который сработал: вызвать остановку garbage collector’а, может поможет, если перед удалением файла провернуть этот трюк. :wink:
Вот эта тема по-моему или аналогичная: https://stackoverflow.com/questions/9398746/java-file-delete-and-system-gc


#5

Можно еще просто после прогона чистить папку.


(Nik Sidorenko) #6

Похоже так и будет. Ещё немного покопаюсь, если ничего не получится с

и с удалением/добавлением аппендера программно, то остановлюсь на этом варианте.


(Nik Sidorenko) #7

Нашёл способ сделать так, чтобы файл можно было удалить в нужный момент.
Для этого перед удалением файла нужно остановить/закрыть FileManager нужного динамически созданного для конкретного теста FileAppender.

        final LoggerContext context = (LoggerContext) LogManager.getContext(false);
        final RoutingAppender routingAppender = context.getConfiguration().getAppender("RoutingAppender");
        final FileAppender fileAppender = (FileAppender) routingAppender.getAppenders().get("TestAppender").getAppender();
        fileAppender.getManager().close();

Важно в методе LogManager.getContext(false) использовать для параметра currentContext не true а именно false. Иначе контекст не видит нужных TestAppender вложенных в RoutingAppender