当前位置: 首页 > news >正文

Flask实现高效日志记录模块

目录

一. 简介:

1. 为什么需要请求日志

二.  日志模块组成

1.  对应日志表创建(包含日志记录的关键字段)

2.  编写日志记录静态方法

3.  在Flask中捕获请求日志

4.  捕获异常并记录错误日志

5.  编写日志接口数据展示

6.  写入数据展示

三. 日志信息格式处理问题

1. 如何处理流式响应(Passthrough)

2. 如何记录响应数据(如JSON响应)

3. 总结与优化建议

四 . 结尾


一. 简介:

在Flask应用中,日志记录是重要的功能之一,它可以帮助开发人员跟踪请求的处理情况,快速定位错误,并且有助于应用的监控与调试。本文将介绍如何在Flask应用中实现请求日志记录,包括如何记录请求的各种信息(如请求数据、响应数据、错误信息等)并将其保存到数据库中。我们还会演示如何捕获不同级别的日志(信息级别、错误级别),并讨论如何处理复杂的响应数据(如流式响应)。


1. 为什么需要请求日志

日志记录可以帮助开发人员和运维团队了解应用的行为和状态,尤其是在生产环境中。通过记录每次请求的详细信息,开发人员能够:

  • 跟踪应用性能。
  • 快速定位和调试错误。
  • 为监控和安全审计提供数据支持。

例如,在出现错误时,记录详细的堆栈信息、请求的URL、请求参数和响应数据,能够帮助你迅速分析问题并进行修复。

二.  日志模块组成

  1.  对应日志表创建(包含日志记录的关键字段

# 日志表
class Log(db.Model,TimestampMixin):"""日志表"""__tablename__ = 't_logs'__table_args__ = {'mysql_engine': 'InnoDB','comment': '日志表'}id = db.Column(db.Integer, primary_key=True, autoincrement=True,comment='id')user_id = db.Column(db.Integer,comment='用户ID')  # 用户IDip_address = db.Column(db.String(50),comment='ip地址')  # ip地址level = db.Column(db.String(50),comment='日志级别')  # 日志级别message = db.Column(db.Text,comment='日志内容')  # 日志内容module = db.Column(db.String(100),comment='模块名称')  # 模块名称method = db.Column(db.String(50),comment='方法名称')  # 方法名称url = db.Column(db.String(255),comment='请求的URL')  # 请求的URLrequest_data = db.Column(db.Text,comment='请求数据')  # 请求数据response_data = db.Column(db.Text,comment='响应数据')  # 响应数据error_code = db.Column(db.String(50),comment='错误代码')  # 错误代码stack_trace = db.Column(db.Text,comment='堆栈追踪')  # 堆栈追踪hostname = db.Column(db.String(100),comment='服务器主机名')  # 服务器主机名context = db.Column(db.String(255),comment='上下文信息')  # 上下文信息def __repr__(self):return f"<ErrorLog(id={self.id}, ip_address={self.ip_address}, level={self.level}, message={self.message})>"

2.  编写日志记录静态方法

    # db.session 进行数据提交等操作@staticmethoddef log_message(session, exception=None, user_id=None,error_code=None,level=None, message=None, **kwargs):try:# 获取请求数据request_data=''if request.method == 'GET':request_data = str(dict(request.args))  # 直接获取查询参数elif request.method == 'POST':if request.is_json:request_data = str(request.get_json())  # 获取 JSON 数据else:request_data = str(request.form)  # 获取表单数据# 获取请求的其他信息ip_address = request.remote_addr  # 获取客户端IP地址url = request.url  # 获取请求的URLresponse_data = str(kwargs.get('response_data', ''))  # 获取响应数据stack_trace = traceback.format_exc() if exception else ""  # 获取堆栈追踪hostname = socket.gethostname()  # 获取服务器主机名context = kwargs.get('context', 'Production')  # 上下文(默认生产环境)if not message:message = str(exception) if exception else "Unknown error"# 检查错误响应数据并跳过日志记录try:# 将响应数据从字符串转换为字典response_dict = json.loads(response_data)if isinstance(response_dict, dict) and response_dict.get("message") == "内部服务器错误":return  # 跳过日志记录except json.JSONDecodeError:# 如果无法解析 JSON,则跳过判断pass# print(user_id)# 创建并保存日志条目log = Log(user_id=user_id if user_id else 0,level=level,message=message,ip_address=ip_address,url=url,request_data=request_data,response_data=response_data,stack_trace=stack_trace,hostname=hostname,context=context,method=request.method,module=request.blueprint,error_code=error_code,)# 保存日志条目db.session.add(log)db.session.commit()except Exception as e:print(e)pass

3. 在Flask中捕获请求日志

在Flask中,我们可以通过使用 after_request 钩子来捕获请求信息。这个钩子在每次请求处理完毕后执行,适合用于记录日志。示例如下:

# 请求成功日志记录
@app.after_request
def after_request(response):# 获取当前用户信息user_id = Nonelevel = "INFO"  # 你可以根据需要动态设置日志级别,如根据响应状态码判断message = "请求成功!"  # 请求成功的默认信息# 记录日志try:current_user = get_jwt_identity()# 获取用户信息(从数据库中获取用户信息做对比)user_info = db.session.query(User).filter(User.username == current_user).first()user_id = user_info.idexcept RuntimeError as e:# 捕获没有 JWT 时抛出的 RuntimeError 异常# 不做任何事情,直接跳过日志记录passexcept Exception as e:print(e)pass# 如果响应处于 passthrough 模式,则不能直接访问 response.dataif not response.direct_passthrough:# 正常情况下获取响应数据并转化为文本response_data = response.get_data(as_text=True)else:# 如果是 passthrough 模式,说明是流式响应或直接传递模式response_data = "{}"  # 或者根据需求设置适当的默认值if user_id:Log.log_message(db.session,user_id=user_id if user_id else 0,level=level,message=message,response_data=response_data,context="Production",  # 可选的环境信息error_code=200,)return response

在这个例子中,我们通过 after_request 钩子来处理每个请求后执行的日志记录。获取响应数据时,根据响应的类型决定是否直接获取 response.data

4. 捕获异常并记录错误日志

在实际开发中,应用程序往往会遇到异常。为了保证日志的完整性,我们可以捕获异常并将其记录下来。特别是对于HTTP 500类错误,应该记录详细的堆栈信息。

# 异常处理日志记录
@app.errorhandler(Exception)
def handle_exception(e):# 捕获所有异常,记录日志level = "ERROR"message = str(e)  # 将异常转换为字符串stack_trace = traceback.format_exc()  # 获取堆栈追踪# 获取当前用户信息user_id = Nonetry:current_user = get_jwt_identity()user_info = db.session.query(User).filter(User.username == current_user).first()user_id = user_info.idexcept RuntimeError:# 如果没有 JWT 则不记录用户IDpassif user_id:# 记录异常日志Log.log_message(db.session,exception=e,user_id=user_id,level=level,message='请求失败!',stack_trace=stack_trace,context="Production",error_code=500,)print(message)# 返回通用的500错误响应return {"message": "内部服务器错误"}, 500

在这个例子中,我们捕获了通用的异常,并将错误信息、堆栈追踪以及其他日志信息保存到数据库。

5. 编写日志接口数据展示

from flask import Response, jsonify, Flask, request, Blueprint,url_for
from configs import *
from modules.Tables import *
from sqlalchemy import func# 创建蓝图,对应的register目录(激活操作视图)
log_view = Blueprint('log_view', __name__)# 日志信息展示
@log_view.route('/log_data', methods=['GET'])
@jwt_required()
def log_data():# 获取分页参数page = request.args.get('page', default=1, type=int)  # 当前页码per_page = request.args.get('per_page', default=15, type=int)  # 每页显示条目数量level = request.args.get('level')  # 日志等级# 定义筛选列表filters = []# 当筛选条件存在时添加到列表if level:filters.append(Log.level == level)# 构建查询条件query = and_(*filters) if filters else True  # 如果 filters 为空,默认条件为 True# 查询主区域点并进行分页pagination = db.session.query(Log.id,Log.user_id,Log.ip_address, Log.level,Log.message,Log.module,Log.method,Log.url,Log.request_data, Log.response_data,Log.error_code, Log.stack_trace,Log.hostname,Log.context,Log.created_at).filter(query).paginate(page=page, per_page=per_page, error_out=False)# 获取分页后的数据data_list = [{'id': item.id,'user_id': item.user_id,'ip_address': item.ip_address,'level': item.level,'message': item.message,'module': item.module,'method': item.method,'url': item.url,'request_data': item.request_data if item.response_data else item.stack_trace,'response_data': item.response_data,'error_code': item.error_code,# 'stack_trace':item.stack_trace,'hostname':item.hostname,'context':item.context,'created_at': format_datetime(item.created_at),}for item in pagination.items]# 构造返回结果,包括分页信息response = {'code': 200,'data': data_list,'pagination': {'current_page': pagination.page,'total_pages': pagination.pages,'total_items': pagination.total,'per_page': pagination.per_page}}return jsonify({'code':200,'data':response})

 6. 写入数据展示

三. 日志信息格式处理问题

1. 如何处理流式响应(Passthrough)

Flask中的流式响应(passthrough)不允许直接访问 response.data,因此需要特别处理。通过 response.get_data(as_text=True) 方法,我们可以安全地获取响应数据并将其存储到日志中。如果响应不可序列化(如流式数据),可以跳过或记录默认值。

if not response.direct_passthrough:response_data = response.get_data(as_text=True)
else:response_data = "Non-serializable response"

2. 如何记录响应数据(如JSON响应)

对于返回JSON数据的响应,我们可以通过 response.get_data(as_text=True) 获取响应体的内容。这种方式适用于大多数JSON响应,确保我们可以将响应内容记录到日志中。

例如,在捕获日志时,我们可以如下处理响应数据:

response_data = response.get_data(as_text=True)

对于非JSON响应,使用 str() 也能保证将其转化为可记录的格式。

3. 总结与优化建议

  • 在Flask应用中,通过 @app.after_request 钩子可以轻松地记录每次请求的日志。
  • 根据不同的请求方法(GET/POST)和响应类型(JSON、流式数据等),动态调整日志记录方式。
  • 使用 try-except 语句捕获异常,并记录详细的错误信息以帮助后期的调试和维护。

通过这些方法,我们可以高效、全面地记录Flask应用中的日志,并为后期的性能优化、故障排查提供支持。

四 . 结尾

日志记录是开发和运维过程中不可或缺的一部分,它能帮助我们及时发现问题并做出调整。通过本文介绍的日志记录方式,我们能够方便地捕获请求和响应的详细信息,同时处理各种异常和特殊情况。希望这篇文章能够帮助你更好地理解并实现Flask中的日志记录。

相关文章:

Flask实现高效日志记录模块

目录 一. 简介&#xff1a; 1. 为什么需要请求日志 二. 日志模块组成 1. 对应日志表创建&#xff08;包含日志记录的关键字段&#xff09; 2. 编写日志记录静态方法 3. 在Flask中捕获请求日志 4. 捕获异常并记录错误日志 5. 编写日志接口数据展示 6. 写入数据展…...

scroll、offset、client三大家族和getBoundingClientRect方法

scroll、offset、client三大家族和getBoundingClientRect方法 1.offset(只能读,不能修改&#xff09;2.client(只能读,不能修改&#xff09;3.scroll滚动家族4.getBoundingClientRect方法 1.offset(只能读,不能修改&#xff09; offsetParent:离当前元素最近的有定位的祖先元素…...

JWT 令牌

目录 一、JWT 1、什么是JWT 2、JWT的组成 3、JJWT签发与验证token 1、创建token 2、解析token 3、设置过期时间 4、自定义claims 前言&#xff1a; 在现代Web应用和微服务架构中&#xff0c;用户身份验证和信息安全传输是核心问题。JSON Web Token&#xff08;J…...

Python基于Flask的豆瓣Top250电影数据可视化分析与评分预测系统(附源码,技术说明)

博主介绍&#xff1a;✌IT徐师兄、7年大厂程序员经历。全网粉丝15W、csdn博客专家、掘金/华为云//InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;&#x1f3…...

JavaScript数组-遍历数组

在JavaScript中&#xff0c;数组是一种非常常用的数据结构&#xff0c;用于存储一系列有序的数据项。无论是处理简单的列表还是复杂的数据集合&#xff0c;遍历数组都是我们经常需要执行的操作之一。本文将详细介绍几种常见的遍历数组的方法&#xff0c;并讨论它们各自的优缺点…...

基于Flask的第七次人口普查数据分析系统的设计与实现

【Flask】基于Flask的第七次人口普查数据分析系统的设计与实现&#xff08;完整系统源码开发笔记详细部署教程&#xff09;✅ 目录 一、项目简介二、项目界面展示三、项目视频展示 一、项目简介 基于Flask的人口普查可视化分析系统 二、项目界面展示 登录/注册 首页/详情 …...

解决DeepSeek服务器繁忙的有效方法

全球42%的企业遭遇过AI工具服务器过载导致内容生产中断&#xff08;数据来源&#xff1a;Gartner 2025&#xff09;。当竞品在凌晨3点自动发布「智能家居安装指南」时&#xff0c;你的团队可能正因DeepSeek服务器繁忙错失「净水器保养教程」的流量黄金期⏳。147SEO智能调度系统…...

分词器(Tokenizer) | 有了分词器,为什么还需要嵌入模型

文章目录 什么是tokenizer有了分词器&#xff0c;为什么还需要嵌入模型分词器为什么在transformers 里Hugging Face的Tokenizer大模型不同tokenizer训练效果对比分词器库选择当前顶尖大模型所采用的 Tokenizer 方法与词典大小 参考 什么是tokenizer Tokenizers huggingface官方…...

VisionTransformer(ViT)与CNN卷积神经网络的对比

《------往期经典推荐------》 一、AI应用软件开发实战专栏【链接】 项目名称项目名称1.【人脸识别与管理系统开发】2.【车牌识别与自动收费管理系统开发】3.【手势识别系统开发】4.【人脸面部活体检测系统开发】5.【图片风格快速迁移软件开发】6.【人脸表表情识别系统】7.【…...

计算机视觉+Numpy和OpenCV入门

Day 1&#xff1a;Python基础Numpy和OpenCV入门 Python基础 变量与数据类型、函数与类的定义、列表与字典操作文件读写操作&#xff08;读写图像和数据文件&#xff09; 练习任务&#xff1a;写一个Python脚本&#xff0c;读取一个图像并保存灰度图像。 import cv2 img cv2.im…...

Vue 3 工程化打包工具:从理论到实践 (下篇)

引言 在前端开发中&#xff0c;打包工具是工程化的重要组成部分。Vue 3 作为当前流行的前端框架&#xff0c;其工程化离不开高效的打包工具。打包工具不仅能够将代码、样式、图片等资源进行优化和压缩&#xff0c;还能通过模块化、代码分割等功能提升应用的性能。本文将深入探…...

java经验快速学习python!

title: java经验快速学习python&#xff01; date: 2025-02-19 01:52:05 tags: python学习路线 java经验快速学习python&#xff01; 本篇文档会一直更新&#xff01;&#xff01;&#xff01;变量、分支结构、循环结构、数据结构【列表、元组、集合字典】python常用内置函数元…...

爬虫破解网页禁止F12

右击页面显示如下 先点击f12再输入网址&#xff0c;回车后没有加载任何数据 目前的一种解决方法&#xff1a; 先 AltD &#xff0c;再 CtrlShifti...

从零开始构建一个语言模型中vocab_size(词汇表大小)的设定规则

从零开始构建一个语言模型就要设计一个模型框架,其中要配置很多参数。在自然语言处理任务中,vocab_size(词汇表大小) 的设定是模型设计的关键参数之一,它直接影响模型的输入输出结构、计算效率和内存消耗。 本文是在我前文的基础上讲解的:从零开始构建一个小型字符级语言…...

Jenkins插件管理切换国内源地址

安装Jenkins 插件时&#xff0c;由于访问不了国外的插件地址&#xff0c;会导致基本插件都安装失败。 不用着急&#xff0c;等全部安装失败后&#xff0c;进入系统&#xff0c;修改插件源地址&#xff0c;重启后在安装所需插件。 替换国内插件更新地址 选择&#xff1a;系统…...

Q - learning 算法是什么

Q - learning 算法是什么 Q - learning 算法是一种经典的无模型强化学习算法,由克里斯沃特金斯(Chris Watkins)在 1989 年提出。它被广泛应用于解决各种决策问题,尤其适用于智能体在环境中通过与环境交互来学习最优策略的场景。下面从基本概念、核心公式、算法流程和特点几…...

nasm - console 32bits

文章目录 nasm - console 32bits概述笔记my_build.batnasm_main.asm用VS2019写个程序&#xff0c;按照win32方式编译&#xff0c;比较一下。备注END nasm - console 32bits 概述 看到一个nasm的例子(用nasm实现一个32bits控制台的程序架子) 学习一下 笔记 my_build.bat ec…...

11.编写前端内容|vscode链接Linux|html|css|js(C++)

vscode链接服务器 安装VScode插件 Chinese (Simplified) (简体中⽂) Language Pack for Visual Studio CodeOpen in BrowserRemote SSH 在命令行输入 remote-ssh接着输入 打开配置文件&#xff0c;已经配置好主机 点击远程资源管理器可以找到 右键链接 输入密码 …...

【deepseek-r1模型】linux部署deepseek

1、快速安装 Ollama 下载&#xff1a;Download Ollama on macOS Ollama 官方主页&#xff1a;https://ollama.com Ollama 官方 GitHub 源代码仓库&#xff1a;https://github.com/ollama/ollama/ 官网提供了一条命令行快速安装的方法。 &#xff08;1&#xff09;下载Olla…...

【Github每日推荐】-- 2024 年项目汇总

1、AI 技术 项目简述OmniParser一款基于纯视觉的 GUI 智能体&#xff0c;能够准确识别界面上可交互图标以及理解截图中各元素语义&#xff0c;实现自动化界面交互场景&#xff0c;如自动化测试、自动化操作等。ChatTTS一款专门为对话场景设计的语音生成模型&#xff0c;主要用…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

SkyWalking 10.2.0 SWCK 配置过程

SkyWalking 10.2.0 & SWCK 配置过程 skywalking oap-server & ui 使用Docker安装在K8S集群以外&#xff0c;K8S集群中的微服务使用initContainer按命名空间将skywalking-java-agent注入到业务容器中。 SWCK有整套的解决方案&#xff0c;全安装在K8S群集中。 具体可参…...

K8S认证|CKS题库+答案| 11. AppArmor

目录 11. AppArmor 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、切换节点 3&#xff09;、切换到 apparmor 的目录 4&#xff09;、执行 apparmor 策略模块 5&#xff09;、修改 pod 文件 6&#xff09;、…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

[10-3]软件I2C读写MPU6050 江协科技学习笔记(16个知识点)

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16...

Python如何给视频添加音频和字幕

在Python中&#xff0c;给视频添加音频和字幕可以使用电影文件处理库MoviePy和字幕处理库Subtitles。下面将详细介绍如何使用这些库来实现视频的音频和字幕添加&#xff0c;包括必要的代码示例和详细解释。 环境准备 在开始之前&#xff0c;需要安装以下Python库&#xff1a;…...

大模型多显卡多服务器并行计算方法与实践指南

一、分布式训练概述 大规模语言模型的训练通常需要分布式计算技术,以解决单机资源不足的问题。分布式训练主要分为两种模式: 数据并行:将数据分片到不同设备,每个设备拥有完整的模型副本 模型并行:将模型分割到不同设备,每个设备处理部分模型计算 现代大模型训练通常结合…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

C语言中提供的第三方库之哈希表实现

一. 简介 前面一篇文章简单学习了C语言中第三方库&#xff08;uthash库&#xff09;提供对哈希表的操作&#xff0c;文章如下&#xff1a; C语言中提供的第三方库uthash常用接口-CSDN博客 本文简单学习一下第三方库 uthash库对哈希表的操作。 二. uthash库哈希表操作示例 u…...