JUL в SLF4J мост - PullRequest
       61

JUL в SLF4J мост

60 голосов
/ 02 февраля 2012

В настоящее время я наблюдаю, что сторонняя библиотека (а именно restfb) использует java.util.logging, и я вижу, что эти журналы заканчиваются в STDOUT, даже если у меня не настроен консольный приложение SLF4J в моем выходе .xml. У меня также есть мост jul-to-slf4j в моем классе. Мост jul-to-slf4j только ведет журнал к appenders, настроенным logback, когда мост установлен, или он также входит в stdout?

Ответы [ 5 ]

77 голосов
/ 02 февраля 2012

Вам нужно позвонить SLF4JBridgeHandler.install().Вам также необходимо включить все уровни журналов в корневом логгере (причина в приведенной ниже выдержке) в java.util.logging и удалить приложение консоли по умолчанию.

Этот обработчик перенаправит журналирование jul на SLF4J.Однако, только журналы, включенные в jul, будут перенаправлены.Например, если оператор журнала, вызывающий jul logger, отключил этот оператор, он по определению не достигнет ни одного экземпляра SLF4JBridgeHandler и не может быть перенаправлен.

Весь процесс может быть выполнен следующим образом:

import java.util.logging.Logger;
import org.slf4j.bridge.SLF4JBridgeHandler;

SLF4JBridgeHandler.removeHandlersForRootLogger();
SLF4JBridgeHandler.install();
Logger.getLogger("").setLevel(Level.FINEST); // Root logger, for example.

Вы можете установить уровень выше, чем самый лучший, из соображений производительности, но вы не сможете включить эти журналы, не включив их сначала в java.util.logging (по причине, упомянутой выше в отрывке).

35 голосов
/ 28 июня 2012

Как упоминалось в javadocs для SLF4JBridgeHandler , вы можете либо установить SLF4JBridgeHandler программно, вызвав:

 // Optionally remove existing handlers attached to j.u.l root logger
 SLF4JBridgeHandler.removeHandlersForRootLogger();  // (since SLF4J 1.6.5)

 // add SLF4JBridgeHandler to j.u.l's root logger, should be done once during
 // the initialization phase of your application
 SLF4JBridgeHandler.install();

, либо через logging.properties

 // register SLF4JBridgeHandler as handler for the j.u.l. root logger
 handlers = org.slf4j.bridge.SLF4JBridgeHandler

Asдля производительности, в разделе jul-to-slf4j bridge обсуждается эта проблема.По сути, поскольку вы уже используете logback, включение LevelChangePropagator должно обеспечить хорошую производительность независимо от нагрузки.

12 голосов
/ 06 апреля 2017

Я использую SLF4J и новый драйвер Postgres 42.0.0

Согласно changelog используется java.util.logging

Чтобы иметь журналы драйверов достаточно:

  1. Добавить мост jul-to-slf4j :

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>jul-to-slf4j</artifactId>
        <version>${slf4j.version}</version>
        <scope>runtime</scope>
    </dependency>
    
  2. Добавить в logback.xml (logback-test.xml)

    <contextListener class="ch.qos.logback.classic.jul.LevelChangePropagator">
        <resetJUL>true</resetJUL>
    </contextListener>
    
    <appender ...
    
    <logger name="org.postgresql" level="trace"/>`
    
  3. Добавить код

    static {
        SLF4JBridgeHandler.install();
    }
    
3 голосов
/ 03 января 2014

Мое решение:

SLF4JBridgeHandler.install();
java.util.logging.LogManager.getLogManager().getLogger("").setLevel( Level.INFO);

помещая jul-to-slf4j на библиотеки приложений или библиотеки Glassfish, они перенаправляют JUL на SLF4J (и, следовательно, в моем случае на LOG4J)

тогда для Джерси вы могли бы сделать что-то вроде:

<logger name="com.sun.jersey" additivity="false">
    <level value="WARN" />
    <appender-ref ref="JVM" />
    <appender-ref ref="CONSOLE" />
</logger>   

<logger name="com.sun.common.util.logging" additivity="false">
    <level value="ERROR" />
    <appender-ref ref="JVM" />
    <appender-ref ref="CONSOLE" />
</logger>

последний конфиг, чтобы избежать загрязнения другими регистраторами

2 голосов
/ 14 января 2015

Решение, которое кажется хорошим (учитывая обстоятельства с мостом JUL) и работает для меня, так как мне нужно только написать все в logback.groovy файл .

  1. ( Если вы не используете logback.groovy конфигурации или logback на всех , конечно, вы должны поставить логику часть в некотором классе (например, как class MyApp { static { /* log init code here */ } ... }) .)

  2. ЦСИ / logback.groovy

    import org.slf4j.bridge.SLF4JBridgeHandler
    import ch.qos.logback.classic.jul.LevelChangePropagator
    
    // for debug: just to see it in case something is logging/initialized before
    System.out.println( 'my myapp logback.groovy is loading' )
    
    // see also: http://logback.qos.ch/manual/configuration.html#LevelChangePropagator
    // performance speedup for redirected JUL loggers
    def lcp = new LevelChangePropagator()
    lcp.context = context
    lcp.resetJUL = true
    context.addListener(lcp)
    
    // needed only for the JUL bridge: http://stackoverflow.com/a/9117188/1915920
    java.util.logging.LogManager.getLogManager().reset()
    SLF4JBridgeHandler.removeHandlersForRootLogger()
    SLF4JBridgeHandler.install()
    java.util.logging.Logger.getLogger( "global" ).setLevel( java.util.logging.Level.FINEST )
    
    def logPattern = "%date |%.-1level| [%thread] %20.20logger{10}|  %msg%n"
    
    appender("STDOUT", ConsoleAppender) {
        encoder(PatternLayoutEncoder) {
            pattern = logPattern
        }
    }
    
    /*// outcommenting in dev will not create dummy empty file
    appender("ROLLING", RollingFileAppender) {  // prod
        encoder(PatternLayoutEncoder) {
            Pattern = "%date %.-1level [%thread] %20.20logger{10}  %msg%n"
        }
        rollingPolicy(TimeBasedRollingPolicy) {
            FileNamePattern = "${WEBAPP_DIR}/log/orgv-fst-gwt-%d{yyyy-MM-dd}.zip"
        }
    }
    */
    
    appender("FILE", FileAppender) {  // dev
    
        // log to myapp/tmp (independent of running in dev/prod or junit mode:
    
        //System.out.println( 'DEBUG: WEBAPP_DIR env prop:  "."='+new File('.').absolutePath+',  \${WEBAPP_DIR}=${WEBAPP_DIR},  env=' + System.getProperty( "WEBAPP_DIR" ))
        String webappDirName = "war"
        if ( new File( "./../"+webappDirName ).exists() )  // we are not running within a junit test
            file = "../tmp/myapp.log"
        else  // junit test
            file = "tmp/myapp-junit-tests.log"
    
        encoder(PatternLayoutEncoder) { pattern = logPattern }
    }
    
    // without JUL bridge:
    //root(WARN, ["STDOUT", "ROLLING"])  // prod
    //root(DEBUG, ["STDOUT", "FILE"])  // dev
    
    // with JUL bridge: (workaround: see links above)
    def rootLvl = WARN
    root(TRACE, [/*"STDOUT",*/ "FILE"])
    // I manually added all "root package dirs" I know my libs are based on to apply
    // the root level to the second "package dir level" at least
    // depending on your libs used you could remove entries, but I would recommend
    // to add common entries instead (feel free to edit this post if you like to
    // enhance it anywhere)
    logger( "antlr", rootLvl )
    logger( "de", rootLvl )
    logger( "ch", rootLvl )
    logger( "com", rootLvl )
    logger( "java", rootLvl )
    logger( "javassist", rootLvl )
    logger( "javax", rootLvl )
    logger( "junit", rootLvl )
    logger( "groovy", rootLvl )
    logger( "net", rootLvl )
    logger( "org", rootLvl )
    logger( "sun", rootLvl )
    
    
    // my logger setup
    
    logger( "myapp", DEBUG )
    
    
    //logger( "org.hibernate.SQL", DEBUG )  // debug: log SQL statements in DEBUG mode
    //logger( "org.hibernate.type", TRACE )  // debug: log JDBC parameters in TRACE mode
    logger( "org.hibernate.type.BasicTypeRegistry", WARN )  // uninteresting
    
    scan("30 seconds")  // reload/apply-on-change config every x sec
    

(рекомендуется для использования мной, поскольку вы можете реагировать на переменные / функции Java-кода, как показано здесь, например, SLF4JBridgeHandler или каталог журнала, относящийся к webappDirName )

(оставил файл завершенным, так как он дает лучшее представление о том, как все можно настроить или как исходный шаблон)

(может иметь отношение к кому-либо - мой env: slf4j 1.7.5, logback 1.1.2, groovy 2.1.9 )

...