Дождитесь окончания асинхронного ведения журнала, прежде чем завершится поток slf4j / log4j2 - PullRequest
0 голосов
/ 22 февраля 2019

Я использую настройку асинхронного ведения журнала базы данных с помощью slf4j / log4j2.Все работает как положено.

Единственным недостатком является то, что иногда, когда сервер выключается, регистратор не завершает запись в базу данных (например, если перед выключением произошел выброс).

Я получаю:

ПРЕДУПРЕЖДЕНИЕ AsyncLoggerConfigDisruptor: время ожидания завершено после 0 МИЛЛИСЕКОНД Log4j2-TF-1-AsyncLoggerConfig-1 ОШИБКА Попытка добавить в базу данных незапущенного приложения * Заявитель * 10081009 *

И я теряю все, что было в буфере логгера.

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

Или, по крайней мере, для получения размера буфера, который все еще нужно записать?

В настоящее время я использую установку с синхронным файловым регистратором и асинхронным регистратором базы данных, поэтому данныевсе еще в файле ...

-> Изменить 02/28/19

Вот пример быстрого и грязного кода:

protected static final Logger logger = LoggerFactory.getLogger(App.class);

public static void main(String[] args) throws Exception {
    ExecutorService executor = Executors.newFixedThreadPool(5);
    for (int i = 0; i < 10; i++) {
        Runnable task = new TestLogging(i);            
        executor.submit(task);
    }
    executor.shutdown();
    System.out.println("Done");
    //LogManager.shutdown();
}

private static class TestLogging implements Runnable {

    private int i;

    public TestLogging(int i) {
        this.i=i;
    }

    public void run() {
        // Generate a big string for DB test
        StringBuffer b=new StringBuffer();
        IntStream.range(0, 1000).parallel().forEach(i -> b.append(UUID.randomUUID().toString()));
        // Writing to context for logging
        MDC.put("test", "test"+i);
        MDC.put("test1", b.toString());
        // Log 1000 lines 
        IntStream.range(0, 1000).forEach(j -> logger.error("Exception " + j + "-"+ i, new RuntimeException()));
    }
}

Конфигурация xml:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="WARN">
    <Appenders>
        <File name="MyFile" fileName="all.log" immediateFlush="false"
            append="false">
            <PatternLayout
                pattern="%d{yyy-MM-dd HH:mm:ss.SSS} tx.id=%X{test} tx.content=%X{test1} [%t] %-5level %logger{36} - %msg%n" />
        </File>
        <JDBC name="databaseAppender" tableName="log_test">
            <PoolingDriver connectionString="jdbc:oracle:thin:@centos.fritz.box:1521:orcl" userName="test"  password="test"  driverClassName="oracle.jdbc.driver.OracleDriver"/>
         <Column name="LOG_ID" pattern="%u" />
         <Column name="ENTRY_DATE" isEventTimestamp="true" />
         <Column name="LOGGER" pattern="%logger" />
         <Column name="LOG_LEVEL" pattern="%level" />
         <Column name="MESSAGE" pattern="%m" />
         <Column name="EXCEPTION" pattern="%throwable" />
         <Column name="ID" pattern="%X{test}" />
         <Column name="XML" pattern="%X{test1}" />
        </JDBC>
    </Appenders>
    <Loggers>
        <AsyncRoot level="info">
            <AppenderRef ref="databaseAppender" />
        </AsyncRoot>
        <Logger name="com.test" level="trace" includeLocation="true">
            <AppenderRef ref="MyFile" />
        </Logger>
    </Loggers>
</Configuration>

А для Oracle DDL:

CREATE TABLE "TEST"."LOG_TEST" 
   (    "LOG_ID" VARCHAR2(100 BYTE), 
    "ENTRY_DATE" TIMESTAMP (6), 
    "LOGGER" VARCHAR2(100 BYTE), 
    "LOG_LEVEL" VARCHAR2(100 BYTE), 
    "MESSAGE" CLOB, 
    "EXCEPTION" CLOB, 
    "ID" VARCHAR2(20 BYTE), 
    "XML" CLOB, 
     PRIMARY KEY ("LOG_ID"))

Если я использую LogManager.shutdown();

Регистрация даже не начинается.Без, в зависимости от БД, я получаю около 500-1000 строк в БД до появления ошибки.

Регистрация в реальной базе данных будет намного более разреженной, это всего лишь тест в худшем случае... и как уже упоминалось, регистрация в файле работает.Было бы неплохо иметь постоянную регистрацию в БД и файле, даже если служба выключена.

...