Files
logs/doc/log-mgmt-frontend-design.md
2026-03-30 18:03:40 +08:00

368 lines
11 KiB
Markdown
Raw Permalink 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.
# Ops Logs 前端页面设计文档Log Mgmt
## 1. 背景与目标
`Logs` 服务负责采集并归一化设备侧日志Syslog / SNMP Trap并提供规则与字典等配置能力。前端需要在统一的后台界面中完成
1. 日志查询(查看归一化后的日志事件及详情)
2. Syslog 规则配置
3. Trap 规则配置
4. Trap 字典配置
5. Trap 屏蔽/抑制规则配置
本设计以当前代码库的后端模型与前端实现为准:后端路由在 `internal/routers/register.go`,前端页面在 `front/src/views/ops/pages/log-mgmt/**/index.vue`
---
## 2. 范围(页面数量与路由)
本模块共 5 个页面,对应后端 5 组资源(列表+CRUD 或列表+详情抽屉)。
| 页面 | 菜单/路由路径 | 前端组件 |
|---|---|---|
| 日志查询 | `/log-mgmt/entries` | `front/src/views/ops/pages/log-mgmt/entries/index.vue` |
| Syslog 匹配规则 | `/log-mgmt/syslog-rules` | `front/src/views/ops/pages/log-mgmt/syslog-rules/index.vue` |
| SNMP Trap 匹配规则 | `/log-mgmt/trap-rules` | `front/src/views/ops/pages/log-mgmt/trap-rules/index.vue` |
| Trap 字典 | `/log-mgmt/trap-dictionary` | `front/src/views/ops/pages/log-mgmt/trap-dictionary/index.vue` |
| Trap 屏蔽/抑制 | `/log-mgmt/trap-suppressions` | `front/src/views/ops/pages/log-mgmt/trap-suppressions/index.vue` |
路由与菜单配置参考:
- `front/src/router/local-menu-flat.ts` / `front/src/router/local-menu-items.ts`
- `front/src/views/ops/pages/system-settings/system-logs/index.vue`(页面入口按钮)
- `front/src/views/ops/pages/monitor/log/index.vue`(嵌入 `LogMgmtEntries`
---
## 3. 数据对象与接口映射
后端认证API 路由组启用 `middleware.JwtAuth(true)`
前端请求的 API Base`front/src/api/ops/logs.ts` 中为 `/Logs/v1`
### 3.1 日志事件entries
- 接口:`GET /Logs/v1/entries`
- 返回结构(前端类型):`LogEntriesResult``total``page``page_size``items`
- 日志事件字段(前端类型 `LogEvent`
- `id`
- `created_at`
- `source_kind``syslog` / `snmp_trap`
- `remote_addr`
- `raw_payload`
- `normalized_summary`
- `normalized_detail`
- `device_name`
- `severity_code`
- `trap_oid`
- `alert_sent`
后端实现:`internal/models/log_event.go``internal/logic/controllers/crud.go``ListLogEvents`)。
### 3.2 Syslog 规则syslog-rules
- 接口:
- `GET /Logs/v1/syslog-rules`
- `POST /Logs/v1/syslog-rules`
- `PUT /Logs/v1/syslog-rules/:id`
- `DELETE /Logs/v1/syslog-rules/:id`
- 规则字段(前端类型 `SyslogRule` / 后端 `SyslogRule`
- `id``created_at``updated_at`
- `name`
- `enabled`
- `priority`
- `device_name_contains`
- `keyword_regex`
- `alert_name`
- `severity_code`
- `policy_id`
后端实现:`internal/models/syslog_rule.go``internal/logic/controllers/crud.go`
### 3.3 Trap 规则trap-rules
- 接口:
- `GET /Logs/v1/trap-rules`
- `POST /Logs/v1/trap-rules`
- `PUT /Logs/v1/trap-rules/:id`
- `DELETE /Logs/v1/trap-rules/:id`
- 规则字段(前端类型 `TrapRule` / 后端 `TrapRule`
- `name`
- `enabled`
- `priority`
- `oid_prefix`
- `varbind_match_regex`
- `alert_name`
- `severity_code`
- `policy_id`
后端实现:`internal/models/trap_rule.go``internal/logic/controllers/crud.go`
### 3.4 Trap 字典trap-dictionary
- 接口:
- `GET /Logs/v1/trap-dictionary`
- `POST /Logs/v1/trap-dictionary`
- `PUT /Logs/v1/trap-dictionary/:id`
- `DELETE /Logs/v1/trap-dictionary/:id`
- 字典条目字段(前端类型 `TrapDictionaryEntry` / 后端 `TrapDictionaryEntry`
- `oid_prefix`后端约束uniqueIndex
- `title`
- `description`
- `severity_code`
- `recovery_message`
- `enabled`
后端实现:`internal/models/trap_dictionary.go``internal/logic/controllers/crud.go`
### 3.5 Trap 屏蔽/抑制trap-suppressions
- 接口:
- `GET /Logs/v1/trap-suppressions`
- `POST /Logs/v1/trap-suppressions`
- `PUT /Logs/v1/trap-suppressions/:id`
- `DELETE /Logs/v1/trap-suppressions/:id`
- 屏蔽规则字段(前端类型 `TrapShield` / 后端 `TrapShield`
- `name`
- `enabled`
- `source_ip_cidr`
- `oid_prefix`
- `interface_hint`
- `time_windows_json`JSON 字符串)
后端实现:`internal/models/trap_shield.go``internal/logic/controllers/crud.go`
---
## 4. 页面设计详情(逐页)
### 4.1 日志查询页(`/log-mgmt/entries`
目标:以“可筛选的列表 + 详情抽屉”方式查看归一化日志事件。
#### 1顶部筛选区
- 使用 `search-table` 组件
- 筛选项:`source_kind`(下拉)
- `全部`value=''
- `Syslog`value='syslog'
- `SNMP Trap`value='snmp_trap'
筛选触发:`@search` 调用 `handleSearch`,重置则 `@reset` 调用 `handleReset`
#### 2列表表格列Columns
表格由 `columns` 定义,主要列:
- `ID`
- `来源``source_kind`,通过 `sourceKindLabel()` 显示(`syslog`->`Syslog``snmp_trap`->`SNMP Trap`
- `时间``created_at`
- `来源地址``remote_addr`
- `设备``device_name`
- `级别``severity_code`
- `OID``trap_oid`
- `原始报文``raw_payload`
- 使用 slot `raw_payload`:省略显示,保留 `tooltip`
- `已告警``alert_sent`
- 使用 slot `alert_sent``a-tag`(已转发/否)
- `操作`slot `operations`
- `详情`:打开右侧抽屉
#### 3详情抽屉a-drawer
- 打开逻辑:点击表格行操作中的 `详情`,调用 `openDetail(record)`
- 抽屉展示:`a-descriptions`1 列bordered
- 展示字段:
- 来源类型(`source_kind`
- 采集时间(`created_at`
- 来源地址(`remote_addr`,空则 `-`
- 设备名(`device_name`
- 严重级别(`severity_code`
- Trap OID`trap_oid`
- 已转发告警(`alert_sent`
- 摘要(`normalized_summary`
- 详情(`normalized_detail``pre-block` 预格式化展示)
- 原始报文(`raw_payload``pre-block` 预格式化展示)
#### 4分页策略
- 分页参数由前端 `pagination.current/pageSize` 控制,并随筛选条件一起请求后端:
- 调用 `fetchLogEntries({ page, page_size, source_kind })`
### 4.2 Syslog 规则页(`/log-mgmt/syslog-rules`
目标:规则的“列表 + 新建/编辑弹窗 + 删除确认”。
#### 1通用列表与本地过滤
- 使用 `search-table`,并在前端进行“关键词本地过滤”,过滤字段:
- `name`
- `alert_name`
- `keyword_regex`
- 搜索输入字段:
- `keyword`label`关键词`placeholder`规则名 / 告警名`
说明:该页(以及 trap-*、dictionary、suppressions 三类列表页)采用“先拉取全量 -> 本地过滤 -> 切片分页”的方式。
#### 2表格列
- `ID`
- `名称``name`
- `优先级``priority`
- `启用``enabled`slot `enabled`tag启用/禁用)
- `设备名包含``device_name_contains`
- `关键字正则``keyword_regex`
- `告警名``alert_name`
- `级别``severity_code`
- `策略ID``policy_id`
- `操作`:编辑/删除
#### 3新建/编辑弹窗a-modal
- 弹窗标题:
- 新建:`新建 Syslog 规则`
- 编辑:`编辑规则 #${editingId}`
- 表单 `a-form`(布局 `vertical`
- 表单字段:
- `name``a-input`(必填)
- `enabled``a-switch`
- `priority``a-input-number`
- `device_name_contains``a-input`
- `keyword_regex``a-input`
- `alert_name``a-input`
- `severity_code``a-input`
- `policy_id``a-input-number`min=0
提交逻辑:
- 编辑:`updateSyslogRule(editingId, { ...formData })`
- 新建:`createSyslogRule({ ...formData })`
- 成功后关闭弹窗并刷新列表 `fetchList()`
#### 4删除确认
- `Modal.confirm` 二次确认
- 删除接口:`deleteSyslogRule(id)`
### 4.3 Trap 规则页(`/log-mgmt/trap-rules`
目标TrapRule 的列表+弹窗 CRUD与 Syslog 规则页同构。
#### 1本地过滤关键词
- 字段:`keyword`
- 匹配来源:
- `name`
- `oid_prefix`
- `alert_name`
#### 2表格列
- `ID``名称``优先级``启用`
- `OID 前缀``oid_prefix`
- `Varbind 正则``varbind_match_regex`
- `告警名``alert_name`
- `级别``severity_code`
- `策略ID``policy_id`
- 操作:编辑/删除
#### 3弹窗表单字段
- `name`(必填)
- `enabled`
- `priority`
- `oid_prefix`
- `varbind_match_regex`
- `alert_name`
- `severity_code`
- `policy_id`min=0
### 4.4 Trap 字典页(`/log-mgmt/trap-dictionary`
目标TrapDictionaryEntry 的列表+弹窗 CRUD。
#### 1本地过滤关键词
- 匹配字段:
- `oid_prefix`
- `title`
- `description`
#### 2表格列
- `ID`
- `OID 前缀``oid_prefix`
- `标题``title`
- `级别``severity_code`
- `启用``enabled`
- `描述``description`
- 操作:编辑/删除
#### 3弹窗表单字段
- `oid_prefix`(必填,建议提示“唯一前缀”)
- `title`(必填)
- `description``a-textarea`rows=3
- `severity_code`
- `enabled`
- `recovery_message``a-textarea`rows=2
### 4.5 Trap 屏蔽/抑制页(`/log-mgmt/trap-suppressions`
目标TrapShield 的列表+弹窗 CRUD并对 `time_windows_json` 做前端校验。
#### 1本地过滤关键词
- 匹配字段:
- `name`
- `oid_prefix`
- `source_ip_cidr`
#### 2表格列
- `ID`
- `名称``name`
- `启用``enabled`
- `源 IP/CIDR``source_ip_cidr`
- `OID 前缀``oid_prefix`
- `接口提示``interface_hint`
- 操作:编辑/删除
#### 3弹窗表单字段
- `name`(必填)
- `enabled`
- `source_ip_cidr`
- `oid_prefix`
- `interface_hint`
- `time_windows_json``a-textarea`rows=4placeholder=`{}`
#### 4time_windows_json JSON 校验
-`time_windows_json` 非空时:
-`trim` 后尝试 `JSON.parse(tw)`
- 校验失败:`Message.warning('时间窗 JSON 格式无效')` 并阻止提交
---
## 5. 页面交互一致性要求(实现要点)
为了保证各列表页体验一致,本模块约定:
1. 列表页使用统一的 `search-table` 布局(顶部搜索、表格、分页、刷新)
2. 规则类/字典/屏蔽页采用“拉取全量 -> 本地过滤 -> 切片分页”的方式
3. 创建/编辑统一使用 `a-modal`,提交按钮触发 `formRef.validate()`
4. 删除统一使用 `Modal.confirm`,成功后刷新列表并给出 `Message.success`
5. `trap-suppressions``time_windows_json` 进行 JSON 字符串合法性校验
---
## 6. 数据流(简图)
```mermaid
flowchart LR
UI[前端页面search-table + 表格/弹窗/抽屉)] --> API[front/src/api/ops/logs.ts]
API --> BE[后端路由 internal/routers/register.go]
BE --> DB[(Postgres)]
BE --> Refresh[ingest.Global.Refresh()(规则/字典/屏蔽变更后触发)]
```