これは興味深い問題でした。 重要なことは、独自の appender を作成することです。インスピレーションを得るために、組み込みの org.apache.log4j.ConsoleAppender コードを調べました。Tomcat でこれをテストし、動作することを確認しました。私は log4j-1.2.17 を使用しました(問題にならないことを願っています)
1) 最初に独自のアペンダーを実装します。このアペンダーは、すべてのログ イベントを現在のスレッドの出力ストリームに書き込みます。
package com.tstwbprj.log;
import org.apache.log4j.Layout;
import org.apache.log4j.WriterAppender;
import java.io.IOException;
import java.io.OutputStream;
public class HttpLogAppender extends WriterAppender {
static ThreadLocal<OutputStream> streamPerHttpThread = new ThreadLocal<OutputStream>();
public HttpLogAppender() {
}
public HttpLogAppender(Layout layout) {
setLayout(layout); //super-class method
activateOptions();
}
public void setCurrentHttpStream(OutputStream stream) {
streamPerHttpThread.set(stream);
}
public void activateOptions() {
setWriter(createWriter(new CurrentHttpThreadOutStream()));
}
/**
* An implementation of OutputStream that redirects to the
* current http threads servlet output stream
*/
private static class CurrentHttpThreadOutStream extends OutputStream {
public CurrentHttpThreadOutStream() {
}
public void close() {
}
public void flush() throws IOException {
OutputStream stream = streamPerHttpThread.get();
if (stream != null) {
stream.flush();
}
}
public void write(final byte[] b) throws IOException {
OutputStream stream = streamPerHttpThread.get();
if (stream != null) {
stream.write(b);
}
}
public void write(final byte[] b, final int off, final int len)
throws IOException {
OutputStream stream = streamPerHttpThread.get();
if (stream != null) {
stream.write(b, off, len);
}
}
public void write(final int b) throws IOException {
OutputStream stream = streamPerHttpThread.get();
if (stream != null) {
stream.write(b);
}
}
}
}
2) 他の設定と同様に、このアペンダーを log4j 構成ファイルに追加します。
log4j.rootLogger=DEBUG、CA、FA、HA
..
log4j.appender.HA= com.tstwbprj.log.HttpLogAppender
log4j.appender.HA.layout=org.apache.log4j.PatternLayout log4j.appender.HA.layout.ConversionPattern =%-4r [%t] %-5p %c %x - %m%n
3) このアペンダーが正しく動作するように、サーブレットに小さなコードを追加します。これが私のサーブレットです。
import org.apache.log4j.Category;
import org.apache.log4j.Logger;
import javax.servlet.ServletOutputStream;
import java.io.IOException;
public class LogServlet extends javax.servlet.http.HttpServlet {
private static final Logger LOG = Logger.getLogger(LogServlet.class);
protected void doPost(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
}
protected void doGet(javax.servlet.http.HttpServletRequest request, javax.servlet.http.HttpServletResponse response) throws javax.servlet.ServletException, IOException {
ServletOutputStream outstream = response.getOutputStream();
configureLogForCurrentRequest(outstream);
LOG.info("Got request");//this is now send to the servlet output stream !!
LOG.info("Hello!!");
LOG.info("Done!!");
}
private void configureLogForCurrentRequest(ServletOutputStream outstream) {
HttpLogAppender appender = (HttpLogAppender) LOG.getAppender("HA");
while (appender == null) {
Category parent = LOG.getParent();
if (parent == null) {
break; //This ideally shouldn't happen. Navigated all the way to root logger and still did not find appender !!..something wrong with log4j configuration setup
}
appender = (HttpLogAppender) parent.getAppender("HA");
}
appender.setCurrentHttpStream(outstream);
}
}
注意: これは、特に複数のサーブレット リクエストなどで十分にテストされていません。また、なぜこれを行う必要があるのかもわかりません。ログメッセージをブラウザーにパイプするのは一般的ではありません。注意して進んでください..:)-