Flask基于队列Queue实现后端日志在前端实时展示

1、编写工具类

  1. 为整个服务创建日志 log.py,主要功能设置日志文件路径,日志格式,日志级别等
# -*- coding: utf-8 -*-
"""
@author:  [email protected]
@version: 1.0.0
@file:    log.py
@time:    2023/2/23 20:00
"""
import logging


def create_logger():
   logger = logging.getLogger("app")
   formatter = logging.Formatter("%(asctime)s[%(levelname)s]: %(message)s", datefmt="%Y-%m-%d %H:%M:%S")

   console_handler = logging.StreamHandler()
   console_handler.setFormatter(formatter)

   file_handler = logging.FileHandler("app.log", encoding="utf8")
   file_handler.setFormatter(formatter)

   logger.setLevel(logging.INFO)
   logger.addHandler(console_handler)
   logger.addHandler(file_handler)
   return logger

  1. r3.py工具类,该工具类主要是对日志接口做二次封装。在日志文件记录的同时,加入一个消息队列。同时get()方法提供从队列批量取消息功能。

r3.py

# -*- coding: utf-8 -*-
"""
@author:  [email protected]
@version: 1.0.0
@file:    r3.py
@time:    2023/2/23 20:25
"""
import logging
import re
import datetime
import queue
mq = queue.Queue()


class R3:
    logger = logging.getLogger("app")

    @staticmethod
    def put(item: str, level="INFO"):
        dtf = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        mq.put(f"{dtf}[{level}]: {item}")

    @staticmethod
    def debug(item, log=True):
        R3.put(item, level="DEBUG")
        if log:
            R3.logger.debug(item)

    @staticmethod
    def info(item, log=True):
        R3.put(item, level="INFO")
        if log:
            R3.logger.info(item)

    @staticmethod
    def warning(item, log=True):
        R3.put(item, level="WARNING")
        if log:
            R3.logger.warning(item)

    @staticmethod
    def error(item, log=True):
        R3.put(item, level="ERROR")
        if log:
            R3.logger.error(item)

    @staticmethod
    def critical(item, log=True):
        R3.put(item, level="CRITICAL")
        if log:
            R3.logger.critical(item)

    @staticmethod
    def get(count):
        data = []
        if mq.empty():
            return data
        pattern = re.compile(r"^.*?\[(INFO|ERROR|WARNING|DEBUG)]:.*$")
        try:
            for _ in range(count):
                item = mq.get_nowait()
                mq.task_done()
                match = re.match(pattern, item)
                message_level = match.group(1) if match else "INFO"
                data.append({"message": item, "level": message_level})
            return data
        except queue.Empty:
            return data


r3 = R3

2、编写flask app

main.py

# -*- coding:utf-8 -*-
"""
@author:  [email protected]
@version: 1.0.0
@file:    main.py
@time:    2023/2/23 19:58
"""
import random
import time
import threading
from flask import Flask, request, render_template
from faker import Faker
from log import create_logger
from r3 import r3
fake = Faker()


def simulated_generation_logs():
    """
    模拟生成后台日志,作为生产者
    实际生产环境中,各个业务逻辑产生日志
    :return:
    """
    def wrap():
        while True:
            sentence = fake.sentence()
            func = random.choice([r3.info, r3.warning, r3.error])        # 生成随机等级的日志
            func(sentence)
            time.sleep(1)
    thread = threading.Thread(target=wrap, name="simulated_generation_logs_thread", daemon=True)
    thread.start()


def create_app():
    app = Flask(__name__)
    # 创建日志
    create_logger()

    @app.get("/generate")
    def generate_logs():
        # 模拟生成日志
        simulated_generation_logs()
        return {"code": 200, "data": None, "msg": "ok"}

    @app.get("/message")
    def get_message():
        count = request.args.get("count", 50)
        data = r3.get(count)
        return {"code": 200, "data": data, "msg": "ok"}

    @app.get("/")
    def index_view():
        return render_template("index.html")
    return app


if __name__ == "__main__":
    app = create_app()
    app.run("127.0.0.1", port=5000, debug=True)

  • 路由/generate: 将会产生一个线程,不断的产生日志消息(消息等级随机),记录在日志文件,并同时加入队列。在实际业务中,日志message由实际业务流程中产生。
  • 路由/message: 从服务器批量获取消息

3、测试接口

启动服务后访问/generate,让服务器不断产生日志,可以看到请求成功,并且后端成功产生日志记录
Flask基于队列Queue实现后端日志在前端实时展示_第1张图片
Flask基于队列Queue实现后端日志在前端实时展示_第2张图片
访问/message,看能否正常取到后端服务器日志。可以看到是能够取到日志的,说明接口没问题,接下来就是第四步了。在前端展示日志
Flask基于队列Queue实现后端日志在前端实时展示_第3张图片

4、前端渲染日志

此步的原理就是在前端利用定时器和ajax,不断的请求/message接口,成功返回数据后异步渲染在前端页面,直接上代码。其中jquery资源在网上自己下载。代码整体目录结构如下:
Flask基于队列Queue实现后端日志在前端实时展示_第4张图片

index.html

DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>首页title>
    <script type="text/javascript" src="/static/jquery-2.1.1.min.js">script>
    <style>
        p{
            margin-block-start: 0;
            margin-block-end: 0;
        }
    style>
head>
<body style="background-color: #999999;">
<div class="main-body" style="background-color: #fff;width: 1000px;height: 95vh;overflow-y: scroll;margin: 20px auto;padding: 20px">
div>
<script>
    let main = $(".main-body");
    get_message()
    setInterval(get_message, 2000)

    function get_message() {
        $.ajax({
            url: "/message",
            type: "get",
            contentType: "application/json",
            async: true,
            success: (res)=>{
                console.log(res);
                if(res.code ===200) {
                    res.data.forEach(function (item, idx) {
                        let elem = $(`

${item.message}

`
) if (item.level === "INFO") { elem.css("color", "#11B45BFF") } else if (item.level === "ERROR") { elem.css("color", "#ef2309") } else { elem.css("color", "#f1a506") } main.append(elem) }) } } }) }
script> body> html>

接下来就是见证奇迹的时候,访问首页,就能够看到效果
Flask基于队列Queue实现后端日志在前端实时展示_第5张图片

总结

以上,就是通过队列实现Flask框架下后端日志在前端的实时输出渲染。
思路采用了消费者和生产者模式,服务器后端server作为日志Message的生产者,前端浏览器(Ajax请求)作为消费者。
原文地址:https://liyinbing.cn/article/det/49
整个代码地址:https://gitee.com/Bingo11/my-projects/tree/master/Web/Flask%E5%9F%BA%E4%BA%8E%E9%98%9F%E5%88%97Queue%E5%AE%9E%E7%8E%B0%E5%90%8E%E7%AB%AF%E6%97%A5%E5%BF%97%E5%9C%A8%E5%89%8D%E7%AB%AF%E5%AE%9E%E6%97%B6%E5%B1%95%E7%A4%BA

你可能感兴趣的:(python,flask,python,后端)