2009-07-12 12 views
5

ファイルを循環させることができるjava.util.logging.FileHandlerを作成しています。アプリケーションのインスタンスが複数実行されると、アプリケーションのインスタンスごとに新しいログファイルが作成されます。ログファイルをサーバーにアップロードしてさらに確認する必要があるため、アプリケーションでどのファイルが使用されているかを知る必要があります。特定のFileHandlerがどのファイルを使用しているかをどのようにして知ることができますか?FileHandlerで使用されているファイルを確認する

答えて

2

最も簡単な方法は、FileHandlerを作成するときに、ファイル名自体にある種の識別子、つまりpattern引数を入れることです。これらは同じアプリケーションのインスタンスなので、それらを区別する方法の1つはプロセスIDであるため、その部分をパターンの一部にすることができます。より良い方法は、コマンドラインで識別子を渡し、それを使ってファイル名を作ることです。そのようにして、ある意味で作成されるファイルを制御します。最後に、アプリケーションが特定のデータベースサーバーに接続するなど、他のすべてのアプリケーションと異なる理由についてアプリケーションが知っている場合は、そのデータベースサーバー名をファイル名の一部として使用できます。

EDIT:FileHandlerで使用されているファイルの名前を取得するAPIはありません。あなたは、インスタンスを代用することができるはず

:私は(どのポートのjava.util.loggingスペックにlog4jの機能の多くを)x4juliにおけるログの拡張を検討してお勧めします

+0

まあ、新しいインスタンスが実行されるたびに、ログファイルがなるようにインクリメントされます。 第一インスタンス - log.0 2番目のインスタンス - log.1 第三インスタンス - log.2 –

+0

たぶん私はしましたあなたの質問を誤解しました。既にインスタンスをファイルに関連付けることができるようです - 他に何が必要ですか?インスタンス1,2,3のような識別情報が必要な場合は、上で指定した方法でインスタンスを拡張する必要があります。そうでない場合は、明確にしてください。 – ars

+0

最後のコメントで述べたように、3つのインスタンスが稼動しており、それぞれに独自のログファイルがあるとします。インスタンス2はエラーを検出し、そのログファイル(log.1)にエラーを記録すると、ログファイルをサーバーにアップロードする必要がありますが、アップロードするには、書き込んだログファイルを知る必要があります。同じものをアップロードしてください。 –

0
:はgetFile()メソッドを提供し、それらのFileHandlerの

OK、私は、FileHandlerは、ログファイルを決定する方法を提供していないと真剣にばかだと言う必要があります。

次の使用可能なログファイル名を/ tmpで検索し、そのファイルを返す "chooseFile()"という関数を書きました。そのファイルの名前を新しいFileHandler()に渡すことができます。

/** 
* Utility: select a log file. File is created immediately to reserve 
* its name. 
*/ 
static public File chooseFile(final String basename) throws IOException { 
    final int nameLen = basename.length(); 
    File tmpDir = new File(System.getProperty("java.io.tmpdir")); 
    String[] logs = tmpDir.list(new FilenameFilter() { 
     public boolean accept(File d, String f) { 
      return f.startsWith(basename); 
     } 
    }); 
    int count = 0; 
    if (logs.length > 0) { 
     for (String name : logs) { 
      int n = atoi(name.substring(nameLen)); 
      if (n >= count) count = n + 1; 
     } 
    } 
    String filename = String.format("%s%d.log", basename, count); 
    File logFile = new File(tmpDir, filename); 
    logFile.createNewFile(); 
    return logFile; 
} 
1

実際、FileHandlerを自分で拡張するだけで、もっと簡単に行うことができます。たとえば...

MyFileHandler.java:

import java.io.IOException; 
import java.util.logging.FileHandler; 
public class MyFileHandler extends FileHandler { 
    protected String _MyFileHandler_Patern; 
    public MyFileHandler(String pattern) throws IOException { 
     _MyFileHandler_Patern = pattern; 
    } 
    public String getMyFileHandlerPattern() { 
     return _MyFileHandler_Patern; 
    } 
} 

DeleteMe.java:

import java.io.IOException; 
import java.util.logging.Handler; 
import java.util.logging.Logger; 
public class DeleteMe { 
    public static void main(String[] args) throws IOException { 
     Logger log = Logger.getLogger(DeleteMe.class.getName()); 
     MyFileHandler output = new MyFileHandler("output.log"); 
     log.addHandler(output); 
     for (Handler handler : log.getHandlers()) { 
      if (handler instanceof MyFileHandler) { 
       MyFileHandler x = (MyFileHandler) handler; 
       if ("output.log".equals(x.getMyFileHandlerPattern())) { 
        System.out.println("found hanlder writing to output.log"); 
       } 
      } 
     } 
    } 
} 
+0

この問題は、パターンを使用した場合に発生します。使用される実際のファイルがどのように分かっていますか? – PhoneixS

+0

また、コントローラMyFileHandlerでsuper(パターン)の呼び出しを追加する必要があります。そうでない場合は、ファイルがログの書き込みに使用されていません。 優れたアプローチは、魅力のように動作します。 –

0

は、ここにその周りに私はむしろハック方法です。書式文字列を使用しない場合はデフォルトで動作し、ファイル名にgとuの書式文字列を使用し、他の文字列は使用しない場合は機能するはずです。

public class FriendlyFileHandler extends FileHandler { 

    /*** 
    * In order to ensure the most recent log file is the file this one owns, 
    * we flush before checking the directory for most recent file. 
    * 
    * But we must keep other log handlers from flushing in between and making 
    * a NEW recent file. 
    */ 
    private static Object[] flushLock = new Object[0]; 

    private String pattern; 

    public FriendlyFileHandler(String pattern, int maxLogLengthInBytes, int count) throws IOException, 
      SecurityException { 
     super(pattern, maxLogLengthInBytes, count); 

     this.pattern = pattern; 
    } 

    /*** 
    * Finds the most recent log file matching the pattern. 
    * This is just a guess - if you have a complicated pattern 
    * format it may not work. 
    * 
    * IMPORTANT: This log file is still in use. You must 
    * removeHandler() on the logger first, .close() this handler, 
    * then add a NEW handler to your logger. THEN, you can read 
    * the file. 
    * 
    * Currently supported format strings: g, u 
    * 
    * @return A File of the current log file, or null on error. 
    */ 
    public synchronized File getCurrentLogFile() { 

     synchronized(flushLock) { 

      // so the file has the most recent date on it. 
      flush(); 


      final String patternRegex = 
        // handle incremental number formats 
        pattern.replaceAll("%[gu]", "\\d*") + 
        // handle default case where %g is appended to end 
        "(\\.\\d*)?$"; 

      final Pattern re = Pattern.compile(patternRegex); 
      final Matcher matcher = re.matcher(""); 

      // check all files in the directory where this log would be 
      final File basedir = new File(pattern).getParentFile(); 
      final File[] logs = basedir.listFiles(new FileFilter() { 

       @Override 
       public boolean accept(final File pathname) { 
        // only get files that are part of the pattern 
        matcher.reset(pathname.getAbsolutePath()); 

        return matcher.find(); 
       } 

      }); 

      return findMostRecentLog(logs); 
     } 
    } 

    private File findMostRecentLog(File[] logs) { 

     if (logs.length > 0) { 
      long mostRecentDate = 0; 
      int mostRecentIdx = 0; 

      for (int i = 0; i < logs.length; i++) { 
       final long d = logs[i].lastModified(); 

       if (d >= mostRecentDate) { 
        mostRecentDate = d; 
        mostRecentIdx = i; 
       } 

      } 

      return logs[mostRecentIdx]; 
     } 
     else { 
      return null; 
     } 

    } 


    @Override 
    public synchronized void flush() { 

     // only let one Handler flush at a time. 
     synchronized(flushLock) { 
      super.flush(); 
     } 
    } 

} 
関連する問題