私は現在、サード パーティのライブラリ (つまり、restfb) が java.util.logging を使用していることを確認しています。また、logback.xml で SLF4J コンソール アペンダーを構成していなくても、これらのログが STDOUT で終了することを確認しています。また、クラスパスに jul-to-slf4jブリッジがあります。jul-to-slf4j ブリッジは、ブリッジのインストール時に logback によって構成されたアペンダにのみログを記録しますか、それとも stdout にもログを記録しますか?
5 に答える
に電話する必要があります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
最初にログを有効にしないとログをオンにすることはできません (上記の抜粋で述べた理由により)。
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 を有効にすると、負荷に関係なく良好なパフォーマンスが得られるはずです。
私の解決策:
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>
最後の設定は、他のロガーによって汚染されないようにすることです
logback.groovyファイルにすべてを書き込むだけでよいので、(JUL ブリッジの状況を考慮して)適切に機能するソリューションです。
( logback.groovy構成またはlogbackをまったく使用していない場合は、もちろん、ロジック部分を何らかのクラス (たとえば
class MyApp { static { /* log init code here */ } ... }
)に配置する必要があります。)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 )