Logger slf4j не использует настроенный уровень logback

Несмотря на то, что я получил награды пользователям ниже, которые попытался помочь, первоначальный вопрос остается без ответа. Нет фактических существует работоспособное решение, обеспечивающее настройку logback.groovy регистрация выполняется в рамках тестов junit. Тесты загружают logback config, и он сообщает правильный уровень, и все же фактическое ведение журнала (исключительно через slf4j) находится в ЛЮБОЙ или TRACE уровень

Я знаю, что другие столкнулись с этой проблемой, и это очень раздражает, когда тесты для крупных проектов занимают намного больше времени из-за консоли запись слишком многословна. Я не могу продолжать бросать щедроты на этот вопрос. Я надеюсь, что кто-то придумает хорошее решение, которое позволяет вести корректную настройку протоколов тестирования на разных уровнях через системное свойство. Тогда могут быть разные конфигурации созданный для проекта, чтобы тесты могли настраиваться на разных пороговых уровнях регистрации.

Мой журнал настраивается с помощью logback через файл logback.groovy

Теперь, когда мой проект Maven POM, который объединяет все другие проекты, запускается, он передает им все свойство System, чтобы установить правильный уровень ведения журнала.

Однако, когда тесты junit запускаются, по какой-то причине регистратор не поднимает правильный уровень, даже если тестовые классы static @beforeClass обеспечивают правильную настройку журнала.

Это не Loggers в тестах, это проблема, - хорошо - да, тоже..., Реальная проблема заключается в том, что регистраторы в разделе кода, которые запускаются (все мои программы регистрируются везде), установлен неверный уровень ведения журнала. Они не собирают то, что регистрируется, когда настроены программные тесты.

Тем не менее, проекты сообщают о правильности, когда 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 [email protected] - Added status listener of type [ch.qos.logback.core.status.OnConsoleStatusListener]
01:22:15,290 |-INFO in [email protected] - 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 [email protected] - Adding ReconfigureOnChangeFilter as a turbo filter
01:22:15,312 |-INFO in [email protected] - About to instantiate appender of type [ch.qos.logback.core.ConsoleAppender]
01:22:15,316 |-INFO in [email protected] - 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 [email protected] - Setting level of logger [ROOT] to INFO
01:22:15,532 |-INFO in [email protected] - 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
    }
}

Ответ 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']);

Ответ 2

Обычно мы отправляем все записи через slf4j, а затем настраиваем ведение журнала с помощью журнала. Поэтому наши зависимости 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, и он настроен с ошибкой.

Поэтому вам может понадобиться использовать один из мостов (например, jcl-over-slf4j), чтобы управлять ведением внешних зависимостей.

Изменить: Павел Хорал, спасибо за смещение, и да, вы правы. Нужно сделать немного больше, чем просто добавить зависимости. У нас также есть конфигуратор logback, который явно вызывает SLF4JBridgeHandler.install(). Наш конфигуратор также загружает конфигурационный файл журнала, и я забыл об этом вызове. Но я в основном хотел указать на проблему с несколькими библиотеками журналов, используемыми внешними зависимостями, и на эти мосты, которые могут помещать разные библиотеки журналов под крышей журнала.