【问题标题】:Logger slf4j is not using the logback configured level记录器 slf4j 未使用 logback 配置的级别
【发布时间】:2015-08-13 20:18:31
【问题描述】:

即使我已将赏金奖励给以下拥有 试图提供帮助,原始问题仍未得到解答。没有实际 存在可行的解决方案以确保配置 logback.groovy 日志记录在 junit 测试中得到尊重。测试加载 logback 配置,它确实报告了正确的级别,但仍然是 实际测试记录(仅通过 slf4j)位于 ANY 或 TRACE 等级

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

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

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

但是,当 junit 测试运行时,由于某种原因,即使测试类 static @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
    }
}

【问题讨论】:

  • 我不知道它是否有帮助,但是 JUnit 安装了它自己的类加载器,这会干扰日志框架。
  • @lllogiq 我知道。 .... 那么为什么由 junit 启动的配置报告正确,即使个别测试不正确。以及如何解决这个问题?

标签: java maven logging slf4j logback


【解决方案1】:

我在 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(loglevel, ['ROOT']);

【讨论】:

  • 这很有帮助。我不确定它是否能解决问题,因为我会根据 Reactor 构建提供的属性在不同级别记录测试。但是谢谢你的提示。
【解决方案2】:

我们通常通过 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,谢谢你的七月,是的,你是对的。需要做的不仅仅是添加依赖项。我们还有一个 logback 配置器,它显式调用 SLF4JBridgeHandler.install()。我们的配置器还加载了 logback 配置文件,我忘记了这个调用。但我主要想指出一个问题的方向,即外部依赖项使用的多个日志库以及这些可以将不同日志库置于 logback 之下的桥梁。

【讨论】:

  • “我什至不知道” -> java.util.logging ... 而这并不像仅仅使用正确的依赖项那么容易- stackoverflow.com/questions/9117030/jul-to-slf4j-bridge
  • 一切都在使用 SLF4J。这就是为什么日志配置注册正确但测试所有日志都好像级别是 TRACE 或 ANY 对我来说是个谜。
  • 感谢您的参与。我给了你赏金,尽管这并不能解决问题。这是一个有价值的补充。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-08-07
  • 2014-07-18
  • 1970-01-01
  • 1970-01-01
  • 2017-05-06
  • 1970-01-01
相关资源
最近更新 更多