Java.util.logging.Level
のJavaDocs 状態:
降順のレベルは次のとおりです。
SEVERE
(最大値)WARNING
INFO
CONFIG
FINE
FINER
FINEST
(最小値)import Java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
logger.setLevel(Level.FINER);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
Logging level is: FINER
Jun 11, 2011 9:39:23 PM LoggingLevelsBlunder main
INFO: 0 0
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 1 1
Jun 11, 2011 9:39:24 PM LoggingLevelsBlunder main
INFO: 2 4
Press any key to continue . . .
私の例ではLevel
をFINER
に設定しているため、ループごとに2つのメッセージが表示されることを期待していました。代わりに、ループごとに1つのメッセージが表示されます(Level.FINE
メッセージがありません)。
FINE
(、FINER
またはFINEST
)の出力を表示するには、何を変更する必要がありますか?
Vineet Reynolds 'answer のおかげで、このバージョンは私の期待どおりに機能します。 3xINFO
メッセージと3xFINE
メッセージが表示されます。
import Java.util.logging.*;
class LoggingLevelsBlunder {
public static void main(String[] args) {
Logger logger = Logger.getAnonymousLogger();
// LOG this level to the log
logger.setLevel(Level.FINER);
ConsoleHandler handler = new ConsoleHandler();
// PUBLISH this level
handler.setLevel(Level.FINER);
logger.addHandler(handler);
System.out.println("Logging level is: " + logger.getLevel());
for (int ii=0; ii<3; ii++) {
logger.log(Level.FINE, ii + " " + (ii*ii));
logger.log(Level.INFO, ii + " " + (ii*ii));
}
}
}
ロガーはメッセージのみを記録します。つまり、ログレコード(またはログリクエスト)を作成します。メッセージを宛先にパブリッシュすることはありません。これは、ハンドラーによって処理されます。ロガーのレベルを設定すると、そのレベル以上のレコードをcreateログに記録するだけです。
ConsoleHandler
(出力がSystem.errまたはファイルの場所を推測することはできませんでしたが、前者であると仮定します)を使用している可能性があります。 Level.INFO
。望ましい結果を得るには、レベルLevel.FINER
以上のログレコードを公開するために、このハンドラーを構成する必要があります。
基礎となる設計を理解するために、 Java Logging Overview ガイドを読むことをお勧めします。このガイドでは、ロガーとハンドラーの概念の違いについて説明しています。
ハンドラーレベルの編集
1。構成ファイルの使用
Java.util.loggingプロパティファイル(デフォルトでは、これはlogging.properties
のJRE_HOME/lib
ファイルです)を変更して、ConsoleHandlerのデフォルトレベルを変更できます。
Java.util.logging.ConsoleHandler.level = FINER
2。実行時にハンドラーを作成する
これは、グローバル構成を上書きするため、推奨されません。コードベース全体でこれを使用すると、管理不能なロガー設定が発生する可能性があります。
Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
Logger.getAnonymousLogger().addHandler(consoleHandler);
理由
Java.util.loggingには、デフォルトでLevel.INFO
に設定されたルートロガーと、デフォルトでLevel.INFO
に設定されたConsoleHandlerが添付されています。 FINE
はINFO
よりも低いため、デフォルトでは細かいメッセージは表示されません。
ソリューション1
アプリケーション全体のロガーを作成します。パッケージ名から、または Logger.getGlobal()
を使用して、独自のConsoleLoggerをフックします。次に、ルートロガーにシャットダウンするように依頼するか(高レベルのメッセージの重複出力を回避するため)、またはロガーに ログを転送しない にルートに依頼します。
public static final Logger applog = Logger.getGlobal();
...
// Create and set handler
Handler systemOut = new ConsoleHandler();
systemOut.setLevel( Level.ALL );
applog.addHandler( systemOut );
applog.setLevel( Level.ALL );
// Prevent logs from processed by default Console handler.
applog.setUseParentHandlers( false ); // Solution 1
Logger.getLogger("").setLevel( Level.OFF ); // Solution 2
ソリューション2
または、ルートロガーのバーを下げることもできます。
コードで設定できます:
Logger rootLog = Logger.getLogger("");
rootLog.setLevel( Level.FINE );
rootLog.getHandlers()[0].setLevel( Level.FINE ); // Default console handler
または、ロギング設定ファイルを使用している場合は、 使用中 :
.level = FINE
Java.util.logging.ConsoleHandler.level = FINE
グローバルレベルを下げると、SwingまたはJavaFXコンポーネントなどのコアライブラリからのメッセージが表示される場合があります。この場合、ルートロガーに Filter を設定して、プログラムからではないメッセージを除外できます。
ログインが期待どおりに機能しない理由を解明するのに役立つjarファイルを提供します。これにより、インストールされているロガーとハンドラー、設定されているレベル、およびロギング階層のどのレベルの完全なダンプが得られます。
なぜ
@Sheepyで述べたように、機能しない理由は、Java.util.logging.Logger
にはデフォルトでLevel.INFO
のルートロガーがあり、そのルートロガーに接続されたConsoleHandler
もデフォルトでLevel.INFO
になっているためです。したがって、FINE
(、FINER
またはFINEST
)の出力を表示するには、次のようにルートロガーとそのConsoleHandler
のデフォルト値をLevel.FINE
に設定する必要があります。 :
Logger.getLogger("").setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);
アップデートの問題(解決策)
@minsで述べたように、INFO
以上のコンソールでメッセージを2回出力します。最初は匿名ロガー、次にその親、ConsoleHandler
も設定されたルートロガーINFO
デフォルトでは。ルートロガーを無効にするには、次のコード行を追加する必要があります:logger.setUseParentHandlers(false);
ログがデフォルトで@Sheepyが言及したルートロガーのコンソールハンドラーによって処理されるのを防ぐ方法は他にもあります。
Logger.getLogger("").getHandlers()[0].setLevel( Level.OFF );
ただし、Logger.getLogger("").setLevel( Level.OFF );
は、ルートロガーに直接渡されるメッセージをブロックするだけで、子ロガーからのメッセージではないため、機能しません。 Logger Hierarchy
の動作を説明するために、次の図を描画します。
public void setLevel(Level newLevel)
このロガーによって記録されるメッセージレベルを指定するログレベルを設定します。この値よりも低いメッセージレベルは破棄されます。レベル値Level.OFFは、ロギングをオフにするために使用できます。新しいレベルがnullの場合、このノードは、特定の(null以外の)レベル値を持つ最も近い祖先からレベルを継承する必要があることを意味します。
保守性と変更のための設計に関して、このソリューションは私にとってより良いように見えます:
リソースプロジェクトフォルダに埋め込むロギングプロパティファイルを作成し、jarファイルに含めます。
# Logging
handlers = Java.util.logging.ConsoleHandler
.level = ALL
# Console Logging
Java.util.logging.ConsoleHandler.level = ALL
コードからプロパティファイルを読み込みます。
public static Java.net.URL retrieveURLOfJarResource(String resourceName) {
return Thread.currentThread().getContextClassLoader().getResource(resourceName);
}
public synchronized void initializeLogger() {
try (InputStream is = retrieveURLOfJarResource("logging.properties").openStream()) {
LogManager.getLogManager().readConfiguration(is);
} catch (IOException e) {
// ...
}
}
他の亜種を試したが、これは適切な場合がある
Logger logger = Logger.getLogger(MyClass.class.getName());
Level level = Level.ALL;
for(Handler h : Java.util.logging.Logger.getLogger("").getHandlers())
h.setLevel(level);
logger.setLevel(level);
// this must be shown
logger.fine("fine");
logger.info("info");
私の実際の問題を見つけましたが、回答には記載されていませんでした:私のユニットテストのいくつかは、同じテストスイート内でロギング初期化コードを複数回実行させ、後のテストのロギングを台無しにしました。