Files
track/backend/alembic/versions
duxingchen 39697ca3ad feat(audit): 每日活动打点表 —— 修正日活「上线/下线时间」口径
【问题】
上线/下线时间此前取自审计记录(写操作)时间,当天只翻看、没做写操作的人
会被整条漏掉;而取登录时间更错(Refresh Token 有效期 7 天,用户不必每天登录,
会出现「登录次数 0 却操作 35 次」的自相矛盾报表)。

【方案 C+:一天一人一行的小状态表】
- 新增 user_daily_seen(user_id, day, first_seen_at, last_seen_at),
  迁移 k1l2m3n4o5p6(紧接 j1k2l3m4n5o6)
- 打点挂在 RequestContextMiddleware —— 它是最外层,能覆盖【所有】请求,
  含不被审计的普通 GET。挂审计中间件没用:那里只记写操作,正是漏人的原因
- 节流:进程内缓存,同一用户 2 分钟内只落盘一次,把"每请求一次写库"
  压到"每人每 2 分钟一次";代价是末次活动时间最多落后 2 分钟
- UPSERT on_conflict_do_update 只刷 last_seen_at,first_seen_at 保持当天首次值
- 打点失败全部吞掉并记日志,绝不影响业务请求

【为什么不复用 audit_logs】
「末次活动」是需要不断 UPDATE 的状态,而审计流水必须只增不改 ——
能改的审计记录等于没有审计价值。写进审计表还会让表随访问量线性膨胀。

【查询合并】
get_daily_usage 改为「活动表 ∪ 审计表」并集:只有活动记录的(只看不操作)
和只有审计记录的(本表上线前的历史数据)都会出现。
上线/下线时间取两者的【最早 / 最晚】而非"活动表优先"——打点有 2 分钟节流、
跨零点或写库失败时可能晚于当天第一次写操作,取 min/max 后结果永不劣于任一来源。

零前端改动、零移动端发版:打点在服务端,PC 与移动端同一套口径、同一张表。
2026-09-21 13:05:35 +08:00
..