0

任意のファイルやクラスから例外をログに記録できるように、シングルトン ロガー クラス用に以下のラッパーを作成しました。私のインスピレーションはここから来ています:複数の Java ファイルから 1 つのファイルにログを記録する

私はJavaが初めてで、例外をファイルに記録しようとするのはこれが初めてです。次のコードは機能しますが、「通常の動作」であるかどうか、または回避策が存在するかどうかを確認したいいくつかの癖に気付きました。

(1) ログ ファイルが作成され、例外を除いて書き込まれると、ログ ファイルを編集すると (たとえば、テキストの一部の行を削除するなど)、ログ ファイルはその時点から二度と書き込まれません。ログ ファイルが再度書き込まれる前に、Web サーバーは Web アプリケーションに関連付けられたドメインを再起動する必要があります。これは正常ですか?理想的には、Web サーバーで Web アプリケーションのドメインを再起動する必要なく、関連するエラーのみをログ ファイルに保持し、無関係なエラーを削除したいと考えています。

(2) ログ ファイルを削除すると、後で Java プログラムで例外が発生し、ログ ファイルが再度作成されず、例外が失われます。ここでも、Web サーバーは、新しいログ ファイルを作成する前に、Web アプリケーションに関連付けられたドメインを再起動する必要があります。これは正常ですか、それとも以下のコードを編集することで何らかの回避策がありますか? 理想的には、いつでもログ ファイルを削除して、アプリケーションで新しいログ ファイルを作成できるようにしたいと考えています。

繰り返しますが、私はここに来たばかりなので、上記の意図が悪いデザインなどであることを指摘してください.

------コードは続きます------

ファイルは次のとおりです: LoggerWrapper.java

import java.io.OutputStream;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.logging.Logger;
import java.util.logging.Level;   
import java.util.logging.FileHandler;  
import java.util.logging.SimpleFormatter;

public class LoggerWrapper {
public static final Logger myLogger = Logger.getLogger("Test");
private static LoggerWrapper instance = null;  

 public static LoggerWrapper getInstance() {  
    if(instance == null) {  
        prepareLogger();  
        instance = new LoggerWrapper ();  
    }  
    return instance;  
 }  

private static void prepareLogger() {
try {
   FileHandler myFileHandler = new FileHandler("/path/to/myLogFile.log", true);  
   myFileHandler.setFormatter(new SimpleFormatter());  
   myLogger.addHandler(myFileHandler);  
   myLogger.setUseParentHandlers(false);  
   myLogger.setLevel(Level.ALL);
} catch (Exception e) {
   ...
}
}    
} 

上記のコードを別のファイルまたはクラスで呼び出すには、次の行を発行します (例):

LoggerWrapper loggerWrapper = LoggerWrapper.getInstance();
...
loggerWrapper.myLogger.log(Level.SEVERE, "some text here"+e.fillInStackTrace());
4

4 に答える 4

3

ロギングに関するこの問題のすべてに取り組む必要はありません。ログハンドラー(およびlogback、log4jなどのすべての代替手段)またはCommons Loggingやslf4jなどのラッパーフレームワークが、この作業のほとんどすべてを実行します。

ロギングを使用する最も広く受け入れられている方法は、ラッパーシステム(slf4jが非常に人気があります)を使用してから、各クラスのプライベート静的属性としてログクラスを含めることです。次に、別のプログラムを使用してすべての構成を実行するか、すべてをセットアップする構成ファイルを作成することができます。

ロギングシステムをコードでセットアップしたい場合(私が行う方法ではありませんが、可能です...)、比較的早くロードされることがわかっている静的初期化子でセットアップします。ロギングシステムに情報が含まれると、再度構成する必要はありません。

于 2012-06-11T21:55:49.860 に答える
2

これはLinuxで実行されていると思いますか?ファイルを開くと、そのファイルへの参照を指しています。ファイルを削除すると参照は失われますが、参照を静的変数に保存したため、コードは何も指さないファイルハンドルを保持しています。代わりに、次のようなことを行う必要があります

cat /dev/null > file

これは、ファイルが指す実際のiノードを変更せずにファイル上に何もコピーしません。

于 2012-06-11T21:56:02.600 に答える
2

これを見たことがありますか?

エディター/OS に関係している可能性があります。リンクされた質問のポスターには、log4j で同様の問題がありました。

他の回答が述べているように、ハンドラーを邪魔することなくログファイルをクリアするには:

cat /dev/null > file.log
于 2012-06-12T14:47:45.647 に答える
-1

ファイルを編集しないことをお勧めします!そして、それらを削除しないでください!

ハハハハ、それはエースの解決策になるでしょうね?

Jonathanによって提案されたオープンソースロギング(私は常にlog4jが好きです-ほとんどのIBはそれを使用します、またはslf4j)を実際に使用する必要があります-これはロギングを行うための標準的な方法です。 。少なくとも、私が知っていることではありません。

わかりました。そうは言っても、Linuxについては、どのような形や形式でもまったくわかりません。Rickが示唆しているように、ファイルを編集/削除すると、ポイントしているものがすべて消えてしまうようです。したがって、擬似コードでは(なぜなら、これについては申し訳ありません-私が示したように、私はウィンドウを使用しているのでテストできません):

public class LoggerWrapper {
    *private* FileHandler myFileHandler;
    *private* static final Logger myLogger = Logger.getLogger("Test");
    private static LoggerWrapper instance = null;  

    /*
      here check if the file you're using has been changed! If so, re-do the file setting
    */
    public void log(Level level, String message){
        //argh you are on your own here. I don't know how to *check* the file being used by the file handler...
        //you know what? you can just do this (but it isn't too clean)
        myLogger.removeFileHandler(myFileHandler);
        myFileHandler = new FileHandler("/path/to/myLogFile.log", true); 
        myLogger.addHandler(myFileHandler);
        myLogger.log(level,message);     
    }  

    private static void prepareLogger() {
        try {
            //don't shadow the myFileHandler by accident!
            myFileHandler = new FileHandler("/path/to/myLogFile.log", true); 

...

もちろん、ログに記録するたびにファイルハンドラーがリセットされるだけです。そして、次のコマンドでログに記録することはありません。

loggerWrapper.myLogger.log(Level.SEVERE, "some text here"+e.fillInStackTrace());

しかし、

loggerWrapper.log(Level.SEVERE, "some text here"+e.fillInStackTrace());

または、オープンソースログ(log4j!)を使用して、満足してください。ファイルが失われたかどうかを確認する方法があるかもしれません-ああ!たぶんisLoggableメソッドをチェックしますか?それが変更されたファイルを拾うかどうかはわかりません...しかし、そうは思わない。

また、fileHandlerにsetErrorManagerを設定する必要がある場合もあります。見た目からすると、ロガーがログに記録できない場合は、errorManagerに何かを送信します。私はこれに慣れていません、そして私はジバリーを話しているかもしれません。

于 2012-06-11T22:49:26.153 に答える