# 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=4,placeholder=`{}`) #### 4)time_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()(规则/字典/屏蔽变更后触发)] ``` --- ## 7. 中优先级待办(已立项,未完成) 本节用于记录当前版本可用但尚未产品化完善的中优先级项,作为后续迭代输入。 ### 7.1 Outbox 可观测性增强 当前状态: - 已支持 `alert_outbox` 入队、重试、死信、手动重试; - 已有基础列表查询接口和前端入口。 待完善内容: - 增加 outbox 指标接口或埋点: - `pending_count` - `retrying_count` - `dead_count` - `dispatch_success_rate` - `dispatch_latency_p95` - 增加失败原因聚合视图(按 `last_error` 分类统计)。 - 增加任务生命周期字段(首次入队时间、最后发送时间)用于问题排查。 建议落地文件: - 后端:`internal/logic/controllers/outbox.go`、`internal/ingest/alert_outbox.go` - 前端:`front/src/views/ops/pages/log-mgmt/entries/index.vue` ### 7.2 分发状态模型统一(替代 bool) 当前状态: - `logs_events` 已新增 `dispatch_status`,并在 outbox 流程中维护状态。 - 历史字段 `alert_sent` 仍保留,用于兼容旧页面展示。 待完善内容: - 明确状态枚举为:`not_applicable/pending/retrying/sent/dead`。 - 前后端统一以 `dispatch_status` 作为主状态字段,`alert_sent` 逐步降级为派生字段或移除。 - 页面文案由“已告警”升级为“分发状态”主展示,避免语义歧义。 建议落地文件: - 后端:`internal/models/log_event.go`、`internal/logic/controllers/crud.go` - 前端:`front/src/api/ops/logs.ts`、`front/src/views/ops/pages/log-mgmt/entries/index.vue` ### 7.3 关键路径测试补齐 当前状态: - 已有基础单测覆盖核心函数。 待完善内容: - 增加资源事件安全链路测试: - 验签失败/成功 - 超时事件拒绝 - 幂等事件重复提交 - 增加 outbox 重试链路测试: - 发送成功更新状态 - 重试次数递增 - 超过阈值转 `dead` - 增加资源冲突优先级测试: - `server > collector > device` 建议落地文件: - `internal/logic/controllers/resource_event_test.go` - `internal/ingest/alert_outbox_test.go` - `internal/ingest/resource_resolver_test.go` --- ## 8. 后续产品化规划(Phase 3) 本节对应“可运维与产品化”阶段,优先级低于中优先级修复项,但会显著提升系统可管理性。 ### 8.1 规则发布流(draft / publish / rollback) 目标: - 规则配置与生效状态解耦,降低误操作风险。 范围: - 引入规则草稿态与发布态; - 支持发布记录、回滚到历史版本; - 变更需记录操作人、时间、变更说明。 接口建议: - `POST /Logs/v1/rule-sets/:id/publish` - `POST /Logs/v1/rule-sets/:id/rollback` - `GET /Logs/v1/rule-sets/:id/history` ### 8.2 规则仿真/回放能力 目标: - 上线前可验证规则命中结果,减少误报漏报。 范围: - 输入样本报文(syslog/trap)执行仿真; - 返回命中链路(命中/未命中原因); - 支持历史事件回放。 接口建议: - `POST /Logs/v1/rule-sets/:id/simulate` - `POST /Logs/v1/rule-sets/:id/replay` ### 8.3 指标与审计面板 目标: - 建立“采集-匹配-分发”全链路可观测性。 范围: - 采集侧:接收速率、解析失败率; - 匹配侧:命中率、规则耗时; - 分发侧:成功率、重试率、死信量; - 安全侧:验签失败次数、重放拦截次数。 前端建议: - 在日志管理模块增加“运行指标”页签; - 对死信和验签失败提供快捷定位入口。 --- ## 9. 未完成项执行顺序(建议) 为降低风险,建议按以下顺序推进: 1. **中优先级先完成** - outbox 指标与失败聚合 - `dispatch_status` 主状态化 - 关键路径测试补齐 2. **再做产品化** - 规则发布流 - 规则仿真/回放 - 指标与审计面板 验收建议: - 每项功能完成后执行“单项验证 + 回归验证”,最后统一做端到端联调。