混合 sync/async 日志记录 log4j 不起作用
mixed sync/async logging log4j does not work
我正在尝试分析和实施混合同步和异步日志记录。我正在使用 Spring 启动应用程序和干扰器 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>
演示 class 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",那么我可以看到我预期的上述结果。现在我有第二个演示 class:
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));
}
}
现在有了上面的 class,我希望所有同步日志都先打印,SOP 应该在所有信息日志之后打印。但是,如果将“additivity="false" 添加到我的配置中,那么所有日志都是异步的。
最后,我无法同时配置同步和异步日志记录。请帮助和建议。
我不太确定你认为你在测试什么。
启用可加性后,日志事件将被复制并放入 Disruptor 的环形缓冲区,在那里它将被路由到不同线程上的控制台附加程序。将复制的事件放入缓冲区后,事件将传递给根记录器并路由到同一线程中的控制台附加程序。由于异步 Logger 和同步 Logger 都在做同样的事情,因此它们将花费大约相同的时间。所以我不太确定为什么您认为在 System.out 调用时会留下任何东西。
当您只使用异步记录器时,主线程除了将事件放入队列外什么都不做,因此它的响应速度会快得多,而且您的 System.out 消息很可能会出现在之前已写入所有日志事件。
我怀疑您忽略了一条非常重要的信息。当事件路由到 Logger 时,将检查 LoggerConfig 上指定的级别,该 Logger 与之关联。当可加性为真时,事件不会路由到父记录器(没有)。它被路由到 LoggerConfig 的父 LoggerConfig。 LoggerConfig 调用 isFiltered(event) 仅检查已在 LoggerConfig 上配置的过滤器。因此,即使您的 Root 记录器上有 level="info",仍会记录通过 AsyncLogger 发送给它的调试事件。您必须向 RootLogger 添加 ThresholdFilter 以防止出现这种情况。
我正在尝试分析和实施混合同步和异步日志记录。我正在使用 Spring 启动应用程序和干扰器 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>
演示 class 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",那么我可以看到我预期的上述结果。现在我有第二个演示 class:
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));
}
}
现在有了上面的 class,我希望所有同步日志都先打印,SOP 应该在所有信息日志之后打印。但是,如果将“additivity="false" 添加到我的配置中,那么所有日志都是异步的。
最后,我无法同时配置同步和异步日志记录。请帮助和建议。
我不太确定你认为你在测试什么。
启用可加性后,日志事件将被复制并放入 Disruptor 的环形缓冲区,在那里它将被路由到不同线程上的控制台附加程序。将复制的事件放入缓冲区后,事件将传递给根记录器并路由到同一线程中的控制台附加程序。由于异步 Logger 和同步 Logger 都在做同样的事情,因此它们将花费大约相同的时间。所以我不太确定为什么您认为在 System.out 调用时会留下任何东西。
当您只使用异步记录器时,主线程除了将事件放入队列外什么都不做,因此它的响应速度会快得多,而且您的 System.out 消息很可能会出现在之前已写入所有日志事件。
我怀疑您忽略了一条非常重要的信息。当事件路由到 Logger 时,将检查 LoggerConfig 上指定的级别,该 Logger 与之关联。当可加性为真时,事件不会路由到父记录器(没有)。它被路由到 LoggerConfig 的父 LoggerConfig。 LoggerConfig 调用 isFiltered(event) 仅检查已在 LoggerConfig 上配置的过滤器。因此,即使您的 Root 记录器上有 level="info",仍会记录通过 AsyncLogger 发送给它的调试事件。您必须向 RootLogger 添加 ThresholdFilter 以防止出现这种情况。