実行時にMDCを使用してログファイルに名前を付ける方法はありますか?
tomcatdocbaseを使用して同時に異なる名前で呼び出されている単一のWebアプリケーションがあります。したがって、それぞれに個別のログファイルを用意する必要があります。
これは、Log4J の後継であるLogbackで実現できます。
Logback は、人気のある log4j プロジェクトの後継として意図されており、log4j が離れたところを取り上げます。
Sifting Appenderのドキュメントを参照してください
SiftingAppender は、ネストされたアペンダーを参照および構成できるという点で独特です。上記の例では、SiftingAppender 内にネストされた FileAppender インスタンスがあり、各インスタンスは「userid」MDC キーに関連付けられた値によって識別されます。「userid」MDC キーに新しい値が割り当てられるたびに、新しい FileAppender インスタンスがゼロから構築されます。SiftingAppender は、作成したアペンダーを追跡します。30 分間使用されなかったアペンダは、自動的に閉じられ、破棄されます。
この例では、MDC 値に基づいてユーザーごとに個別のログ ファイルを生成します。必要に応じて、他の MDC 値を使用できます。
これはlog4jでも可能です。これを行うには、独自のアペンダーを実装します。最も簡単な方法は、 AppenderSkeletonをサブクラス化することだと思います。
すべてのロギングイベントappend(LoggingEvent event)
は、実装する必要のあるメソッドで終了します。
その方法では、次の方法でMDCにアクセスできます。event.getMDC("nameOfTheKeyToLookFor");
次に、この情報を使用して、書き込み先のファイルを開くことができます。RollingFileAppenderのような標準のアペンダーの実装を見て、残りを理解することが役立つ場合があります。
私はこのアプローチをアプリケーションで自分で使用して、さまざまなスレッドのログをさまざまなログファイルに分割しましたが、非常にうまく機能しました。
私はしばらくの間、log4j で SiftingAppender のような機能を見つけるのに苦労しました (いくつかの依存関係のために logback に切り替えることができませんでした)。
// this can be any thread-specific string
String processID = request.getProcessID();
Logger logger = Logger.getRootLogger();
// append a new file logger if no logger exists for this tag
if(logger.getAppender(processID) == null){
try{
String pattern = "%d{yy/MM/dd HH:mm:ss} %p %c{2}: %m%n";
String logfile = "log/"+processID+".log";
FileAppender fileAppender = new FileAppender(
new PatternLayout(pattern), logfile, true);
fileAppender.setName(processID);
// add a filter so we can ignore any logs from other threads
fileAppender.addFilter(new ProcessIDFilter(processID));
logger.addAppender(fileAppender);
}catch(Exception e){
throw new RuntimeException(e);
}
}
// tag all child threads with this process-id so we can separate out log output
MDC.put("process-id", processID);
//whatever you want to do in the thread
LOG.info("This message will only end up in "+processID+".log!");
MDC.remove("process-id");
上に追加されたフィルターは、特定のプロセス ID をチェックするだけです。
public class RunIdFilter extends Filter {
private final String runId;
public RunIdFilter(String runId) {
this.runId = runId;
}
@Override
public int decide(LoggingEvent event) {
Object mdc = event.getMDC("run-id");
if (runId.equals(mdc)) {
return Filter.ACCEPT;
}
return Filter.DENY;
}
}
これが少し役立つことを願っています。