Как избежать FileSystemException (Невозможно удалить файл - Используется другим процессом), когда прокатка происходит с использованием lo4j2? - PullRequest
0 голосов
/ 04 июля 2019

Мы теряем файлы журналов, когда прокатка происходит с использованием CronTriggeringPolicy с библиотекой Log4j2, и приложение вызывается одновременно (я использовал почтальон для запуска 10 вызовов за 5 секунд до того, как произошло событие прокатки). Есть ли способ изменить конфигурацию или способ, которым средства ведения журнала используются в приложении для обеспечения безопасности потока, когда другие службы записывают данные в файл журнала, чтобы избежать потери ценных файлов журнала в работе?

Приложение работает в IBM WebSphere Application Server 8.5.5.14, Red Hat Enterprise Linux 7.3, дополнительные технологии / библиотеки: Java 7, Java EE 6, Log4j2 (v2.11.2).

Платформы не используются, мы используем реализации, предоставляемые WebSphere.

Нет проблем с разрешениями для файлов, так как пользователь, использовавший для запуска сервера, является владельцем всего каталога и подкаталогов.

Я обнаружил, что эта проблема заключается в проверке, когда служба (или несколько служб) пишет в файл, и происходит прокрутка. Существует очевидная блокировка файла, когда log4j2 пытается переместить файл. Я прочитал документацию, но не нашел четкого примера, чтобы избежать этой проблемы.

Это класс точки входа websphere, который расширяет приложение:

import javax.ws.rs.ApplicationPath;
import javax.ws.rs.core.Application;

@ApplicationPath("")
public NiceServiceApplication extends Application {}

Тогда у нас есть простой компонент для вызова из сервиса

import org.apache.logging.log4j.Logger;

public interface BeanOne {
    public abstract void hello();
    public abstract void setLogger(Logger logger);
}

Реализация компонента

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.ejb.Remote;
import javax.ejb.Stateless;
import javax.ejb.TransactionManagement;
import javax.ejb.TransactionManagementType;
@Stateless
@Remote(BeanOne.class)
@TransactionManagement(TransactionManagementType.BEAN)
public class BeanOneImpl implements BeanOne {

    private Logger logger;

    public void hello() {
        logger.info("Hello in bean one called :D");
    }

    public void setLogger(Logger logger) {
        if(logger == null) {
            LogManager.getLogger("fallback-logger")
        } else {
            this.logger = logger;
        }
    }
}

Класс обслуживания

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.GET;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
@Path("/helloService")
public class NiceService {
    private static final Logger logger = LogManager.getLogger("nice-logger");

    @EJB
    private BeanOne bean;

    @PostConstruct
    private void init() {
        beanOne.setLogger(logger);
    }

    @GET
    @Path("/hello")
    @Produces(MediaType.APPLICATION_JSON)
    public Response sayHelloToMe() {
        bean.hello();
        return Response.ok().entity("{\"msg\":\"Hello there!\"}").build();
    }
}

Используемая конфигурация Lo4j2:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="INFO" monitorInterval="30">
    <Properties>
        <Property name="log-path">C:\logs</Property>
    </Properties>
    <Appenders>

        <!-- Default Console appender -->
        <Console name="console-log" target="SYSTEM_OUT">
            <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %p %c{1}:%M - %m%n" />
        </Console>

        <RollingFile name="fallback-log-appender"
            fileName="${log-path}/fallback.log"
            filePattern="${log-path}/archive/fallback-%d{yyyyMMddHHmmss}.log.gz">

            <PatternLayout>
                <pattern>%d{yyyy-MM-dd HH:mm:ss} %p %C{1}:%M - %m%n</pattern>
            </PatternLayout>

            <Policies>
                <SizeBasedTriggeringPolicy size="100 MB" />
                <CronTriggeringPolicy schedule="0 0/5 * ? * * *"/>
            </Policies>
        </RollingFile>


        <RollingFile name="nice-log-appender"
            fileName="${log-path}/nice-service.log"
            filePattern="${log-path}/archive/nice-service-%d{yyyyMMddHHmmss}.log.gz">

            <PatternLayout>
                <pattern>%d{yyyy-MM-dd HH:mm:ss} %p %C{1}:%M - %m%n</pattern>
            </PatternLayout>

            <Policies>
                <SizeBasedTriggeringPolicy size="50 MB" />
                <CronTriggeringPolicy schedule="0 0/5 * ? * * *"/>
            </Policies>
        </RollingFile>

    </Appenders>

    <Loggers>
        <Root level="trace">
            <AppenderRef ref="console-log" />
        </Root>

        <Logger name="fallback-logger" level="trace" additivity="false">
            <Appender-ref ref="fallback-log-appender" level="trace" />
        </Logger>

        <Logger name="nice-logger" level="trace" additivity="false">
            <Appender-ref ref="nice-log-appender" level="trace" />
        </Logger>

    </Loggers>
</Configuration>

Исключение, которое я получаю, это из log4j2:

[04/07/19 13.35.00:041 CEST] 000000ee SystemOut     O 2019-07-04 13:35:00,041 Log4j2-TF-7-Scheduled-6 ERROR Unable to delete file C:\logs\nice-service.log: java.nio.file.FileSystemException C:\logs\nice-service.log: Impossibile accedere al file. Il file è utilizzato da un altro processo.

Я ожидаю, что файл журнала gzip без проблем будет перемещен в папку архива после события прокрутки.

...