web-dev-qa-db-ja.com

Level.FINEロギングメッセージが表示されないのはなぜですか?

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 . . .

問題文

私の例ではLevelFINERに設定しているため、ループごとに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));
        }
    }
}
106
Andrew Thompson

ロガーはメッセージのみを記録します。つまり、ログレコード(またはログリクエスト)を作成します。メッセージを宛先にパブリッシュすることはありません。これは、ハンドラーによって処理されます。ロガーのレベルを設定すると、そのレベル以上のレコードをcreateログに記録するだけです。

ConsoleHandler (出力がSystem.errまたはファイルの場所を推測することはできませんでしたが、前者であると仮定します)を使用している可能性があります。 Level.INFO。望ましい結果を得るには、レベルLevel.FINER以上のログレコードを公開するために、このハンドラーを構成する必要があります。

基礎となる設計を理解するために、 Java Logging Overview ガイドを読むことをお勧めします。このガイドでは、ロガーとハンドラーの概念の違いについて説明しています。

ハンドラーレベルの編集

1。構成ファイルの使用

Java.util.loggingプロパティファイル(デフォルトでは、これはlogging.propertiesJRE_HOME/libファイルです)を変更して、ConsoleHandlerのデフォルトレベルを変更できます。

Java.util.logging.ConsoleHandler.level = FINER

2。実行時にハンドラーを作成する

これは、グローバル構成を上書きするため、推奨されません。コードベース全体でこれを使用すると、管理不能なロガー設定が発生する可能性があります。

Handler consoleHandler = new ConsoleHandler();
consoleHandler.setLevel(Level.FINER);
Logger.getAnonymousLogger().addHandler(consoleHandler);
119
Vineet Reynolds

理由

Java.util.loggingには、デフォルトでLevel.INFOに設定されたルートロガーと、デフォルトでLevel.INFOに設定されたConsoleHandlerが添付されています。 FINEINFOよりも低いため、デフォルトでは細かいメッセージは表示されません。


ソリューション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 を設定して、プログラムからではないメッセージを除外できます。

24
Sheepy

なぜJavaロギングが機能しないのか

ログインが期待どおりに機能しない理由を解明するのに役立つjarファイルを提供します。これにより、インストールされているロガーとハンドラー、設定されているレベル、およびロギング階層のどのレベルの完全なダンプが得られます。

4
matthew

なぜ

@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の動作を説明するために、次の図を描画します。

enter image description here

public void setLevel(Level newLevel) このロガーによって記録されるメッセージレベルを指定するログレベルを設定します。この値よりも低いメッセージレベルは破棄されます。レベル値Level.OFFは、ロギングをオフにするために使用できます。新しいレベルがnullの場合、このノードは、特定の(null以外の)レベル値を持つ最も近い祖先からレベルを継承する必要があることを意味します。

3
Joe Yichong

保守性と変更のための設計に関して、このソリューションは私にとってより良いように見えます:

  1. リソースプロジェクトフォルダに埋め込むロギングプロパティファイルを作成し、jarファイルに含めます。

    # Logging
    handlers = Java.util.logging.ConsoleHandler
    .level = ALL
    
    # Console Logging
    Java.util.logging.ConsoleHandler.level = ALL
    
  2. コードからプロパティファイルを読み込みます。

    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) {
          // ...
       }
    }
    
0
user2627331

他の亜種を試したが、これは適切な場合がある

    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");
0
zhen_khokh

私の実際の問題を見つけましたが、回答には記載されていませんでした:私のユニットテストのいくつかは、同じテストスイート内でロギング初期化コードを複数回実行させ、後のテストのロギングを台無しにしました。

0
Alex R