如何通过Python装饰器实现审计日志,将用户行为记录到数据库?
- 内容介绍
- 文章标签
- 相关推荐
本文共计1166个文字,预计阅读时间需要5分钟。
在业务函数上直接增加一层装饰器,是轻量级、侵入性最小的日志记录方案。它不改变原有的逻辑,仅负责将谁、什么时间、调用了什么、传了哪些参数、结果如何等信息记录到数据库。
常见错误是把所有参数原样 json.dumps 存进去——遇到 datetime、Decimal 或自定义对象会直接报 TypeError: Object of type ... is not JSON serializable。
- 只序列化可安全落库的字段:用户ID(
current_user.id)、函数名(func.__name__)、开始时间(datetime.utcnow())、参数快照(用repr()或白名单过滤后转字典) - 避免记录敏感参数:比如密码、token、银行卡号,装饰器里加个
exclude_keys=('password', 'token', 'card_number')参数 - 别在装饰器里做同步 DB 写入——高并发下会拖慢主流程;用
threading.Thread或异步队列(如queue.Queue配后台线程)异步落库
log_operation 必须能拿到当前用户上下文
Web 场景下,用户信息通常存在请求上下文(如 Flask 的 g.user、Django 的 request.user),但装饰器本身没 request 对象。
本文共计1166个文字,预计阅读时间需要5分钟。
在业务函数上直接增加一层装饰器,是轻量级、侵入性最小的日志记录方案。它不改变原有的逻辑,仅负责将谁、什么时间、调用了什么、传了哪些参数、结果如何等信息记录到数据库。
常见错误是把所有参数原样 json.dumps 存进去——遇到 datetime、Decimal 或自定义对象会直接报 TypeError: Object of type ... is not JSON serializable。
- 只序列化可安全落库的字段:用户ID(
current_user.id)、函数名(func.__name__)、开始时间(datetime.utcnow())、参数快照(用repr()或白名单过滤后转字典) - 避免记录敏感参数:比如密码、token、银行卡号,装饰器里加个
exclude_keys=('password', 'token', 'card_number')参数 - 别在装饰器里做同步 DB 写入——高并发下会拖慢主流程;用
threading.Thread或异步队列(如queue.Queue配后台线程)异步落库
log_operation 必须能拿到当前用户上下文
Web 场景下,用户信息通常存在请求上下文(如 Flask 的 g.user、Django 的 request.user),但装饰器本身没 request 对象。

