77

私は現在、サード パーティのライブラリ (つまり、restfb) が java.util.logging を使用していることを確認しています。また、logback.xml で SLF4J コンソール アペンダーを構成していなくても、これらのログが STDOUT で終了することを確認しています。また、クラスパスに jul-to-slf4jブリッジがあります。jul-to-slf4j ブリッジは、ブリッジのインストール時に logback によって構成されたアペンダにのみログを記録しますか、それとも stdout にもログを記録しますか?

4

5 に答える 5

109

に電話する必要がありますSLF4JBridgeHandler.install()。また、java.util.logging でルート ロガー (以下の抜粋の理由) ですべてのログ レベルを有効にし、デフォルトのコンソール アペンダーを削除する必要があります。

このハンドラーは、jul ロギングを SLF4J にリダイレクトします。ただし、7 月に有効化されたログのみがリダイレクトされます。たとえば、jul ロガーを呼び出すログ ステートメントがそのステートメントを無効にした場合、定義により、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最初にログを有効にしないとログをオンにすることはできません (上記の抜粋で述べた理由により)。

于 2012-02-02T17:44:11.790 に答える
45

SLF4JBridgeHandlerの javadoc に記載されているように、以下を呼び出してプログラムで 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

パフォーマンスに関しては、jul-to-slf4jブリッジのセクションでこの問題について説明しています。要するに、既に logback を使用しているため、LevelChangePropagator を有効にする、負荷に関係なく良好なパフォーマンスが得られるはずです。

于 2012-06-28T12:49:33.080 に答える
5

私の解決策:

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

アプリ ライブラリまたはグラスフィッシュ ライブラリに jul-to-slf4j を配置すると、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>

最後の設定は、他のロガーによって汚染されないようにすることです

于 2014-01-03T09:22:27.013 に答える
4

logback.groovyファイルにすべてを書き込むだけでよいので、(JUL ブリッジの状況を考慮して)適切に機能するソリューションです。

  1. ( logback.groovy構成またはlogbackをまったく使用していない場合は、もちろん、ロジック部分を何らかのクラス (たとえばclass MyApp { static { /* log init code here */ } ... })に配置する必要があります。)

  2. src/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
    

( SLF4JBridgeHandlerやwebappDirNameに関するログ ディレクトリなど、ここで確認できるように、Java コード変数/関数に反応できるため、私が使用することをお勧めします)

(すべてをどのようにセットアップできるか、または開始テンプレートとしてより良い印象を与えるため、ファイルを完全なままにしておきます)

(誰かに関連している可能性があります - 私の環境: slf4j 1.7.5, logback 1.1.2, groovy 2.1.9 )

于 2015-01-14T13:50:56.293 に答える