Logger slf4j未使用Logback配置级别

时间:2015-05-31 08:36:39

标签: java maven logging slf4j logback

  

即使我已将奖金奖励给下面的用户   试图帮助,原来的问题仍然没有答案。没有实际的   存在可行的解决方案以确保配置logback.groovy   日志记录在junit测试中得到尊重。测试加载了   logback配置它确实报告了正确的级别,但仍然是   实际测试记录(仅通过slf4j)处于任何或特定状态   水平

     

我知道其他人也遇到过同样的问题   由于控制台,大型项目的测试需要更长的时间,这很烦人   记录太冗长了。我不能继续投掷赏金   这个问题。我希望有人提出一个很好的解决方案   允许在不同级别正确配置测试日志记录   通过系统属性。然后,可以是不同的配置   为项目创建,以便测试能够配置为不同的日志记录阈值级别。

我的日志记录是通过logback.groovy文件

进行logback配置的

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

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

测试中的记录器不是问题所在 - 嗯 - 是的,是的 - 真正的问题是运行的代码段中的记录器(我所有程序记录器到处都是)设置为错误的日志记录级别。在配置程序测试时,他们没有掌握日志记录的内容。

但是,当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 个答案:

答案 0 :(得分:3)

我在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']);

答案 1 :(得分:1)

我们通常通过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)来控制外部依赖项的记录。

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