【问题标题】:How to dynamically change log level in SLF4j OR Log4J如何在 SLF4j 或 Log4J 中动态更改日志级别
【发布时间】:2012-11-06 17:39:00
【问题描述】:

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

我确信记录器支持这种情况,但不知道如何实现这一点。如果你们对此有任何想法/想法,请告诉我。

提前感谢您的帮助。

-纳伦德拉

【问题讨论】:

  • 您不能使用 SLF4J API 执行此操作;您必须使用自己的 API 配置日志记录后端(在您的情况下为 log4j)。
  • 您想更改某些消息发送到日志框架的级别,还是用于过滤写入日志的消息的级别?
  • 你能告诉我两者的区别吗?
  • 实际上有三种改变日志级别的方法。 (1) 更改 appender 输出的所有日志记录的级别,(2) 更改特定类记录器的日志记录输出级别,以及 (3) 更改代码中各个位置的单个日志记录语句的级别。使用SLF4j 你不能做#3,但如果你使用logger.log("stuff", LEVEL); 你可以在log4j 中,因为LEVEL 可能来自一个变量。后者仅在非常特定的情况下才需要。所以很可能 Narendra 意味着改变每个 appender 的日志级别。

标签: java logging log4j slf4j


【解决方案1】:

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

【讨论】:

  • 看起来 Logback 与 SLF4j 结合使用。我会试试这个,看看 Logback 有什么可能性。
【解决方案2】:

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

【讨论】:

    【解决方案3】:

    在 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 的目的是提供一个远离你正在使用的特定后端的抽象。

    【讨论】:

    • 那么如何使用 slf4j 解决这个问题呢?有什么想法吗?
    【解决方案4】:

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

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

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

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

    <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>
    

    干杯!

    【讨论】:

      【解决方案5】:

      对于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) logger2;
      @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");
      

      【讨论】:

        猜你喜欢
        • 2011-06-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-07-25
        • 2010-12-16
        • 1970-01-01
        • 2018-04-14
        • 1970-01-01
        相关资源
        最近更新 更多