Skip to content

操作日志

操作日志中间件自动拦截写请求(POST/PUT/DELETE/PATCH)并记录操作日志,无需手动埋点。日志落库通过后台线程异步执行,不阻塞响应。源码位于 src/middleware/operation_log.py。

工作原理 ​

1. 请求进入 → operation_log 判断是否需要记录
2. 仅拦截写请求(POST/PUT/DELETE/PATCH),排除登录/验证码等路径
3. 记录请求参数、响应结果、耗时、操作类型
4. 日志落库通过后台线程异步执行
5. 不阻塞主请求,对性能影响极小

排除路径 ​

以下路径不记录操作日志:

python
# src/middleware/operation_log.py
_EXCLUDED_PATH_SEGMENTS = ("/login", "/captcha", "/logout", "/sendSms")

排除逻辑使用 endswith 匹配路径末段,而非精确匹配完整路径。

操作类型自动推断 ​

中间件根据 HTTP 方法和 URL 路径自动推断操作类型:

python
# src/middleware/operation_log.py

# HTTP 方法 → 日志类型
_METHOD_LOG_TYPE = {
    "POST": 3,   # 新增
    "PUT": 4,    # 修改
    "DELETE": 5, # 删除
}

# URL 路径关键字 → 日志类型(优先级高于方法)
_PATH_ACTION_TYPE = {
    "status": 4,      # 状态变更
    "import": 3,      # 导入
    "export": 5,      # 导出
    "batchDelete": 5, # 批量删除
}

def _infer_log_type(request) -> int:
    """从 HTTP 方法和 URL 路径推断操作类型"""
    # 先按路径关键字匹配
    for keyword, log_type in _PATH_ACTION_TYPE.items():
        if keyword in request.path:
            return log_type
    # 再按 HTTP 方法匹配
    return _METHOD_LOG_TYPE.get(request.method, 18)  # 18=其它
路径末段操作类型类型ID
add新增1
update修改2
delete删除3
batchdelete批量删除4
status状态设置5
resetpwd重置密码6
updatepassword修改密码7
import导入8
export导出9
kickout强退10
generate生成代码11
clear清空数据12
auth授权13
refresh缓存14
openaccount开账号15
其它其它0

日志字段 ​

字段说明
title操作标题(从路由装饰器获取)
type操作类型(自动推断)
method路由方法名
url请求路径
param请求参数(截取前2000字符)
result响应结果(截取前2000字符)
consume_time耗时(毫秒)
status状态:0-成功 1-失败
error错误信息
create_user操作人

查询接口 ​

GET /api/v1/oper/log/list?pageNo=1&pageSize=10
GET /api/v1/oper/log/detail/<id>

性能优化 ​

1. 后台任务:日志落库通过后台线程异步执行,不阻塞响应
2. 前缀解析:仅解析响应体前 8KB,避免大响应体全量解析
3. 长度截断:参数和结果截取前 2000 字符,防止撑爆日志表
4. 路径排除:登录/验证码等高频路径不记录
5. 路径段边界匹配:排除前缀按 path == prefix 或 prefix + '/' 匹配,避免子串误伤

中间件实现 ​

python
# src/middleware/operation_log.py
from flask import request, g
import time
import threading

def register_operation_log(app):
    """注册操作日志中间件"""

    @app.before_request
    def _start_timer():
        g.start_time = time.time()

    @app.after_request
    def _log_operation(response):
        # 仅记录写请求
        if request.method not in ('POST', 'PUT', 'DELETE', 'PATCH'):
            return response

        # 排除特定路径
        if any(seg in request.path for seg in _EXCLUDED_PATH_SEGMENTS):
            return response

        # 计算耗时
        consume_time = int((time.time() - g.start_time) * 1000)

        # 获取响应内容
        result = response.get_data(as_text=True)[:2000]

        # 异步记录日志
        def _save_log():
            # 保存日志到数据库
            pass

        thread = threading.Thread(target=_save_log)
        thread.start()

        return response

后台线程

Flask 使用后台线程异步记录操作日志,不阻塞主请求。日志记录失败不会影响正常业务流程。

总结 ​

操作日志模块具备以下特点:

1. 自动记录:中间件拦截写请求,无需手动埋点
2. 类型推断:根据 URL 路径自动推断操作类型
3. 异步落库:后台线程执行,不阻塞主请求
4. 性能友好:前缀解析 + 长度截断 + 路径排除
5. 完整信息:记录参数、结果、耗时、操作人等

小蚂蚁云团队 · 提供技术支持