# 系统日志与审计日志 — 产品 + 设计文档 > **版本**:v1.0 | **日期**:2026-07-09 | **作者**:许清楚(产品经理)| **关联文档**:[PRD v1.2](../../01-产品文档/IT智能服务台-产品需求文档PRD-v2.md) / [架构设计 v1.3](../../02-技术文档/技术架构/IT智能服务台-系统架构设计文档v2.md) / [安全审计报告-日志结构化](../../06-安全审计/审计报告-安全审计/健康检查+错误码+日志结构化.md) / [管理员手册 §10.2](../../05-运营文档/用户手册/03-管理员手册.md) > > **一句话**:管理后台长期存在 5 类「日志」机制概念混淆,本文档统一 A/B/C/D/E 的定义、边界、接口与权限,并落地用户(宋献,税友集团 IT 支持组长)已拍板的 5 项决策。 --- ## 1. 概述:为什么要有这份文档 管理后台经代码与文档盘点,确认存在 5 类被笼统称为「日志」的机制,但其**记录对象、落点、读者、用途**各不相同,长期造成概念混淆与维护歧义: - **A. 系统日志** = 配置变更历史(记「配置项改了什么值」) - **B. 操作日志 / 审计日志** = 安全行为事件(记「谁做了什么安全相关动作」) - **C. 自动化动作日志** = 外部系统调用出入参(排障 + 审计) - **D. 运行期结构化日志** = 应用运行 stdout 日志(排障) - **E. 会话 / 消息记录** = 业务主数据(非独立日志子系统) 其中 A 与 B 最易混淆(都涉及「配置变更」),当前 A 页面**无任何筛选控件**;D 运行期日志查看(决策 4)**已落地**(后端接口 `GET /api/admin/runtime-logs` + 前端 `RuntimeLogs.vue` + 部署 `RUNTIME_LOG_DIR` bind mount)。本文档目标: 1. 给五类日志一个**统一定义与命名**,消除歧义; 2. 明确 **A vs B** 的关键差异与双写边界; 3. 将用户 5 项决策**产品化**为可验收的规格; 4. 作为下一阶段架构师(高见远)的输入,**自包含**地描述接口、字段、权限。 --- ## 2. 五类日志总览表 | 编号 | 内部名称 | 管理后台 UI 命名 | 落点(表 / 存储) | 核心用途 | 主要读者 | 实现状态 | |------|----------|------------------|-------------------|----------|----------|----------| | **A** | 系统日志(配置变更历史) | **配置变更历史** | `config_change_logs` | 记录配置项前后值 diff | 管理员 / 运维 | 已实现(前端无筛选) | | **B** | 操作日志 / 审计日志 | **安全审计日志** | `audit_logs` | 记录安全行为事件 | 管理员 / 审计员 | 已实现(部分事件待补) | | **C** | 自动化动作日志 | 自动化动作日志 | `auto_action_logs` | 外部系统调用出入参全量落表 | 运维 / 开发 | 已实现(落表为主) | | **D** | 运行期结构化日志 | 运行期日志查看 | stdout → Docker 文件 | 应用运行排障 | 运维 / 开发 | 已落地(前后端 + 部署) | | **E** | 会话 / 消息记录 | 会话与消息 | `conversations` / `messages` | 业务主数据(会话日志格式规范) | 坐席 / 管理员 | 已实现 | > **关系图**:配置变更动作同时写 A 与 B(双写,不收敛);C 记录自动化对外调用;D 是应用层运行日志;E 是业务数据,阶段四对其约定「会话日志格式规范」。 ```mermaid flowchart LR subgraph 写 PUT[PUT /api/admin/configs/key] -->|双写| A[(A config_change_logs)] PUT -->|双写 config_change 事件| B[(B audit_logs)] end subgraph 落表 AUTO[自动化动作] --> C[(C auto_action_logs)] APP[应用运行] -->|JSONFormatter + trace_id| D[(D stdout→Docker文件)] CHAT[会话/消息] --> E[(E conversations/messages)] end subgraph 读-管理后台 A --> PA[配置变更历史页] B --> PB[安全审计日志页] C -. 暂未暴露列表接口 .-> PC[(待定)] D --> PD[运行期日志查看页] E --> PE[会话管理] end ``` --- ## 3. 逐类详述 ### 3.1 A — 配置变更历史(系统日志) **定义**:系统配置项被修改时自动记录的前后值差异(diff),用于「配置改了什么、谁改的、什么时候改的」可回溯。 **使用场景(谁 / 何时 / 为什么)**: - **谁**:系统管理员(admin)。 - **何时**:调用 `PUT /api/admin/configs/{key}` 更新任意配置项时,由后端自动写入(该接口注释「更新单个配置项(同时记录变更日志)」)。 - **为什么**:排查「为什么某功能表现变了」时,快速定位配置被谁在何时改成什么值。 **接口**: | 项目 | 说明 | |------|------| | 列表查询 | `GET /api/admin/system-logs`(当前参数 `page` / `page_size`) | | 写入触发 | `PUT /api/admin/configs/{key}`(admin_api.py 第 117 行)→ 同时写 A 与 B | | 实现 | `admin_service.get_system_logs` | | 权限 | admin(沿用 `/api/admin` 鉴权;建议明确为 `config_log:read`) | > **决策 3(待开发)**:`GET /api/admin/system-logs` 需补充过滤参数 `config_key`(配置键)、`changed_by`(操作人 agent_id)、`changed_from` / `changed_to`(时间),并在前端 A 页面增加对应筛选控件。 **数据模型(JSON Schema 风格)**: ```json { "ConfigChangeLog": { "config_key": "string // 配置项键", "old_value": "string? // 变更前的值", "new_value": "string? // 变更后的值", "changed_by": "string // 操作人 agent_id", "changed_by_name": "string // 操作人姓名", "changed_at": "datetime // 变更时间" } } ``` > Schema:`backend/app/schemas/admin.py` 的 `ConfigHistoryItem`;模型:`backend/app/models/config_change_log.py`。前端:`frontend-admin/src/views/SystemLogs.vue`(el-table 五列:时间 / 配置键 / 操作人 / 变更前红色删除线 / 变更后绿色 + 分页 20/50/100)。 **UI 命名(决策 1)**:管理后台侧边栏原「系统日志」→ 明确命名为 **「配置变更历史」**,与 B 的「安全审计日志」并列区分。 --- ### 3.2 B — 安全审计日志(操作日志 / 审计日志) **定义**:记录系统中与安全相关的行为事件(登录、消息、会话、管理员操作、配置变更等),用于审计与合规追溯。 **使用场景(谁 / 何时 / 为什么)**: - **谁**:管理员、审计员(auditor)。 - **何时**:关键行为发生时由对应业务代码写入(见下方「已记录事件」)。 - **为什么**:安全审计、责任追溯、异常行为发现(如异常登录、敏感数据查询)。 **接口**: | 项目 | 说明 | |------|------| | 查询 | `GET /admin/audit-logs`(router 前缀 `/admin/audit-logs`) | | 过滤参数 | `employee_id` / `action` / `resource` / `from` / `to` / `page` / `page_size` | | 权限 | `audit_log:read:all`(admin / auditor 角色) | | 实现 | `backend/app/api/audit_logs.py` | **数据模型(JSON Schema 风格)**: ```json { "AuditLog": { "employee_id": "string // 操作人", "action": "string // 动作类型,如 login/logout/config_change", "resource": "string // 资源类型", "resource_id": "string? // 资源标识", "details": "object // JSON:前后值 / IP / UA 等", "result": "enum(success|failure|partial)", "ip_address": "string // 来源 IP", "user_agent": "string // UA", "created_at": "datetime // 发生时间" } } ``` **已记录事件(安全审计报告 §3)**:登录 / 登出、消息发送、会话创建关闭、管理员操作、配置变更。 **待补事件**:敏感数据查询(P1)、角色变更(P1)、系统配置变更(P1)、异常登录(P1)、API 调用统计(P2)。 **UI 命名(决策 1)**:管理后台侧边栏明确命名为 **「安全审计日志」**,与 A 的「配置变更历史」区分。 --- ### 3.3 C — 自动化动作日志 **定义**:自动化流程调用外部系统时的出入参全量落表,用于排障与审计。 **使用场景(谁 / 何时 / 为什么)**: - **谁**:运维 / 开发(排障);审计(追溯外部调用)。 - **何时**:自动化动作触发外部系统调用(如 `huorong.isolate` 火绒隔离)时。 - **为什么**:外部调用失败 / 耗时异常时,定位是请求问题还是对方系统问题。 **接口 / 落点**: | 项目 | 说明 | |------|------| | 落点 | `auto_action_logs`(模型 `ActionLog`,`backend/app/models/automation.py` 第 249 行) | | 管理后台列表接口 | **暂未暴露**(当前仅落表);如需可视化查询可后续补充 | **数据模型(JSON Schema 风格)**: ```json { "ActionLog": { "session_id": "string? // 关联会话", "action_id": "string? // 自动化动作 ID", "employee_id": "string? // 触发员工", "event": "string // 事件,如 huorong.isolate", "direction": "enum(in|out) // 入/出方向", "system": "string // 外部系统", "request": "object // 请求(脱敏)", "response": "object // 响应(脱敏)", "status": "string // 状态", "latency_ms": "int? // 耗时", "error": "string? // 错误信息" } } ``` --- ### 3.4 D — 运行期结构化日志 **定义**:应用运行期输出的结构化日志(JSON),承载排障信息,含 `request_id` / `user_id` 上下文。 **落点与现状**(日志结构化审计报告 §3): - 落点:**stdout → Docker 文件**;`JSONFormatter` + 中间件注入 `trace_id`(辅助函数 `log_business` / `log_security`)。 - 短期:stdout + `docker logs` + `grep`(Docker 收集到 `/var/log/wecom-it-desk/*.log`)。 - 中长远:Loki + Promtail(中期)/ ELK(长期)。 **管理后台「日志查看」**:管理员手册 §10.2 承诺「按时间、级别筛选日志,支持下载日志文件」,**已落地**:前端 `RuntimeLogs.vue`(4 项筛选 + 下载按钮)+ 后端 `GET /api/admin/runtime-logs`(`download=true` 流式返回)+ 部署 `docker-compose.yml` 挂载 `RUNTIME_LOG_DIR=/app/logs`(详见 sysdesign.md 第六节)。 **D 页面产品规格(决策 4,详见 §5.1)**:筛选维度 = 级别 + 时间;下载格式 = `.txt` / `.log`;权限 = admin。 --- ### 3.5 E — 会话 / 消息记录 **定义**:业务主数据(非独立日志子系统),记录员工与坐席的会话及消息。 **落点**:`conversations` / `messages` 表。 **与日志的关系**:PRD 阶段四「会话日志格式规范」是对其**记录格式**的约定,为后续审计与分析打基础(属于 B 审计的数据来源之一,也支撑阶段四的数据统计看板)。 --- ## 4. 关键辨析:A(记配置值 diff) vs B(记安全行为事件) | 维度 | A 配置变更历史 | B 安全审计日志 | |------|---------------|----------------| | 记录对象 | 配置项**值 diff**(old_value → new_value) | 安全**行为事件**(action + resource + result) | | 触发点 | `PUT /api/admin/configs/{key}` | 登录/登出/消息/会话/管理员操作/配置变更等 | | 字段重心 | `config_key` / `old_value` / `new_value` / `changed_by` / `changed_at` | `action` / `resource` / `result` / `ip_address` / `user_agent` / `details` | | 核心问题 | 「配置被改成什么了?」 | 「谁做了什么安全动作?结果如何?」 | | 主要读者 | 管理员(查配置变更) | 管理员 / 审计员(审计追溯) | | 列表接口 | `GET /api/admin/system-logs`(参数待补) | `GET /admin/audit-logs`(多过滤参数) | | 权限 | admin | `audit_log:read:all`(admin / auditor) | | 双写关系 | 同一配置变更动作**同时写 A 与 B**(`config_change` 事件) | 同上 | > **结论**:A 与 B 是「同一动作的两个视角」——A 记「值」,B 记「事」。决策 2 明确**维持双写、不收敛**。 --- ## 5. 5 项决策的产品化表述 + 验收标准 > 决策来源:用户(宋献)2026-07-09 拍板。本文档严格承袭,未自行增减范围。 | # | 决策 | 优先级 | 产品化表述 | 验收标准 | |---|------|--------|-----------|----------| | **1** | 命名与归并 | P1 | 管理后台侧边栏「系统日志」明确区分命名:**配置变更历史(A)** vs **安全审计日志(B)** | ① 侧边栏出现两个独立、命名清晰的入口;② 入口标题与本文档 A/B 命名一致,无「系统日志」歧义统称 | | **2** | 双写边界 | P0 | 配置变更维持 **A+B 双写**,不收敛 | ① `PUT /api/admin/configs/{key}` 同时写 `config_change_logs` 与 `audit_logs` 的 `config_change` 事件;② 不在任一侧删除或合并 | | **3** | 筛选能力 | P1 | A 页面补充「配置键 / 操作人 / 时间」筛选 | ① 前端 A 页增加三类筛选控件;② 后端 `GET /api/admin/system-logs` 支持 `config_key` / `changed_by` / `changed_from~changed_to` 过滤参数;③ 筛选结果与分页正确联动 | | **4** | 运行期日志查看 | P0 | 落地 D「按级别 / 时间筛选 + 下载」页面与后端接口 | 见 §5.1 D 页面产品规格表,全部满足 | | **5** | 文档闭环 | — | 补《系统日志/审计日志 产品+设计文档》,并入 PRD v1.2 与架构 v1.3,列入项目任务 | ① 本文档已建立;② PRD / 架构已增补日志体系小节;③ 状态看板登记 #101–#104 | ### 5.1 决策 4 — D 运行期日志查看页 产品规格 | 规格项 | 定义 | |--------|------| | 页面名称 | 运行期日志查看(管理后台侧边栏入口) | | 权限 | **admin**(仅管理员可访问) | | 数据来源 | 后端聚合 `RUNTIME_LOG_DIR`(容器内 `/app/logs`)下 `*.log`(JSONFormatter 逐行 JSON 输出)。落地方案:应用层 `RotatingFileHandler` 写入 + docker-compose 宿主机目录 bind mount(`/var/log/wecom-it-desk:/app/logs`);stdout 仍由 docker `json-file` 捕获供 `docker logs` 兜底。中长远 = Loki / ELK | | 筛选维度 | **级别**(DEBUG / INFO / WARNING / ERROR / CRITICAL)+ **时间**(from / to) | | 关键字检索 | 支持按文本关键字检索(如 trace_id / 员工 ID) | | 下载 | 支持下载筛选后的日志,格式 **`.txt` / `.log`** | | 分页 / 加载 | 支持分页(默认 100/页,可切 20/50/100) | | 后端接口(已落地) | `GET /api/admin/runtime-logs`(参数:`level` / `from` / `to` / `keyword` / `page` / `page_size` / `download`,`download=true` 时以 `text/plain` 流式返回命中行,文件名 `runtime-logs-{ts}.log`) | | 验收标准 | ① admin 可筛选级别 + 时间查看日志;② 可下载 `.txt` / `.log`;③ 非 admin 无权限;④ 非 admin 调用接口返回 403 | --- ## 6. 待确认 / 遗留问题 1. **D 页后端聚合实现方案**:**短期已定稿**(应用层 JSON 文件日志 + docker-compose 宿主机目录 bind mount,详见 sysdesign.md 第六节),**中长期** 是否切换 Loki / ELK 仍待架构师(高见远)按数据量与检索需求评估后决策。 2. **B 待补事件排期**:敏感数据查询 / 角色变更 / 系统配置变更 / 异常登录(P1),API 调用统计(P2)——需纳入迭代计划。 3. **C 是否需管理后台可视化查询接口**:当前仅落表,无列表页;若审计 / 排障需要,后续补充 `GET /admin/auto-action-logs`(权限待定)。 4. **A 页面权限命名**:建议明确为 `config_log:read`(当前沿用 `/api/admin` 鉴权);可与 B 的 `audit_log:read:all` 一并纳入 RBAC 梳理。 5. **E 与 B 的衔接**:阶段四「会话日志格式规范」落地后,需确保会话相关行为在 B 中有对应审计事件。 --- ## 变更记录 | 版本 | 日期 | 变更说明 | |------|------|----------| | v1.0 | 2026-07-09 | 初稿(许清楚) | | v1.2.1 | 2026-08-04 | §5.1 D 接口与「待开发」措辞修正为已落地状态;下载接口统一为 query 参数 `download=true`(不再使用 `/runtime-logs/download` 子路径);§6 D 页后端聚合实现方案标注短期已定稿(应用层 JSON 文件 + bind mount) |