4

これは少し奇妙ですが、私は logging パッケージとそのプロパティの使用に不慣れです。グーグルで見つけることができるすべての質問は、「ログを複数のファイルで開く方法は?」です。しかし、今日の私の質問は、複数のファイルを同時に処理しないようにする方法です。どうぞ...

まず最初に、このプロジェクトは java.util.logging の使用に制限されています。いいえ、log4j やその他のサードパーティ パッケージに切り替えることはできません。はい、それらがより優れているはずであることはわかっています。:-)

したがって、このアプレットが起動すると、次のコードが実行されます。

import java.util.logging.Logger;
import java.util.logging.LogManager;

// in startup routine:
LogManager.getLogManager().readConfiguration(
  this.getClass().getResourceAsStream("/logging.properties"));

プロパティファイルをJARから引き出して適用すると、うまくいきます。はreadConfiguration()、VM の起動からすべての既存の設定をリセットすることになっています。プロジェクトの残りの部分には次のような行があります

private final static Logger LOGGER = Logger.getLogger(NameOfClass.class.getName());

これはかなり標準的だと思います。すべてのクラスは同じパッケージ (たとえば、TheProject と呼びます) にあり、ファンキーなログ名/プロパティ階層は同じ規則に従っています。

logging.properties ファイルは、Java 6 SE JRE に同梱されているもののコピーとして開始され、その後変更されました。次のようになります。

handlers=java.util.logging.FileHandler,java.util.logging.ConsoleHandler

# Default global logging level. 
.level=INFO

# Loggers 
# ------------------------------------------ 
# Loggers are usually attached to packages. 
# Here, the level for each package is specified. 
# The global level is used by default, so levels 
# specified here simply act as an override. 
java.level = INFO
javax.swing.level = INFO
sun.awt.level = INFO
theproject.level = ALL

# Handlers 
# -----------------------------------------
theproject.handlers=java.util.logging.FileHandler

# Override of global logging level 
java.util.logging.FileHandler.level=ALL

# Naming style for the output file: 
java.util.logging.FileHandler.pattern=/path/to/logfiles/TheProject%u.%g.log

ログメッセージがJavaコンソールに表示され、ディスクファイルにも表示されるという点で、すべて「機能」します。ここで奇妙な点があります。アプレットが実行されるとすぐに、 TheProject0.0.log と TheProject1.0.log の両方の2 つのファイルが同時に開かれます。ログ メッセージが発生すると、両方のファイルに同時に表示されます。両方のファイルは、最大サイズに達し、(両方!) ローテーションされる場合を含め、常に互いの正確なコピーです。

一度に 1 つの JRE VM しか実行されていないことを確認しました。

いつでも、両方のファイルが開かれているか、両方が閉じられているかを確認しました。一方が他方よりも長いまたは短い時間開いているわけではありません。

2 つのファイル名の間で異なる %u トークンは、ログファイルが別のプロセスによって既に開かれている場合に備えて、「競合を解決するための一意の番号」として文書化されていますが、両方のログが同一のデータを取得していて何も取得していないため、ここではそうではないと思います。それ以外の場合はファイルを開きます。(証拠: Windows では、VM の実行中はどちらのファイルも削除できませんが、VM が最終的に終了すると削除されます。)

プロパティファイルで何かばかげたことをしているのですか、それともプロパティを正しくロードする方法を誤解していますか...?

4

2 に答える 2

3

あなたが思うように機能するとは思いreadConfiguration()ません。JavaDoc を作成します。

ロギング プロパティを再初期化し、指定されたストリームからロギング構成を再読み取りします。これは java.util.Properties 形式である必要があります。プロパティが読み取られた後、PropertyChangeEvent が発生します。

ターゲット Logger が存在する場合、新しい構成ファイルのログ レベル定義は、Logger.setLevel() を使用して適用されます。

これが実際にロギング構成をリセットするかどうか、または単に現在の構成を追加/更新するかどうかはわかりません。

reset()に電話する前に電話 する必要があると思いますreadConfiguration()

ロギング構成をリセットします。

すべての名前付きロガーについて、リセット操作はすべてのハンドラーを削除して閉じ、(ルート ロガーを除く) レベルを null に設定します。ルート ロガーのレベルは Level.INFO に設定されます。

編集:プロパティファイルに問題がないことを示すために、theproject以下のようにパッケージにtestというクラスを作成して実行できます。実行時に作成されるログ ファイルの数がわかるように、必ず既存のログ ファイルを削除してください。

package theproject;

import java.util.logging.FileHandler;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;
public class Test {

    private final static Logger LOGGER = Logger.getLogger(Test.class.getName());

    public static void main(String[] args) throws Exception {
        LogManager.getLogManager().readConfiguration(
                  Test.class.getResourceAsStream("/logging.properties"));
//      The only way I could get it to create two log files was to uncomment the line below that
//      adds another FileHandler to the root logger.
//      LogManager.getLogManager().getLogger("").addHandler(new FileHandler("/path/to/logfiles/TheProject%u.%g.log"));
        Test test = new Test();
    }   

    public Test(){
        LOGGER.log(Level.INFO, "Info");
    }

}
于 2012-11-14T17:16:47.447 に答える
1

@Joopはそれを釘付けにしました(コメントで、回答としてマークすることはできません)。ハンドラーの設定は付加的なプロセスであり、以前の設定を単に上書きするだけではないことがわかりました。それは私には本当に直感的ではないように思えますが、それはあなたにとって java.util.logging です...他のすべてのプロパティをそのままにして、ハンドラーの割り当てを削除するのが道でした。

@jschoen によって提案された reset() 呼び出しも使用しています。

皆様、本当にありがとうございました。これをすべて「閉鎖」とマークする方法がわかりません...サイトをいじる時間です。

于 2012-11-14T19:09:00.713 に答える