Files
wecom_it_smart_desk/docs/04-功能设计/系统日志与审计日志-产品与设计.md
T

259 lines
15 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 系统日志与审计日志 — 产品 + 设计文档
> **版本**v1.0 **日期**2026-07-09 | **作者**:许清楚(产品经理)| **关联文档**[PRD v1.2](../../02-产品需求/02-产品需求文档PRD-v1.2-20260704.md) [架构设计 v1.3](../../03-技术架构/00-系统架构设计文档-v1.3.md) / [安全审计报告-日志结构化](../../08-安全审计/审计报告-安全审计/健康检查+错误码+日志结构化.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 的「日志查看」在管理员手册中已承诺但**后端接口未落地**。本文档目标:
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 承诺「按时间、级别筛选日志,支持下载日志文件」,**目前无后端接口,未落地**(见决策 4)。
**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**(仅管理员可访问) |
| 数据来源 | 后端聚合 Docker 容器 stdout 日志(JSONFormatter 输出);短期 = `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`+ 下载接口 `GET /api/admin/runtime-logs/download` |
| 验收标准 | ① admin 可筛选级别 + 时间查看日志;② 可下载 `.txt` / `.log`;③ 非 admin 无权限;④ 非 admin 调用接口返回 403 |
---
## 6. 待确认 / 遗留问题
1. **D 页后端聚合实现方案**stdout 文件读取 vs Loki 接入的取舍,需架构师(高见远)在阶段细化时定稿(短期先走 `docker logs` 聚合)。
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 中有对应审计事件。