asynchronous - 混合同步/异步日志记录 log4j 不起作用
问题描述
我正在尝试分析和实现混合同步和异步日志记录。我正在使用 Spring Boot 应用程序和 Disruptor API。我的 log4j 配置:
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug">
<Appenders>
<Console name="Console-Appender" target="SYSTEM_OUT">
<PatternLayout>
<pattern>
[%-5level] %d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %c{1} - %msg%n
</pattern>>
</PatternLayout>
</Console>
</Appenders>
<Loggers>
<AsyncLogger name="com.example.logging" level="debug">
<AppenderRef ref="Console-Appender"/>
</AsyncLogger>
<Root level="info">
<AppenderRef ref="Console-Appender"/>
</Root>
</Loggers>
演示类 1:
package com.example.logging;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
@SpringBootApplication
public class DemoApplication2 {
static Logger logger = LogManager.getLogger(DemoApplication2.class);
public static void main(String[] args) {
SpringApplication.run(DemoApplication2.class, args);
long startTime = System.currentTimeMillis();
for(int i = 0; i < 2000; i++) {
logger.debug("Async : " + i);
}
System.out.println("time taken:: " + (System.currentTimeMillis() - startTime));
}
}
使用上面的代码,我期望“System.out”应该在所有“调试”语句的日志记录之前打印,因为我正在为“调试”级别使用异步日志记录。因此,首先会记录少量调试器日志(例如,少量 100 或 150 个),然后应打印 SOP,然后应记录剩余的调试器日志。但是,当我运行我的应用程序时,所有调试器语句首先记录,然后 SOP 打印,这不是预期的结果。此外,如果我在“asynclogger”(<AsyncLogger name="com.example.logging" level="debug" additivity="false">
)中使用 additivity="false",那么我可以看到我预期的上述结果。现在我有第二个演示课:
package com.example.logging;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
@SpringBootApplication
public class DemoApplication3 {
static Logger logger = LogManager.getLogger(DemoApplication3.class);
public static void main(String[] args) {
SpringApplication.run(DemoApplication3.class, args);
long startTime = System.currentTimeMillis();
for(int i = 0; i < 2000; i++) {
logger.info("Sync : " + i);
}
System.out.println("time taken:: " + (System.currentTimeMillis() - startTime));
}
}
现在有了上面的课程,我期待所有的同步记录首先和 SOP 应该在所有信息日志之后打印。但是如果将“additivity="false" 添加到我的配置中,那么所有日志都是异步的。
最后,我无法同时配置同步和异步日志记录。请帮助和建议。
解决方案
我不确定你认为你在测试什么。
启用可加性后,日志事件将被复制并放置到 Disruptor 的 Ring Buffer 中,在那里它将被路由到不同线程上的控制台附加程序。将复制的事件放入缓冲区后,该事件将被传递到根记录器并在同一线程中路由到控制台 Appender。由于异步 Logger 和同步 Logger 都在做同样的事情,所以它们将花费大约相同的时间。所以我不太确定你为什么相信在 System.out 调用时会留下任何东西。
当您只使用异步记录器时,主线程除了将事件放入队列之外什么都不做,因此它会更快地响应,并且您的 System.out 消息很可能会在所有日志事件被写入之前出现。
我怀疑您忽略了一项非常重要的信息。当一个事件被路由到一个 Logger 时,在 LoggerConfig 上指定的与 Logger 关联的级别被检查。当可加性为真时,事件不会路由到父 Logger(没有一个)。它被路由到 LoggerConfig 的父 LoggerConfig。LoggerConfig 调用 isFiltered(event) 仅检查已在 LoggerConfig 上配置的过滤器。因此,即使您的 Root 记录器上有 level="info",仍然会记录通过 AsyncLogger 发送给它的调试事件。您必须将 ThresholdFilter 添加到 RootLogger 以防止这种情况。
推荐阅读
- spring - 在 JPA 中使用 CrudRepository save() 方法仅更新多个对象是否有任何限制?
- ffmpeg - FFmpeg 从文件“如果存在”中删除字幕
- apache-flink - 需要一些 flink-sql 流式处理的例子
- docker - 使用 UI 在给定时间停止或运行 docker 容器
- python - tkinter:如何动态更改树视图中的列数
- javascript - 如何使用 Three.js 将多个 3D 对象链接到列表按钮?
- python - 全局平均池化不影响训练速度
- c++ - 由于____chkstk_darwin,在 Catalina 上使用 Deployment 10.10 编译的 MacOS 应用程序在 < HighSierra 的版本上崩溃
- angular - Angular2+ - 克隆一个变量并不能阻止改变它
- xamarin - System.TypeLoadException:'无法从 typeref 解析带有令牌 010000a0 的类型(程序集中的预期类'Camera')'