如何将log4j输出重定向到HttpServletResponse输出流? [英] How do I redirect log4j output to my HttpServletResponse output stream?

查看:99
本文介绍了如何将log4j输出重定向到HttpServletResponse输出流?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在部署在JBoss AS 7.1.1.Final上的Spring 3.1.1.RELEASE应用程序中使用log4j 1.2.15.我正在尝试将用log4j编写的输出路由到我的响应输出流.我的输出是这样写的

I'm using log4j 1.2.15 in a Spring 3.1.1.RELEASE application deployed on JBoss AS 7.1.1.Final. I'm trying to route output written in log4j to my response output stream. I have output written like this

private static final Logger LOG = Logger.getLogger(TrainingSessionServiceImpl.class);
…
LOG.info("Creating/updating training session associated with order #:" + order.getId());

而我正试图将其路由到我的输出流中……

and I'm trying to route it to my output stream like so …

@RequestMapping(value = "/refreshPd", method = RequestMethod.GET)
public void refreshPD(final HttpServletResponse response) throws IOException
{
    ...        
    final WriterAppender appender = new WriterAppender(new PatternLayout("%d{ISO8601} %p - %m%n"),response.getWriter());
    appender.setName("CONSOLE_APPENDER");
    appender.setThreshold(org.apache.log4j.Level.DEBUG);
    Logger.getRootLogger().addAppender(appender);

    worker.work();

    Logger.getRootLogger().removeAppender("CONSOLE_APPENDER");

但是可悲的是,即使我(通过调试)知道正在调用日志记录语句,也没有任何输出到我的浏览器.有谁知道我如何调整我的设置以使其正常工作?下面是我的log4j.properties文件,该文件已部署到我的wAR的WEB-INF/classes目录中.

but sadly, nothing is getting output to my browser, even though I know (through debugging) that logging statements are getting called. Does anyone know how I can adjust my setup to make it work? Below is my log4j.properties file, deployed to my wAR's WEB-INF/classes directory.

log4j.rootLogger=DEBUG, CA, FA

#Console Appender
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

#File Appender
log4j.appender.FA=org.apache.log4j.FileAppender
log4j.appender.FA.File=/usr/java/jboss/server/default/log/log4j.log
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
log4j.appender.FA.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n

# Set the logger level of File Appender to WARN
log4j.appender.FA.Threshold = DEBUG

谢谢-戴夫

推荐答案

这是一个有趣的问题. 关键是编写自己的附加程序.我查找了内置的org.apache.log4j.ConsoleAppender代码以获取灵感.我已经在雄猫中对此进行了测试,并验证了它的有效性.我使用了log4j-1.2.17(希望没关系)

This was an interesting problem. The key thing is to write your own appender. I looked up the in built org.apache.log4j.ConsoleAppender code for inspiration. I have tested this in my tomcat and verified that it works. I used log4j-1.2.17 (hopefully shouldn't matter)

1)首先实现自己的附加程序.该追加器会将所有日志事件写入当前线程的输出流中

1) First implement your own appender. This appender will write all log events to current thread's outputstream

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配置文件中

2) Add this appender in your log4j configuration file just like the other settings

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

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)在您的servlet中添加一小段代码,以便此附加程序正常工作.这是我的servlet.

3) Add a small piece of code in your servlet so that this appender works correctly . Here's my servlet.

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);
    }
}

警告:尚未对它进行彻底的测试,尤其是对于多个servlet请求等.也不确定为什么要这样做.将日志消息通过管道传输到浏览器并不常见.谨慎操作..:)-

Caution : This is not thoroughly tested especially with multiple servlet requests etc. Also not sure why you want to do this. Its not typical to pipe log messages to browser. Proceed with caution..:)-

这篇关于如何将log4j输出重定向到HttpServletResponse输出流?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆