等待异步日志记录完成,直到线程结束slf4j / log4j2

时间:2019-02-22 11:30:20

标签: asynchronous logging log4j2 slf4j

我正在通过slf4j / log4j2使用异步数据库日志记录设置。一切都按预期进行。

唯一的缺点是,有时在服务器关闭时,记录器尚未完成对数据库的写入(例如,在关闭前是否有突发事件)。

我得到:

  

WARN AsyncLoggerConfigDisruptor:0后关闭超时   MILLISECONDS Log4j2-TF-1-AsyncLoggerConfig-1错误尝试附加   到未启动的附加程序databaseAppender

我失去了记录缓冲区中的所有内容。

slf4jlog4j2中是否有一种方法可以等待异步记录器完成(例如,任务结束时的阻塞调用)?

还是至少要获得缓冲区的大小,仍然需要写入?

当前,我使用带有同步文件记录器和异步数据库记录器的安装程序,因此数据仍在文件中...

->编辑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行。

实际数据库中的日志记录将更加稀疏,这只是最坏的测试……而且如上所述,文件中的日志记录有效。即使关闭了服务,也要在数据库和文件中保持一致的日志记录,这还是很好的。

0 个答案:

没有答案