Files
junhong_cmp_fiber/openspec/changes/refactor-audit-log-persistence/proposal.md
邹进 b7a7430cc3
All checks were successful
构建并部署到测试环境(无 SSH) / build-and-deploy (push) Successful in 12m8s
feat: 审计动作按落库策略分级写入,系统过程动作改写应用日志
- 审计注册表为可由系统任务、定时任务发起的动作声明落库策略(always/on_success/outcome/log_only/none),未声明按 log_only
- 人工、开放接口、个人客户、外部系统发起的动作始终写审计表
- log_only 写所在服务 app.log(logger=audit),不含快照
- 对接日志不再补写 integration.attempt_started,无上游审计时 audit_event_id 为空
- 新增 audit.persist_overrides 按动作覆盖策略
- 审计覆盖扫描要求机器动作必须声明策略
- 新增 OpenSpec 提案 refactor-audit-log-persistence 与技术方案文档

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-05 18:27:24 +09:00

6.2 KiB
Raw Blame History

Why

统一审计表被当作过程日志使用。系统任务每次同步、扣减、对接调用开始、失败重试,都会写一条审计事件,外加 2–3 条资源快照。生产近 14 天日均写入约 122 万条,其中 99% 以上由机器发起;测试环境日均约 12.6 万条。两张审计表合计 21 个索引,写入成本高,是 11-03 生产数据库 IO 打满、轮询停摆的主要原因之一。

同时,从审计中移出的过程数据必须仍能查到。现有采集记录、停复机记录等业务表大多只能按单卡查询,筛选条件少。采集失败的具体原因被丢弃,也没有保存运营商原始响应,出了问题无据可查。

方案依据:docs/2026-11-05-审计日志写入改造技术方案.md(方案 B)。本 Change 基于 Iteration/8-11 实施,只部署到测试环境。

What Changes

审计写入

  • 统一审计注册表为每个动作声明落库策略:总是写、只写成功、只写结论、只写应用日志、不写。
    • 未声明策略的系统任务、定时任务动作,默认只写应用日志。
    • 后台账号、个人客户、OpenAPI、外部系统发起的动作始终写审计。
  • 系统任务的过程类动作不再写审计表,改写到所在服务的应用日志(logs/app.log,带 logger=audit 标记,不含变更前后快照)。涉及的动作包括:流量同步、网络状态同步、流量扣减、停机原因更新、通知投递、优先轮询、流量重置明细等。
  • 自动重试类动作只写最终结论:最终成功,或重试用尽转人工。每一次尝试都记录在业务尝试记录表中。
  • BREAKING 对接日志不再补写 integration.attempt_started 审计事件。没有上游审计事件的对接日志,其 audit_event_id 允许为空。
  • 提供按动作的运行时覆盖配置,不发版即可临时调整某个动作的落库策略。

退款资产后处理

  • 新增退款后处理尝试记录,每次尝试一条,只增不改。
  • 自动重试最多 10 次,指数退避,间隔最长 1 小时。超过上限后标记"需人工处理",不再自动重投。

停复机记录

  • 停复机指令在调用上游之前就结束时(已是目标状态、条件不再满足、不允许停复机),写一条结果为"跳过"的停复机记录,并写明原因。

运营商流量采集记录

  • BREAKING 成功与失败分表:现有采集记录表只写成功读数,新增采集失败表。
    • 失败记录带错误类别、上游返回码与信息、耗时。
    • 失败记录不再判断卡有没有套餐,所有轮询到的卡都写。
  • 成功表和失败表都保存网关原始请求(加密前明文业务参数)与原始响应。
  • BREAKING 在线保留由 90 天改为 2 个月(当月加最近 2 个整月)。到期的月分区按"摘出分区、导出 csv.gz、校验、删除"四步处理,压缩包和说明文件留在 worker 运行目录,由同步服务器拉走。

记录查询接口

  • 每类独立记录各提供一个列表接口:传卡标识查单个,不传查全部。
  • 都支持分页和条件筛选,时间范围必填。所需索引随筛选条件新建或重建。
  • 覆盖的记录:采集成功、采集失败、停复机、套餐日流量详单、卡日流量、流量冲正、退款后处理尝试。退款列表增加后处理状态筛选。

测试环境部署配置

  • api、worker 各自挂载自己的 logs/ 目录,不再共用同一个 app.log。
  • 每个服务保留 40 个压缩备份。
  • worker 挂载 archive/ 目录。

Capabilities

New Capabilities

  • operational-record-query:独立业务记录的统一分页条件查询。覆盖采集成功与失败、停复机、套餐日流量、卡日流量、流量冲正、退款后处理尝试;可查单个,也可查全部。
  • refund-asset-post-processing:退款资产后处理的逐次尝试记录、重试上限、退避与转人工。

Modified Capabilities

  • operations-audit:审计落库策略分级;系统过程动作改写应用日志;结论型写入;对接日志允许无审计关联;轮询审计边界调整。
  • card-traffic-metering:采集记录成功与失败分表、保存原始请求与响应、失败记录不再判断有无套餐、在线保留 2 个月并到期归档为压缩包。该 capability 来自尚未归档的 add-card-traffic-queue-and-observed-deduction,本 Change 须在其归档后再归档。
  • gateway-call-observability:停复机指令在调用前结束时写"跳过"记录。该 capability 来自尚未归档的 add-carrier-gateway-rate-limit,本 Change 须在其归档后再归档。

Impact

  • 审计:internal/infrastructure/audit(注册表、Writer)、pkg/constants/audit.go、internal/governance/auditcoverage、internal/query/audit(时间线合并停复机记录)。
  • 对接日志:internal/infrastructure/integrationlog/repository.go。
  • 退款:internal/service/refund、internal/infrastructure/commissiondelivery(补偿扫描),新增尝试记录表。
  • 停复机:停复机指令执行路径中写入跳过记录。
  • 采集:
    • 原始数据收集器:internal/gateway/client.go
    • 采集写入:internal/task/polling_carddata_handler.go、internal/application/cardobservation
    • 存储与分区维护:internal/store/postgres/card_traffic_collection_store.go、cmd/worker/main.go
  • 接口:internal/routes、internal/handler/admin、internal/model/dto、internal/store/postgres,并同步生成接口文档。
  • 数据库迁移:
    • 新增采集失败表、退款后处理尝试表;
    • 采集成功表增加 carrier_id 与原始数据列;
    • 退款单增加后处理状态字段;
    • 各记录表新建或重建索引。
  • 配置与部署:pkg/config(audit.persist_overrides)、docker-compose.prod.yml、.gitea/workflows/deploy.yaml。
  • 与已有 Change 的关系:add-audit-integration-write-switches 的全局写入开关保持不变。全局开关用于应急全停;本 Change 是常态下按动作分级,两者互不替代。
  • 不涉及:生产环境的代码、配置与服务;已有审计数据的删除或迁移。