Java实现日志拦截下载功能

需求:
前段时间根据工作人员反馈无法看到当前功能执行过程中的日志,希望实现一个日志导出的功能,可以查看当前功能执行过程中有哪些地方发生了错误,方便数据的调试。

实现:
使用过滤器,过滤到当前功能(方法)执行过程中产生的日志,将日志进行记录,当前功能(方法)执行完毕后,将过滤得到的日志写入到一个文件中进行下载即可。
废话不多说了,直接看代码,相信有一点经验的程序员都能看懂。

1. 实现一个过滤器,拦截日志

@Component
@Scope()
public class CiRouteLogFilter extends Filter<ILoggingEvent> {

//    先定义一个静态的标识变量为false,标识该过滤器的状态(true:生效,false:不生效)
    private static boolean status = false;

//    覆盖的方法,在项目启动时,该方法默认执行,该拦截器默认是启动生效的,在默认启动时,将自定义的状态修改为false
    @Override
    public void start() {
        status = false;
    }

//    自定义的一个启动方法,调用时将自定义的状态修改为true
    public void begin(){
        status = true;
    }

//    覆盖的方法,过滤器关闭的方法,在关闭过滤器时,将自定义的状态修改为false
    @Override
    public void stop() {
        status = false;
    }

//    获取自定义的状态标识
    public boolean getStatus() {
        return status;
    }

//    以上操作的主要目的是通过定义一个静态标识变量,来实现手动控制过滤器的启动与关闭,默认是自启动的


//    覆盖的一个方法,具体的过滤流程就在这里了
    @Override
    public FilterReply decide(ILoggingEvent iLoggingEvent) {

//        如果自定义的状态为true,则开始过滤,否则不进行任何操作
        if (getStatus()) {
            String exception = "";
            IThrowableProxy throwableProxy = iLoggingEvent.getThrowableProxy();
            if(throwableProxy != null){
                exception = "<span class='excehtext'>"+throwableProxy.getClassName()+" "+throwableProxy.getMessage()+"</span></br>";
                for(int i=0; i<throwableProxy.getStackTraceElementProxyArray().length;i++){
                    exception += "<span class='excetext'>"+throwableProxy.getStackTraceElementProxyArray()[i].toString()+"</span></br>";
                }
            }
//            自我封装的一个日志消息对象,将当前过滤到的日志消息封装到该对象中
            LoggerMessage loggerMessage = new CiLoggerMessage(
                    iLoggingEvent.getFormattedMessage(),
                    DateFormat.getDateTimeInstance().format(new Date(iLoggingEvent.getTimeStamp())),
                    iLoggingEvent.getThreadName(),
                    iLoggingEvent.getLoggerName(),
                    iLoggingEvent.getLevel().levelStr,
                    exception,
                    ""
            );
//            将该日志消息对象放入到自我定义的一个队列中,保证日志的顺序性
            CiLoggerQueue.getInstance().add(loggerMessage);
        }

//        放行该过滤器,使该过滤器继续向下执行其他的过滤器
//        FilterReply的值:ACCEPT 、NEUTRAL、DENY。
        return FilterReply.NEUTRAL;
    }

}

日志消息对象

@Data
@AllArgsConstructor
public class LoggerMessage {

    private String body;

    private String timestamp;

    private String threadName;

    private String className;

    private String level;

    private String exception;

    private String cause;
}
//CiLoggerMessage是该类的子类,在此没有做任何的扩展

存放日志的队列

public class CiLoggerQueue {

//	这是一个单例的队列,用来存放日志消息,该队列默认大小为3000,根据自己的业务进行调整
    private static LinkedBlockingQueue<LoggerMessage> ciMessageQueue = null;

    public synchronized static LinkedBlockingQueue<LoggerMessage> getInstance(){
        if (ciMessageQueue == null){
            ciMessageQueue = new LinkedBlockingQueue<LoggerMessage>(3000);
        }
        return ciMessageQueue;
    }
}

2. 配置该过滤器
在项目的logback.xml日志配置文件中对于自定义的过滤器进行配置
在这里插入图片描述

3. 在对应的功能上添加过滤

    @Autowired
    CiRouteLogFilter ciRouteFilter;

    @RequestMapping(value = "/downloadLog")
    public void uploadExcelCiRouteDownloadLog(@RequestParam(value = "containEndSignal",required = false)Boolean containEndSignal, HttpServletRequest req, HttpServletResponse response) {
//        手动启动自定义的日志过滤器,启动后自定义的状态为true
        ciRouteFilter.begin();
        
//        执行目标方法
        try{
            ...
        }catch (Exception ex){
            Logger.error(ex.getMessage());
        }


//        处理日志
        LinkedBlockingQueue<LoggerMessage> queue = CiLoggerQueue.getInstance();
        StringBuffer sb = new StringBuffer();
        for (LoggerMessage message : queue) {
            sb.append(message.getTimestamp()+"   ").append(message.getBody()).append("\n");
        }
        queue.clear();
        String log = sb.toString();
        ciRouteFilter.stop();

//        下载日志
        try {

            InputStream inputStream = IOUtils.toInputStream(log);
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/plain");
            response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode("log.txt", "UTF-8"));
            IOUtils.copy(inputStream,response.getOutputStream());
            response.getOutputStream().flush();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }

如有疑问,欢迎留言
到此结束,祝大家有所收获!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

难过的风景

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值