如何使用 Java 代码配置 Logback 以设置日志级别?

Posted

技术标签:

【中文标题】如何使用 Java 代码配置 Logback 以设置日志级别?【英文标题】:How to configure Logback with Java code to set log level? 【发布时间】:2011-12-19 12:15:49 【问题描述】:

我想使用默认的 SLF4J + Logback 配置,除了将 org.springframework.data.document.mongodb 日志级别设置为 DEBUG

如何用 Java 代码做到这一点?

我没有使用 XML,这个决定是在运行时做出的。

【问题讨论】:

我希望会有更好的答案:这也适用于单元/功能/集成测试,人们经常希望在测试期间抑制噪音。不得不使用配置文件有点痛苦。 【参考方案1】:

以下内容对我有用,但通常这不是一个好主意。您的代码将依赖于 Logback(您不能选择 SLF4J 之后的其他日志框架)。

final org.slf4j.Logger logger = 
    org.slf4j.LoggerFactory.getLogger("test.package");
if (!(logger instanceof ch.qos.logback.classic.Logger)) 
    return;

ch.qos.logback.classic.Logger logbackLogger = 
    (ch.qos.logback.classic.Logger) logger;
logbackLogger.setLevel(ch.qos.logback.classic.Level.TRACE);
logger.trace("some log");

【讨论】:

如果你使用类名而不是包,上述方法将不起作用,因为获取的记录器是不同的实例。但是在使用包时,它是可以的,因为日志级别会传播给子级。【参考方案2】:

正如@palacsint 所说,依赖于logback-classic 并不是一个好主意。您可以使用 Java 的反射 API 实现您想要的。请注意,由于使用反射,这种方法会给您的程序带来一些开销。

用法:

LogbackUtils.setLogLevel("com.***.sample", "DEBUG")

代码:

public  static final String LOGBACK_CLASSIC        = "ch.qos.logback.classic";
public  static final String LOGBACK_CLASSIC_LOGGER = "ch.qos.logback.classic.Logger";
public  static final String LOGBACK_CLASSIC_LEVEL  = "ch.qos.logback.classic.Level";
private static final Logger logger                 = LoggerFactory.getLogger(LogbackUtils.class);

/**
 * Dynamically sets the logback log level for the given class to the specified level.
 *
 * @param loggerName Name of the logger to set its log level. If blank, root logger will be used.
 * @param logLevel   One of the supported log levels: TRACE, DEBUG, INFO, WARN, ERROR, FATAL,
 *                   OFF. @code null value is considered as 'OFF'.
 */
public static boolean setLogLevel(String loggerName, String logLevel)

    String logLevelUpper = (logLevel == null) ? "OFF" : logLevel.toUpperCase();

    try
    
        Package logbackPackage = Package.getPackage(LOGBACK_CLASSIC);
        if (logbackPackage == null)
        
            logger.info("Logback is not in the classpath!");
            return false;
        

        // Use ROOT logger if given logger name is blank.
        if ((loggerName == null) || loggerName.trim().isEmpty())
        
            loggerName = (String) getFieldValue(LOGBACK_CLASSIC_LOGGER, "ROOT_LOGGER_NAME");
        

        // Obtain logger by the name
        Logger loggerObtained = LoggerFactory.getLogger(loggerName);
        if (loggerObtained == null)
        
            // I don't know if this case occurs
            logger.warn("No logger for the name: ", loggerName);
            return false;
        

        Object logLevelObj = getFieldValue(LOGBACK_CLASSIC_LEVEL, logLevelUpper);
        if (logLevelObj == null)
        
            logger.warn("No such log level: ", logLevelUpper);
            return false;
        

        Class<?>[] paramTypes =   logLevelObj.getClass() ;
        Object[]   params     =   logLevelObj ;

        Class<?> clz    = Class.forName(LOGBACK_CLASSIC_LOGGER);
        Method   method = clz.getMethod("setLevel", paramTypes);
        method.invoke(loggerObtained, params);

        logger.debug("Log level set to  for the logger ''", logLevelUpper, loggerName);
        return true;
    
    catch (Exception e)
    
        logger.warn("Couldn't set log level to  for the logger ''", logLevelUpper, loggerName, e);
        return false;
    


// getFieldValue() method omitted for bravity from here,
// but available at GitHub link below.

包含测试的完整代码:Github Gist。

【讨论】:

以上是关于如何使用 Java 代码配置 Logback 以设置日志级别?的主要内容,如果未能解决你的问题,请参考以下文章

关于logback如何通过当前配置文件获取路径

Java可以如何实现文件的监听

Java日志框架-logback的介绍及配置使用方法(转)

如何使用SBT和Scala正确管理开发和生产中的logback配置?

14-Java之-Logback大型项目使用总结

Spring Boot系列一:默认日志logback配置解析