如何动态更改SLF4j或Log4J中的日志级别

问题描述 投票:0回答:6

最近遇到了Application

Loglevel
动态变化的情况。应用程序管理员可以从前端将其设置为
INFO/DEBUG/ WARN
。根据选择的日志级别,必须更改应用程序日志记录。

我确信记录器支持这种情况。我怎样才能实现这个目标?

java logging log4j slf4j
6个回答
19
投票

在 slf4j 中无法动态更改日志级别,但 slf4j 的某些后端支持它,包括 log4j。

这个解决方案对我有用:

org.apache.log4j.Logger logger4j = org.apache.log4j.Logger.getRootLogger();
logger4j.setLevel(org.apache.log4j.Level.toLevel("ERROR"));

(来源:http://prateep.info/2015/12/12/Dynamically-change-log-level-in-SLF4j-Log4J-with-Standalone-Java-Class/

此解决方案的缺点是它直接使用后端,在使用 slf4j 时不应该这样做,因为 slf4j 的目的是提供远离您正在使用的特定后端的抽象。


10
投票

考虑 Logback http://logback.qos.ch/ - “流行的 log4j 项目的后继者,继承了 log4j 的不足”。如果指示这样做,logback-classic 将扫描其配置文件中的更改,并在配置文件更改时自动重新配置自身。此外,您可以使用 JMX 控制 Logback 的日志记录级别。


7
投票

对于 SLF4J,此代码将演示如何以编程方式(在运行时)控制记录器级别。

这个答案假设您正在使用Logback Classic

假设默认 SLF4J 配置:

final Logger logger = LoggerFactory.getLogger(LoggerListener.class);
// These five statements will log.
logger.error("error");
logger.warn("warn");
logger.info("info");
logger.debug("debug");
logger.trace("trace");

final ch.qos.logback.classic.Logger logger2 = (ch.qos.logback.classic.Logger) logger;
@Nullable
final Level nullablePrevLevel = logger2.getLevel();
final Level level = Level.INFO;
logger2.setLevel(level);
logger.info("Change log level: [{}]->[{}]", nullablePrevLevel, level);

// These three statements will log.
logger.error("error");
logger.warn("warn");
logger.info("info");
// These two statements will not log.
logger.debug("debug");
logger.trace("trace");

6
投票

我必须使用 log4j 执行一次此操作。我能弄清楚如何做到这一点的唯一方法是在 Logger 对象上调用 getAllAppenders。然后,循环遍历附加程序。如果他们扩展 AppenderSkeleton 类(他们应该),他们将拥有 setThreshold 方法。使用您的新级别作为参数调用此方法。对记录器的后续调用应使用新级别。这将在内存中设置级别,但不会在 log4j 配置文件中设置级别。您可能也想这样做,除非当管理员通过前端更改级别时它会自动更改。如果可以的话,您可能需要考虑遵循 Evgeniy Dorofeev 的建议并使用 logback。听起来好像会更容易。


3
投票

slf4j
版本
1.7.26
开始,我能够更改日志记录级别。

这是源文件夹中的

logback.xml
。如果是 Spring Boot 应用程序,您可能希望将其放置在 resources 文件夹中。

<configuration scan="true" scanPeriod="20000">
    <include file="C:/logback-ext.xml"/>
</configuration>

logback-ext.xml
文件保存在任何外部位置。
scanPeriod
以毫秒为单位。如果失败,请尝试使用
include resource
而不是
include file
中的
logback.xml

<included>
  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
      <pattern>
          %d{yyyy-MM-dd HH:mm:ss} %-5p [%t] --- %c{1}.%M:%L :: %m %n
      </pattern>
    </encoder>
  </appender>
  <root level="INFO">
    <appender-ref ref="STDOUT" />
  </root>
</included>

我能够更改日志记录级别、日志记录模式、附加/分离新的附加程序以及添加/删除附加程序。

这些是

pom.xml

中的依赖项
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.3</version>
<scope>compile</scope>
</dependency>
<dependency>
    <groupId>org.slf4j</groupId>
    <artifactId>slf4j-api</artifactId>
    <version>1.7.25</version>
</dependency>

干杯!


0
投票

我们正在将这样的动态日志调整构建为一项服务,是的,slf4j 本身不支持这一点。我们通过在每个流行的日志框架中进行实现,然后发布不同的 Maven 工件来解决这个问题。

您可以通过使用过滤 API 获得更好的控制/精度,而不是在根记录器上设置级别。例如

public abstract class BaseTurboFilter extends TurboFilter {

  @Override
  public FilterReply decide(Marker marker, Logger logger, Level level, String s, Object[] objects, Throwable throwable) {
    if (YOUR_LOGIC) {
      return FilterReply.ACCEPT;
    } 
    return FilterReply.NEUTRAL;
  }
}

Logback Turbo 过滤器中的完整示例

Log4j2 AbstractLoggingListener 中的完整示例

© www.soinside.com 2019 - 2024. All rights reserved.