如何读取log4j输出到网页?

Ran*_*Ran 5 java logging tomcat log4j slf4j

我有一个用于管理目的的网页,它运行一项任务(从远程站点获取图像).
为了能够仅使用浏览器调试任务,没有ssh等,我希望能够从执行线程读取所有日志输出并将其吐出到网页.
任务归结为:

  1. 在呼叫开始时更改当前线程的日志级别,并在完成呼叫时恢复.
  2. 读取当前线程的所有日志输出并将其存储在字符串中.

所以在伪代码中,我的execute()方法看起来像这样:(我正在使用struts2)

public String execute() throws Exception {
  turnLoggingLevelToDebugOnlyForThisThread()
  ... do stuff...
  restoreLoggingLevelForThisThread()
  String logs = readAllLogsByThisThread();
}
Run Code Online (Sandbox Code Playgroud)

这可以用log4j完成吗?

我正在使用tomcat,struts2,log4j和slf4j.

编辑1:我应该注意,动机是能够在网页上查看现有日志,而无需在代码中添加新的日志行.想象一个漂亮的Web调试界面,它允许您运行操作,结果会吐出操作的日志.
编辑2:我还应该注意到我已经在使用log4j(通过slf4j)和一个log4j.xml,所以我正在寻找的解决方案需要将当前的日志记录系统放在一边,而不是破坏它.

Mik*_*uka 14

您可以创建一个log4j appender来写入StringWriter.这是我前段时间做的一个例子:

consoleWriter = new StringWriter();
WriterAppender appender = new WriterAppender(new PatternLayout("%d{ISO8601} %p - %m%n"),consoleWriter);
appender.setName("CONSOLE_APPENDER");
appender.setThreshold(org.apache.log4j.Level.ERROR);
Logger.getRootLogger().addAppender(appender);
Run Code Online (Sandbox Code Playgroud)

它将所有ERROR日志写入consoleWriter,但您可以根据需要设置日志的范围或级别.范围(记录器名称)应该是线程的唯一标识符.这样的事情:

Logger.getLogger("Thread-00001").addAppender(appender);
Run Code Online (Sandbox Code Playgroud)

您的线程应该写入此记录器.

Logger.getLogger("Thread-00001").info("blah blah blah");
Run Code Online (Sandbox Code Playgroud)

当你想完成日志记录时:

Logger.getLogger("Thread-00001").removeAppender("CONSOLE_APPENDER");
Run Code Online (Sandbox Code Playgroud)

更新:这是一个工作示例.将错误日志写入文件(在log4j.xml中设置)+将所有线程日志写入StringWriter,启用时:

import java.io.StringWriter;
import org.apache.log4j.Logger;
import org.apache.log4j.Level;
import org.apache.log4j.WriterAppender;
import org.apache.log4j.PatternLayout;

public class Log4jTest implements Runnable {

    public static final String CONSOLE_APPENDER = "CONSOLE_APPENDER";
    private static WriterAppender appender = null;
    private static int counter = 1;

    public static synchronized String getNextId() {
        return "Thread_00"+(counter++);
    }

    public void run() {
        String id="UNKNOWN";
        try {
            id = getNextId();
            Logger log = Logger.getLogger(id);
            log.addAppender(appender);
            log.setLevel(Level.DEBUG);
            log.info(id+" log message 1");
            log.removeAppender(CONSOLE_APPENDER);
            log.info(id+" log message 2");
            log.error(id+" log message 3");
        } catch (Exception e) {
            System.out.println("Error in "+id);
            e.printStackTrace();
        }
    }

    public static void main(String [] args) {
        try {
            StringWriter consoleWriter = new StringWriter();
            appender = new WriterAppender(new PatternLayout("%d{ISO8601} %p - %m%n"),consoleWriter);
            appender.setName(CONSOLE_APPENDER);
            appender.setThreshold(org.apache.log4j.Level.DEBUG);

            for (int i=0; i<5; i++) {
                Thread t = new Thread(new Log4jTest());
                t.start();
            }

            Thread.sleep(200);
            System.out.println(consoleWriter.getBuffer().toString());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是我的log4j.xml:

<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration>
  <appender name="FILE" class="org.apache.log4j.RollingFileAppender">
    <param name="File" value="./Log4jTest.log" />
    <param name="MaxFileSize" value="1000KB" />
    <param name="MaxBackupIndex" value="5" />
    <layout class="org.apache.log4j.PatternLayout">
      <param name="ConversionPattern" value="%d{ISO8601} %p - %m%n" />
    </layout>
    <filter class="org.apache.log4j.varia.LevelRangeFilter">
      <param name="LevelMin" value="WARN" />
      <param name="LevelMax" value="FATAL" />
    </filter>
  </appender>
  <root>
    <level value="ERROR" />
    <appender-ref ref="FILE" />
  </root>
</log4j:configuration>
Run Code Online (Sandbox Code Playgroud)