java 如何实现在线日志

news2024/10/2 1:27:07

如何采集springboot日志至web页面查看

实现方案

基于Filter方式,在日志输出至控制台前,LoggerFitler 拦截日志通过websocket推送至前台页面

实现逻辑:
LoggerFilter采集日志添加至LoggerQueue队列,
LoggerConsumer 从LoggerQueue中采集推送至前台页面

push
pull
socket
LoggerFilter
LoggerQueue
LoggerConsumer
wsLog.html

1. 配置拦截器

  • logback 在appender中指定filter 拦截
<configuration>
    <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%magenta(%d{yyyy-MM-dd HH:mm:ss.SSS}) %highlight(%-5level) %green([%thread]) %logger{40}: %m %n
            </pattern>
            <charset>utf8</charset>
        </encoder>
        <filter class="com.weblog.logger.LoggerFilter"></filter>
    </appender>
    <root level="info">
        <appender-ref ref="STDOUT"/>
    </root>
</configuration>

2. 代码逻辑

2.1 LoggerFilter 拦截日志来源

从ILoggingEvent 获取日志信息,封装为LoggerMessage ,添加至日志队列

public class LoggerFilter extends Filter<ILoggingEvent> {


    private String formatTime(long timestamp) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        return simpleDateFormat.format(new Date(timestamp));
    }

    /**
     * 解析日志事件信息内容 加入队列
     *
     * @param event 日志事件
     */
    @Override
    public FilterReply decide(ILoggingEvent event) {
        LoggerMessage log = new LoggerMessage();
        log.setClassInfo(event.getLoggerName());
        log.setLogTime(formatTime(event.getTimeStamp()));
        log.setLogInfo(event.getFormattedMessage());
        log.setLogLevel(event.getLevel().levelStr);
        String exception = "";
        IThrowableProxy throwableProxy = event.getThrowableProxy();
        if (throwableProxy != null) {
            exception = ThrowableProxyUtil.asString(throwableProxy);
        }
        log.setErrorInfo(exception);
        LoggerQueue.getInstance().push(log);
        return FilterReply.ACCEPT;
    }
}

2.2 LoggerQueue 提供日志的存放与获取

内置队列管理器, 提供pull 和push方法
代码未优化,队列应该选择先进先出

public class LoggerQueue {
    /**
     * 最大队列大小
     */
    public static final int QUEUE_MAX_SIZE = 10000;

    /**
     * 日志队列
     */
    private static LoggerQueue loggerQueue = new LoggerQueue();

    /**
     * 阻塞队列
     */
    private BlockingQueue<LoggerMessage> blockingQueue = new LinkedBlockingQueue<LoggerMessage>(QUEUE_MAX_SIZE);

    private LoggerQueue() {
    }

    public static LoggerQueue getInstance() {
        return loggerQueue;
    }

    /**
     * 推送最新日志消息
     *
     * @param loggerMessage 日志消息
     * @return 是否成功
     */
    public boolean push(LoggerMessage loggerMessage) {
        return this.blockingQueue.add(loggerMessage);//队列满了就抛出异常,不阻塞
    }

    /**
     * 拉取最新日志消息
     *
     * @return 日志消息
     */
    public LoggerMessage pull() {
        LoggerMessage loggerMessage = null;
        try {
            loggerMessage = this.blockingQueue.take();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return loggerMessage;
    }
}

2.4 WebSocketLoggerConsumer 实现消息推送至websocket

开启固定线程,获取日志队列信息,推送至websocket

@Component
public class WebSocketLoggerConsumer implements LoggerConsumer {

    @Resource
    private SimpMessagingTemplate messagingTemplate;

    /**
     * 创建日志消费线程池
     */
    @PostConstruct
    public void createLogExecutor() {
        ExecutorService executorService = Executors.newFixedThreadPool(1);
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                while (true) {
                    LoggerQueue loggerQueue = LoggerQueue.getInstance();
                    if (loggerQueue != null) {
                        consumer(loggerQueue.pull());
                    }
                }
            }
        };
        executorService.submit(runnable);
    }

    @Override
    public void consumer(LoggerMessage loggerMessage) {
        messagingTemplate.convertAndSend("/topic/log", loggerMessage.toString());
    }
}

3. 测试

3.1 测试示例

1s 写入1条info日志,2s 写入1条warn 日志

    @Scheduled(fixedDelay = 1000)
    private void mockLogInfoData() {
        logger.info("logger info data!");
    }

    @Scheduled(fixedDelay = 2000)
    private void mockLogWarnData() {
        logger.warn("logger warn data!");
    }

3.2 idea 控制台日志:

在这里插入图片描述

3.3 socket日志效果

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/397824.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

LearnOpenGL-光照-3.材质

本人刚学OpenGL不久且自学&#xff0c;文中定有代码、术语等错误&#xff0c;欢迎指正 我写的项目地址&#xff1a;https://github.com/liujianjie/LearnOpenGLProject 文章目录材质例子1代码相关光照太强了例子2例子3: 不同的光源颜色材质 引出材质 如果我们想要在OpenGL中模拟…

TTS | 语音合成常见数据集及数据格式详情

linkLJSpeech网址 &#xff1a; The LJ Speech Dataset (keithito.com)数据集描述&#xff1a;数据集大小&#xff1a;2.6GB这是一个公共领域的语音数据集&#xff0c;由 13&#xff0c;100 个简短的音频剪辑组成 一位演讲者阅读 7 本非小说类书籍的段落。为每个剪辑提供转录。…

删除的文件怎么恢复?恢复方法在这里(支持Win和Mac)

案例&#xff1a;文件永久删除还能找回来吗&#xff1f;关于Win和Mac系统的恢复方法 “前几天我在清理电脑垃圾&#xff0c;不小心误删了重要的文件。有没有什么比较全面的方法&#xff0c;可以帮助我恢复删除的文件啊&#xff1f;在线急等回复&#xff01;” 随着电脑使用的…

Golang 中 Slice的分析与使用(含源码)

文章目录1、slice结构体2、slice初始化3、append操作4、slice截取5、slice深拷贝6、值传递还是引用传递参考文献众所周知&#xff0c;在golang中&#xff0c;slice&#xff08;切片&#xff09;是我们最常使用到的一种数据结构&#xff0c;是一种可变长度的数组&#xff0c;本篇…

三维人脸实践:基于Face3D的渲染、生成与重构 <二>

face3d: Python tools for processing 3D face git code: https://github.com/yfeng95/face3d paper list: PaperWithCode 3DMM方法&#xff0c;基于平均人脸模型&#xff0c;可广泛用于基于关键点的人脸生成、位姿检测以及渲染等&#xff0c;能够快速实现人脸建模与渲染。推…

MySQL基础篇3

第一章 多表关系实战 1.1 实战1&#xff1a;省和市 方案1&#xff1a;多张表&#xff0c;一对多 方案2&#xff1a;一张表&#xff0c;自关联一对多 id1 name‘北京’ p_id null; id2 name‘昌平’ p_id1 id3 name‘大兴’ p_id1 id3 name‘上海’ p_idnull id4 name‘浦东’…

中国人工智能企业中集飞瞳全球港航人工智能领军者,箱况残缺检测视频流动态感知智能闸口,自动化港口码头数字化智慧港航中国人工智能企业

中国人工智能企业中集飞瞳全球港航人工智能领军者&#xff0c;箱况残缺检测视频流动态感知超级智能闸口&#xff0c;自动化港口码头数字化智慧港航。CIMCAI已完成全球250万人工智能集装箱箱况检验&#xff0c;完成全球上亿集装箱信息&#xff0c;先进产品在全球各港区及集装箱枢…

CNStack 多集群服务:基于 OCM 打造完善的集群管理能力

作者&#xff1a;学靖 概述 随着 Kubernetes 在企业业务中的应用和发展&#xff0c;单集群内的管理能力已经趋于完善&#xff0c;越来越多的客户期望在多云、多集群场景部署其业务&#xff0c;因此需要提供相应的多云、多集群管理能力。 CNStack 多集群服务是 CNStack 面向多…

【实现“大图”功能 Objective-C语言】

一、这时候,我们来实现另外一个功能,就是点击,实现这个“大图”, 1.点击“大图”按钮,实现这个“大图”, 那么我先给大家说一下,这个点击“按钮”,实现“大图”,这个思路是怎样的,大家看一下,这个示例程序,当你点击“大图”的时候,首先,这个图片变大,同时,后…

Nvidia jetson nano 部署yolov5_技术文档

Nvidia jetson nano 部署yolov5_技术文档 每天一句小姜格言&#xff1a;我行&#xff0c;我不是一般人儿 部署开始&#xff1a; 1、通过FileZilla&#xff0c;将window文件传输至jetson nano 上的nano文件夹下。 2、查看cuda 我买的jetson nano是带有配置好的镜像。系统配置…

[数据结构]:16-归并排序(顺序表指针实现形式)(C语言实现)

目录 前言 已完成内容 归并排序实现 01-开发环境 02-文件布局 03-代码 01-主函数 02-头文件 03-PSeqListFunction.cpp 04-SortFunction.cpp 结语 前言 此专栏包含408考研数据结构全部内容&#xff0c;除其中使用到C引用外&#xff0c;全为C语言代码。使用C引用主要是…

嵌入式开发:CIA保护跨连接设备的嵌入式数据

在嵌入式开发中&#xff0c;ITTIA SDL保护数据并确保嵌入式系统的开发安全。嵌入式系统中的数据管理安全威胁是什么?ITTIA如何解决这个问题?嵌入式系统和企业系统的数据管理理想情况下遵循相同的安全威胁。有三个主要的基本原则或目标被称为CIA&#xff1a;保密性&#xff1a…

【FATE联邦学习】standalone版Fateboard修改配置

背景&做法 很多其他程序&#xff08;比如vscode的code server&#xff09;也会使用这个 127 0 0 1:8080 socket进行通信&#xff0c;这样就没办法远程用vscode去开发了&#xff0c;所以需要修改下Fateboard的socket配置。官方文档中也给出了如何修改配置 The default data…

代码随想录--数组--滑动窗口解决最长/短子数组题型

注意题目是说找连续数组的和>s的最小长度&#xff0c;是“和”&#xff0c;不然都不知道题目在说什么。 http://【拿下滑动窗口&#xff01; | LeetCode 209 长度最小的子数组】 https://www.bilibili.com/video/BV1tZ4y1q7XE/?share_sourcecopy_web 看一下暴力算法&…

android 卡顿、ANR优化(1)屏幕刷新机制

前言&#xff1a; 本文通过阅读各种文章和源码总结出来的&#xff0c;如有不对&#xff0c;还望指出 目录 正文 基础概念 视觉暂留 逐行扫描 帧 CPU/GPU/Surface&#xff1a; 帧率、刷新率、画面撕裂 画面撕裂 Android屏幕刷新机制的演变 单缓存&#xff08;And…

限流算法详解

限流是我们经常会碰到的东西&#xff0c;顾名思义就是限制流量。它能保证我们的系统不会被突然的流量打爆&#xff0c;保证系统的稳定运行。像我们生活中&#xff0c;地铁就会有很多护栏&#xff0c;弯弯绕绕的&#xff0c;这个就是一种限流。像我们抢茅台&#xff0c;肯定大部…

案例17-环境混用带来的影响

目录一、背景介绍背景事故二、思路&方案三、过程四、总结nginx做转发fastdfs&#xff08;文件上传下载&#xff09;五、升华一、背景介绍 本篇博客主要介绍开发中项目使用依赖项环境闭一只带来的恶劣影响&#xff0c;在错误中成长进步。 背景 本公司另外一个产品开发God…

爱因斯坦求和约定 含代码einsum

目录 一、简介 1.哑标 2.自由标 二、torch实现 1.计算迹 2.取矩阵对角线 3.计算外积 4.batch矩阵乘法 5.带有子列表和省略号 一、简介 爱因斯坦求和约定(Einstein summation convention)是一种标记的约定, 又称为爱因斯坦标记法(Einstein notation), 可以基于一些约定…

position:absolute详解

position:absolute详解 日常开发中&#xff0c;经常会涉及元素的定位&#xff0c;我们都知道&#xff0c;绝对定位相对于最近position不为static的父级元素来定位&#xff0c;但其中定位的位置还是有细微的差别的。 绝对定位根据left和top属性来规定绝对定位元素的位置。 基…

2023年前端面试题集锦

2023年又是行情惨淡的一年&#xff0c;为此我从 「枇杷村IT面试宝典」小程序里收集了一些题目&#xff0c;更多题目可以扫下方二维码查看 现做个总结如下&#xff1a; 1. 在JavaScript中, 0 -0的结果是什么&#xff1f; 结果为true&#xff01; 严格等于比较的是值和类型&…