122

状態のJavaDocsjava.util.logging.Level


降順のレベルは次のとおりです。

  • 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の回答のおかげで、このバージョンは私の期待どおりに機能します。3xINFOメッセージと3xメッセージが表示されFINEます。

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));
        }
    }
}
4

7 に答える 7

132

ロガーはメッセージのみをログに記録します。つまり、ログレコード(またはログ要求)を作成します。ハンドラーによって処理される宛先にメッセージを公開しません。ロガーのレベルを設定すると、そのレベル以上に一致するログレコードのみが作成されます。

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

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

ハンドラーレベルの編集

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);
于 2011-06-11T11:53:21.120 に答える
31

なぜ

java.util.loggingには、デフォルトで。に設定されたルートロガーがLevel.INFOあり、それに接続されたConsoleHandlerもデフォルトで。に設定されていLevel.INFOます。 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コンポーネントなどのコアライブラリからのメッセージが表示されるようになる場合があります。この場合、ルートロガーにフィルターを設定し、プログラムからではないメッセージをフィルターで除外することができます。

于 2015-08-06T10:10:09.470 に答える
10

どうして

@Sheepyが述べたように、それが機能しない理由は、java.util.logging.Loggerデフォルトで。にデフォルト設定されているルートロガーがあり、そのルートロガーLevel.INFOConsoleHandler接続されているものもデフォルトでに設定されているためLevel.INFOです。したがって、FINE(、FINERまたはFINEST)の出力を表示するには、ルートロガーとそのデフォルト値を次のように設定する必要がありConsoleHandlerますLevel.FINE

Logger.getLogger("").setLevel(Level.FINE);
Logger.getLogger("").getHandlers()[0].setLevel(Level.FINE);


アップデートの問題(解決策)

@minsで述べたように、メッセージはコンソールに2回INFO以上印刷されます。最初は匿名のロガー、次にその親であるルートロガーがデフォルトで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以外の)レベル値を持つ最も近い祖先からそのレベルを継承する必要があることを意味します。

于 2018-01-26T03:29:24.860 に答える
4

Javaログが機能しないのはなぜですか

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

于 2013-05-02T23:17:56.453 に答える
1

他のバリアントを試しましたが、これは適切な場合があります

    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");
于 2017-08-15T07:05:13.783 に答える
0

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

于 2017-06-11T17:18:51.127 に答える
0

このソリューションは、保守性と変更のための設計に関して、私にはよく見えます。

  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) {
          // ...
       }
    }
    
于 2018-03-10T17:05:39.263 に答える