Logger slf4j未使用Logback配置级别

尽管我已经向下面尝试过帮助的用户颁发奖金,但最初的问题仍未得到答复 . 没有实际可行的解决方案来确保在junit测试中遵守logback.groovy配置的日志记录 . 测试加载了logback配置,它确实报告了正确的级别,但实际的测试记录(仅通过slf4j)仍处于ANY或TRACE级别我知道其他人遇到了同样的问题,并且在测试大型项目时非常烦人由于控制台日志记录过于冗长,需要花费更长时间 . 我无法继续向这个问题投掷赏金 . 我希望有人提出一个很好的解决方案,允许通过系统属性在不同级别正确配置测试日志 . 然后,可以为项目创建不同的配置,以便可以在不同的日志记录阈值级别配置测试 .

我的日志记录是通过logback.groovy文件进行logback配置的

现在,当我的Maven POM项目聚合所有其他项目时,它会传递所有System属性以设置正确的日志记录级别 .

但是,当junit测试运行时,由于某种原因,即使测试类静态@beforeClass确保正确配置了logback, Logger 也不会获取正确的级别 .

测试中的 Logger 不是问题所在 - 嗯 - 是的,也是 - , the real problem is that the loggers in the code sections that run (all my programs loggers everywhere) are set to the wrong logging level. They are not picking up what the logging is when the program tests are configured.

但是,当logback使用logback.goovy文件初始化时,项目报告正确 . 但是,实际日志记录级别设置为TRACE或ALL

从下面的输出中可以看出,logback已配置为INFO . 但TRACE(最后一行)的第一个项目日志声明表明没有被提取 .

救命 .

-------------------------------------------------------
 T E S T S
-------------------------------------------------------
Running groovy.text.StreamingTemplateEngineTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 1.245 sec
Running net.abcd.templating.InlinerTest
01:22:15,265 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - Added status listener of type [ch.qos.logback.core.status.OnConsoleStatusListener]
01:22:15,290 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - Setting ReconfigureOnChangeFilter scanning period to 5 minutes
01:22:15,290 |-INFO in ReconfigureOnChangeFilter{invocationCounter=0} - Will scan for changes in [[C:\Users\ABDC\Dropbox\workspace\abcd\AbcdTemplating\conf\logback.groovy]] every 300 seconds. 
01:22:15,290 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - Adding ReconfigureOnChangeFilter as a turbo filter
01:22:15,312 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
01:22:15,316 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - Naming appender as [STDOUT]
***********************************************************

LOGGING MODE PROPERTY 'net.abcd.logging.level' SET TO: [info]
IT CAN BE SET TO: OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL, INFO

***********************************************************
getLogLevel() returned 'INFO'
01:22:15,496 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - Setting level of logger [ROOT] to INFO
01:22:15,532 |-INFO in ch.qos.logback.classic.gaffer.ConfigurationDelegate@1e8c3cb - Attaching appender named [STDOUT] to Logger[ROOT]
01:22:15.846 [main] TRACE net.abcd.templating.Inliner - Document:

我的logback.groovy文件是:

displayStatusOnConsole()
scan('5 minutes')  // Scan for changes every 5 minutes.
setupAppenders()
setupLoggers()

def displayStatusOnConsole() {
    statusListener OnConsoleStatusListener 
}

def setupAppenders() {
    appender('STDOUT', ConsoleAppender) {
        encoder(PatternLayoutEncoder) {
            pattern = "%d{HH:mm:ss.SSS} [%thread] %-5level %-16logger{50} - %msg%n"
        }
    }
}


def setupLoggers() {    
    def loglevel = getLogLevel() 
    println("getLogLevel() returned '${loglevel}'")
    root(loglevel, ['STDOUT'])
}

def getLogLevel() {
    def mode = System.getProperty('net.abcd.logging.level', '')
    println("***********************************************************")
    println("")
    println("LOGGING MODE PROPERTY 'net.abcd.logging.level' SET TO: [${mode}]")
    println("IT CAN BE SET TO: OFF, ERROR, WARN, INFO, DEBUG, TRACE, ALL, INFO")
    println("")
    println("***********************************************************")
    switch(mode.toLowerCase()){
    case 'off':
        return OFF
    case 'error':
        return ERROR
    case 'warn':
        return WARN
    case 'info':
        return INFO
    case 'debug':
        return DEBUG
    case 'trace':
        return TRACE
    case 'all':
        return ALL
    default:
        return INFO
    }
}

回答(2)

3 years ago

我在junit测试中遇到了类似的问题 . 我找不到一个好的解决方案 . 我在下面的工作中使用过:

import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger;
import org.slf4j.LoggerFactory;
...
static Logger logger;
static{
   // Logger.ROOT_LOGGER_NAME == "ROOT"
   logger = ((Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME));
   logger.setLevel(Level.INFO);
}

...

我认为在你的情况下,某个库使用它自己的ConsoleAppender实例,其名称不是'STDOUT' . 我希望设置root日志级别可以解决问题 .

root(loglevel, ['ROOT']);

3 years ago

我们通常通过slf4j路由每个日志记录,然后使用logback配置日志记录 . 所以我们的Maven依赖关系看起来像:

<dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jcl-over-slf4j</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>log4j-over-slf4j</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jul-to-slf4j</artifactId>
        <version>${slf4j.version}</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-core</artifactId>
        <version>${logback.version}</version>
    </dependency>
    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>${logback.version}</version>
    </dependency>

因此,如果某些依赖项使用java-commons-logging(jcl),log4j或java.util.logging(jul),那么它的日志记录将被桥接到slf4j . 应用程序日志记录也使用slf4j,而不是使用logback配置 .

因此,您可能需要使用其中一个桥(例如jcl-over-slf4j)来控制外部依赖项的日志记录 .

Edit: Pavel Horal,谢谢jul,是的,你是对的 . 人们需要做的不仅仅是添加依赖项 . 我们还有一个logback配置器,它显式调用SLF4JBridgeHandler.install() . 我们的配置程序还加载了logback配置文件,我忘记了这个调用 . 但我主要想指出外部依赖项使用的多个日志记录库的问题,以及这些可以将不同的日志记录库置于logback之上的桥 .