java - 暂时提高多线程服务中的log4j2记录器级别

标签 java multithreading log4j2

这里有一个很长的问题要问 Log4j2 专家。

我有一项服务:

  1. 有非常严格的性能要求
  2. 使用 log4j2 进行大量日志记录调用。

典型的调用是门控的,例如:

if ( LOG.isInfoEnabled() ) {
  LOG.info("everything's fine"); 
}

由于日志消息的数量和性能需求,该服务通常会在日志记录设置为 WARN 的情况下运行(即消息不多)。

但是,我被要求在服务调用中构建一个参数,如果给出该参数,将导致它:

  1. 暂时将日志记录级别提高到参数中请求的级别(例如 INFO 或 TRACE)
  2. 添加 WriterAppender 以捕获 PrintWriter 中的日志记录。
  3. PrintWriter 日志数据附加到请求响应中。

很明显,由于我在每个日志记录调用周围设置了门控,我实际上需要暂时提高日志记录级别,如下所示:

LoggerContext ctx = (LoggerContext) LogManager.getContext(false);
Configuration cfg = ctx.getConfiguration();
LoggerConfig loggerCfg = cfg.getLoggerConfig("com.mycompany.scm");
loggerCfg.setLevel(logLevel);
.. other code to add `WriterAppender` ...
ctx.updateLoggers();

但我有一个直接的问题,因为它导致日志记录也进入服务的日志文件。这可能不是世界末日,但如果可能的话,我想避免这种情况。

我通过让默认日志记录通过按级别过滤的附加程序来做到这一点,这样即使打开日志记录,它也不会写入比默认日志文件中所需的更详细的任何消息。 (像这样,来 self 的 .properties 文件):

appenders=scm_warn, scm_info 

appender.scm_warn.type = Console
appender.scm_warn.name = SCM_WARN
appender.scm_warn.layout.type = PatternLayout
appender.scm_warn.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
appender.scm_warn.filter.threshold.type = ThresholdFilter
appender.scm_warn.filter.threshold.level = warn

appender.scm_info.type = Console
appender.scm_info.name = SCM_INFO
appender.scm_info.layout.type = PatternLayout
appender.scm_info.layout.pattern = %d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
appender.scm_info.filter.threshold.type = ThresholdFilter
appender.scm_info.filter.threshold.level = info

loggers = coreConfigurator

logger.coreConfigurator.name = com.mycompany.scm
logger.coreConfigurator.level = warn
logger.coreConfigurator.additivity = false   # do not let configurator log messages get processed by client application's parent or root logger.
logger.coreConfigurator.appenderRefs = core
logger.coreConfigurator.appenderRef.core.ref = SCM_WARN

...这样,即使日志记录级别增加,额外的消息也不会进入主日志文件(我只希望它们进入我的 PrintWriter)。

现在,问题来了!

如何暂时提高当前线程的日志级别(就像我在上面的代码中尝试做的那样)?

如果同时有三 (3) 个服务调用,我...

  1. ...希望每个添加的 Appender 只写入由创建该 Appender 的线程生成的日志消息。
  2. ...希望每个添加的 Appender 在添加它的请求完成后被删除。
  3. ...希望日志记录级别重置回原来的状态,只要没有其他打开此日志记录参数的请求仍在处理中。

理想情况下,我认为这听起来像是我希望每个线程都有一个完全独立的日志记录上下文。那可能吗?关于如何做到这一切有什么想法吗?

最佳答案

您可以使用自定义 Context Selector每个线程有不同的上下文,但是当多个线程想要写入同一个日志文件时,这可能会导致问题,因此可能不是一个可行的选择。

另一种方法是编写一个自定义Appender,它使用ThreadLocal来存储StringWriter。如果尚未为线程建立StringWriter,则追加的内容将跳过日志记录。此自定义 Appender 应添加到 Log4J 配置文件中,以便它始终存在并接收日志条目。

这样,您可以通过创建 StringWriter 并将其分配给 ThreadLocal 来启用特定线程的日志记录,运行代码,然后清除 ThreadLocal > 并从StringWriter获取记录的信息。由于任何线程最初都没有 StringWriter,因此追加器不会执行任何操作,因此不会以任何明显的方式影响性能。

您仍然需要执行已经在执行的级别升级,并在其他附加程序上使用过滤器。

关于java - 暂时提高多线程服务中的log4j2记录器级别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57695811/

相关文章:

java - 汉诺塔游戏中钉子和圆盘的 ArrayList 的 ArrayList

Java - 单击按钮后绘制圆圈

java - 向 LDAP 服务器代理 HTTP 摘要认证请求

python - python子进程中的线程行为很奇怪

java - Log4j2 RollingFile Appender - 在每个日志文件的开头添加自定义信息

java - 如何为 ResponseEntity<> 返回 'Integer' 类型并在 api 页面上获取结果?

Python 线程返回值

c - Linux中进程和线程的区别

java - 如何以编程方式正确配置 log4j2?

java - log4j2 扩展 Logger 类