如果发生异常,则转储调试日志

时间:2015-04-28 18:36:06

标签: java logging slf4j logback error-logging

我正在编写一个java Web应用程序。我正在使用slf4j&记录的logback。我使用调试级别来输出一些可能对查找错误有用的信息,但通常它没用,而且非常详细。

我在应用程序中有一个位置可以捕获所有异常并记录它们。我想要做的是从请求开始捕获此线程中的所有先前日志记录输出,并将其全部保存在单独的事件文件中。因此,如果发生异常,我会为系统执行没有错误的干净日志和详细的事件日志。

这个问题有一些现成的解决方案吗?可能会有不同的方法吗?

现在我将所有调试输出保存到存储7天的文件中,但在需要时,轻击此文件并不是最容易完成的任务。

1 个答案:

答案 0 :(得分:2)

您可以创建自定义appender来存储所有日志消息,然后在需要时写入另一个appender。在请求开头调用clearLog,如果出现错误,请writeLog

import java.util.ArrayList;
import java.util.List;

import ch.qos.logback.core.Appender;
import ch.qos.logback.core.AppenderBase;

public class SavingAppender<E> extends AppenderBase<E> {
    private final ThreadLocal<List<E>> events = new ThreadLocal<List<E>>() {
        protected List<E> initialValue() {
            return new ArrayList<>();
        }
    };

    protected void append(E event) {
        events.get().add(event);
    }

    public void clearLog() {
        events.get().clear();
    }

    public void writeLog(Appender<E> other) {
        for(E event:events.get()) {
            other.doAppend(event);
        }
    }
}

配置所有日志消息以转到appender,并为事件日志创建另一个appender:

<configuration> 
    <appender name="savingAppender" class="SavingAppender"> 
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="outputError" class="ch.qos.logback.core.ConsoleAppender">
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter"> 
            <level>error</level>
        </filter>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <appender name="incidentAppender" class="ch.qos.logback.core.FileAppender">
        <file>output.log</file>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>

    <root level="info">
        <appender-ref ref="savingAppender"/>
        <appender-ref ref="outputError"/>
    </root>

    <logger name="incident">
        <appender-ref ref="incidentAppender"/>
    </logger>
</configuration>

测试类:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.Appender;

public class Main {
    public static void main(String[] args) {
        Logger rootLogger = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
        Appender<ILoggingEvent> savingAppender = ((ch.qos.logback.classic.Logger)rootLogger).getAppender("savingAppender");

        Logger incidentLogger = LoggerFactory.getLogger("incident");
        Appender<ILoggingEvent> incidentAppender = ((ch.qos.logback.classic.Logger)incidentLogger).getAppender("incidentAppender");

        ((SavingAppender<ILoggingEvent>)savingAppender).clearLog();

        LoggerFactory.getLogger(Main.class).error("Error 1...");
        LoggerFactory.getLogger(Main.class).error("Error 2...");
        LoggerFactory.getLogger(Main.class).error("Error 3...");
        LoggerFactory.getLogger(Main.class).info("Info 1...");
        LoggerFactory.getLogger(Main.class).info("Info 2...");
        LoggerFactory.getLogger(Main.class).info("Info 3...");

        ((SavingAppender<ILoggingEvent>)savingAppender).writeLog(incidentAppender);
    }
}