当前位置: 首页 > 知识库问答 >
问题:

我们如何让主线程等待异步日志记录完成(或者其他方式)

翁建弼
2023-03-14

我试图使用log4j2以编程方式创建异步记录器。

它在特定点之前工作正常,但之后会出现以下错误:

2019-12-25 13:36:15,503Log4j2-TF-1-AsyncLogger[AsyncContext@659e0bfd]-1 ERROR试图追加到未启动的appender控制台Appender

此外,由于此原因,仅打印部分日志。我的意思是,如果总共打印1000份日志,那么只打印800份。

示例代码如下:

public void log() {

    final ConfigurationBuilder<BuiltConfiguration> builder = ConfigurationBuilderFactory.newConfigurationBuilder();
    config = builder.build();
    ctx = Configurator.initialize(config);
    config = ctx.getConfiguration();
    ctx.start(config);
    ctx.updateLoggers();
    logger = ctx.getLogger(loggerName);
    logger.addAppender(attachConsoleAppender(ctx.getConfiguration(), appenderName));
    while (counter < 2000) {
        logger.error(testMessage + counter);
        counter++;
    }
    closeLogger();
}

private Appender attachConsoleAppender(Configuration config, String appenderName) {
    Appender consoleAppender = ConsoleAppender.newBuilder().setConfiguration(config).setName(appenderName)
            .withImmediateFlush(true).build();
    consoleAppender.start();
    return consoleAppender;
}

public void closeLogger() {

    config.getLoggerConfig(loggerName).getAppenders().get(appenderName).stop();
    config.getLoggerConfig(loggerName).removeAppender(appenderName);
    config.removeLogger(loggerName);
    ctx.updateLoggers();
    }
}

在我看来,问题在于异步记录器在其独立于main的线程中运行。

我移除记录器的逻辑是同步执行的,它首先被执行,这导致关闭appender并移除记录器,而另一个线程中的日志记录仍然没有完成。

我已经通过了多个链接,但没有得到太多的帮助:

Log4j2自定义追加器:尝试追加到未启动的追加器时出错

log4j:尝试附加到名为[…]的已关闭附加程序时出错

log4j:log4j:尝试附加到名为[stdout]的已关闭追加器时出错

https://issues.apache.org/jira/browse/LOG4J2-927

有什么办法来处理这种情况,它会是好的,仍然等待主线程直到日志记录完成或日志消息,即使主线程完成。以及我们如何才能实现它。

PS:上面的代码只是一个可以复制问题的示例。

我在log4j2中获得具有以下属性的异步记录器。组成部分属性:Log4jContextSelector=org。阿帕奇。登录中。log4j。果心异步的。AsyncLoggerContextSelector

共有2个答案

郝修为
2023-03-14

替换CloseLogger()方法或在org.apache.logging.log4j之前添加此调用。anager.shutdown;

乔伯寅
2023-03-14

我可以看到,您已经添加了所有全局变量,当线程执行closeLogger()函数时,它会从loggerconfig中删除appender,从而使后续线程无法写入日志。

在删除appender之前检查活动线程,希望这会有所帮助。

 类似资料:
  • 我打算在主线程中启动2个线程,主线程应该等到所有2个子线程完成,我就是这样做的。 在上面的代码中,确实让主线程等待子线程,但问题是,在第一个线程完成之前不会创建第二个线程。这不是我想要的。 我想要的是,这两个线程立即在主线程中创建,然后主线程等待它们完成。似乎做不到,是吗? 我想,也许我可以通过一个信号灯来完成这项工作,但还有别的方法吗?

  • 我正在编写一个WinForms应用程序,它将数据传输到USB HID类设备。我的应用程序使用了优秀的通用HID库V6.0,可以在这里找到。简单来说,当我需要向设备写入数据时,这是被调用的代码: 当我的代码退出while循环时,我需要从设备中读取一些数据。但是,设备无法立即响应,因此我需要等待此呼叫返回后再继续。由于当前存在,RequestToGetInputReport()声明如下: GetInp

  • 我试图为从服务调用异步函数的函数编写测试,但我一辈子都不知道如何让Jasmine在执行expect函数之前等待异步操作完成。 我试图使用Jasmine的“完成”功能,但我不知道如何实现它。 在本例中,只要 调用时,它立即跳转到expect并失败,因为异步操作尚未完成。

  • 我通读了Dart/flatter中的Async/Await/then,试图理解为什么aysnc函数中的Await不会等到完成后再继续。在我的UI中,有一个按钮调用一个异步方法来返回一个位置,该位置总是返回null,并且不等待函数完成。 该函数将调用推送到一个新的UI页面,该页面选择一个位置,并应返回一个结果。如何使该函数等待结果?我不是在使用异步吗?

  • 正如logback的文档所说,大多数appender本质上是同步的,但是如果我们将appender包装在异步appender中,那么线程将把数据推送到BlockingQueue中,如果有,比如说X-logback线程将从BlockingQueue获取数据并将其追加。这就是我对它的基本理解。 尝试使用JstackThread转储来测试这个。但是空手返回,没有回退线程的线索。 作为参考,请检查下面lo

  • 有时我看到一些线程还没有完成他们的工作,服务杀死那个线程,我怎么能强迫服务等待,直到线程完成他们的工作? 这是我的代码: 我看到了一些例外。future.is完成())块。我怎么能确保每一个未来是当执行者服务关闭?