From a24f9d29db24c987447e45abfef348ec77c4e2c2 Mon Sep 17 00:00:00 2001 From: qian Date: Sun, 2 Aug 2026 00:56:03 +0800 Subject: [PATCH] =?UTF-8?q?feat(log)=EF=BC=9A=E6=B7=BB=E5=8A=A0=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E7=A1=AC=E5=88=A0=E9=99=A4=E6=8C=89=E9=92=AE=EF=BC=8C?= =?UTF-8?q?=E9=98=B2=E6=AD=A2=E9=A2=91=E7=B9=81=E9=94=99=E8=AF=AF=E5=BD=B1?= =?UTF-8?q?=E5=93=8D=E6=95=B0=E6=8D=AE=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- api/admin/admin.go | 2 + api/admin/v1/error_log.go | 10 +++++ api/admin/v1/monitor.go | 16 ++++++-- .../controller/admin/admin_v1_error_log.go | 3 ++ internal/controller/admin/admin_v1_monitor.go | 3 ++ internal/logic/admin/error_log.go | 15 +++++++ internal/logic/monitor/alert_event.go | 40 +++++++++++++++++++ internal/logic/monitor/monitor.go | 8 ++++ internal/middleware/rbac.go | 2 + internal/service/admin.go | 5 +++ internal/service/monitor.go | 1 + .../src/views/monitor/AlertEventsPage.vue | 30 +++++++++++++- web/admin/src/views/monitor/ErrorLogsPage.vue | 28 ++++++++++++- 13 files changed, 157 insertions(+), 6 deletions(-) diff --git a/api/admin/admin.go b/api/admin/admin.go index 3a4969c..620ad11 100644 --- a/api/admin/admin.go +++ b/api/admin/admin.go @@ -104,6 +104,7 @@ type IAdminV1 interface { ErrorLogResolve(ctx context.Context, req *v1.ErrorLogResolveReq) (res *v1.ErrorLogResolveRes, err error) ErrorLogBatchResolve(ctx context.Context, req *v1.ErrorLogBatchResolveReq) (res *v1.ErrorLogBatchResolveRes, err error) ErrorLogStats(ctx context.Context, req *v1.ErrorLogStatsReq) (res *v1.ErrorLogStatsRes, err error) + ErrorLogClear(ctx context.Context, req *v1.ErrorLogClearReq) (res *v1.ErrorLogClearRes, err error) FeedbackListAll(ctx context.Context, req *v1.FeedbackListAllReq) (res *v1.FeedbackListAllRes, err error) FeedbackReply(ctx context.Context, req *v1.FeedbackReplyReq) (res *v1.FeedbackReplyRes, err error) FeedbackUpdateStatus(ctx context.Context, req *v1.FeedbackUpdateStatusReq) (res *v1.FeedbackUpdateStatusRes, err error) @@ -164,6 +165,7 @@ type IAdminV1 interface { AlertEventList(ctx context.Context, req *v1.AlertEventListReq) (res *v1.AlertEventListRes, err error) AlertEventAcknowledge(ctx context.Context, req *v1.AlertEventAcknowledgeReq) (res *v1.AlertEventAcknowledgeRes, err error) AlertEventResolve(ctx context.Context, req *v1.AlertEventResolveReq) (res *v1.AlertEventResolveRes, err error) + AlertEventClear(ctx context.Context, req *v1.AlertEventClearReq) (res *v1.AlertEventClearRes, err error) TemplateList(ctx context.Context, req *v1.TemplateListReq) (res *v1.TemplateListRes, err error) TemplateGet(ctx context.Context, req *v1.TemplateGetReq) (res *v1.TemplateGetRes, err error) TemplateUpdate(ctx context.Context, req *v1.TemplateUpdateReq) (res *v1.TemplateUpdateRes, err error) diff --git a/api/admin/v1/error_log.go b/api/admin/v1/error_log.go index 574e72f..d88c9e9 100644 --- a/api/admin/v1/error_log.go +++ b/api/admin/v1/error_log.go @@ -61,3 +61,13 @@ type ErrorLogStatsReq struct { type ErrorLogStatsRes struct { Data map[string]any `json:"data"` } + +// ErrorLogClearReq 清空全部错误日志(硬删除,用于错误大量堆积时快速释放数据库空间) +type ErrorLogClearReq struct { + g.Meta `path:"/error-logs/clear" method:"delete" mime:"json" tags:"管理后台-系统错误" summary:"清空错误日志(硬删除全部)"` +} + +// ErrorLogClearRes 清空错误日志响应 +type ErrorLogClearRes struct { + Deleted int64 `json:"deleted" dc:"删除的记录数"` +} diff --git a/api/admin/v1/monitor.go b/api/admin/v1/monitor.go index 534a0e8..9d9688e 100644 --- a/api/admin/v1/monitor.go +++ b/api/admin/v1/monitor.go @@ -24,9 +24,9 @@ type MonitorTrafficRes struct { type MonitorTrafficFlowReq struct { g.Meta `path:"/monitor/traffic-flow" method:"get" mime:"json" tags:"管理后台-监控" summary:"流量流向桑基图"` - StartDate string `json:"start_date" in:"query"` // YYYY-MM-DD,缺省=近30天起点 - EndDate string `json:"end_date" in:"query"` // YYYY-MM-DD,缺省=今天 - Metric string `json:"metric" in:"query" d:"cost"` // cost|tokens|requests,桑基边权重指标 + StartDate string `json:"start_date" in:"query"` // YYYY-MM-DD,缺省=近30天起点 + EndDate string `json:"end_date" in:"query"` // YYYY-MM-DD,缺省=今天 + Metric string `json:"metric" in:"query" d:"cost"` // cost|tokens|requests,桑基边权重指标 } type MonitorTrafficFlowRes struct { @@ -242,3 +242,13 @@ type AlertEventResolveReq struct { } type AlertEventResolveRes struct{} + +// AlertEventClearReq 清空全部告警记录(硬删除,同时清理 Redis 中的触发状态) +type AlertEventClearReq struct { + g.Meta `path:"/alert/events/clear" method:"delete" mime:"json" tags:"管理后台-告警" summary:"清空告警记录(硬删除全部)"` +} + +// AlertEventClearRes 清空告警记录响应 +type AlertEventClearRes struct { + Deleted int64 `json:"deleted" dc:"删除的记录数"` +} diff --git a/internal/controller/admin/admin_v1_error_log.go b/internal/controller/admin/admin_v1_error_log.go index 0d3aebc..8b21c9e 100644 --- a/internal/controller/admin/admin_v1_error_log.go +++ b/internal/controller/admin/admin_v1_error_log.go @@ -22,3 +22,6 @@ func (c *ControllerV1) ErrorLogBatchResolve(ctx context.Context, req *v1.ErrorLo func (c *ControllerV1) ErrorLogStats(ctx context.Context, req *v1.ErrorLogStatsReq) (res *v1.ErrorLogStatsRes, err error) { return service.Admin().ErrorLogStats(ctx, req) } +func (c *ControllerV1) ErrorLogClear(ctx context.Context, req *v1.ErrorLogClearReq) (res *v1.ErrorLogClearRes, err error) { + return service.Admin().ErrorLogClear(ctx, req) +} diff --git a/internal/controller/admin/admin_v1_monitor.go b/internal/controller/admin/admin_v1_monitor.go index 1f9564b..ad72fbe 100644 --- a/internal/controller/admin/admin_v1_monitor.go +++ b/internal/controller/admin/admin_v1_monitor.go @@ -67,3 +67,6 @@ func (c *ControllerV1) MonitorModelPerformance(ctx context.Context, req *v1.Moni func (c *ControllerV1) MonitorDispatch(ctx context.Context, req *v1.MonitorDispatchReq) (res *v1.MonitorDispatchRes, err error) { return service.Monitor().Dispatch(ctx, req) } +func (c *ControllerV1) AlertEventClear(ctx context.Context, req *v1.AlertEventClearReq) (res *v1.AlertEventClearRes, err error) { + return service.Monitor().AlertEventClear(ctx, req) +} diff --git a/internal/logic/admin/error_log.go b/internal/logic/admin/error_log.go index d5c5341..537e222 100644 --- a/internal/logic/admin/error_log.go +++ b/internal/logic/admin/error_log.go @@ -129,6 +129,21 @@ func (s *sAdmin) ErrorLogBatchResolve(ctx context.Context, req *v1.ErrorLogBatch return &v1.ErrorLogBatchResolveRes{}, nil } +// ErrorLogClear 硬删除全部错误日志。 +// 系统报错大量堆积时用于快速释放数据库空间:用 TRUNCATE 而非逐行 DELETE, +// 秒级清空并立即归还磁盘空间(DELETE 需等 VACUUM 回收)。TRUNCATE 不返回行数, +// 故先取删除前条数作为反馈。表无数据库级外键,TRUNCATE 安全。 +func (s *sAdmin) ErrorLogClear(ctx context.Context, _ *v1.ErrorLogClearReq) (*v1.ErrorLogClearRes, error) { + count, err := dao.SysErrorLogs.Ctx(ctx).Count() + if err != nil { + return nil, err + } + if _, err := g.DB().Ctx(ctx).Exec(ctx, "TRUNCATE TABLE sys_error_logs RESTART IDENTITY"); err != nil { + return nil, err + } + return &v1.ErrorLogClearRes{Deleted: int64(count)}, nil +} + // ErrorLogStats returns error log statistics. func (s *sAdmin) ErrorLogStats(ctx context.Context, _ *v1.ErrorLogStatsReq) (*v1.ErrorLogStatsRes, error) { // Total unresolved diff --git a/internal/logic/monitor/alert_event.go b/internal/logic/monitor/alert_event.go index b93f5f8..dada118 100644 --- a/internal/logic/monitor/alert_event.go +++ b/internal/logic/monitor/alert_event.go @@ -200,6 +200,46 @@ func GetAlertStats(ctx context.Context) (map[string]any, error) { }, nil } +// ClearAlertEvents 硬删除全部告警事件,并清理关联的 Redis 触发状态。 +// 告警事件表持续追加,异常频发时会迅速膨胀拖累数据库;TRUNCATE 秒级清空并立即归还 +// 磁盘空间(DELETE 需等 VACUUM 回收)。表无数据库级外键,TRUNCATE 安全。 +func ClearAlertEvents(ctx context.Context) (int64, error) { + count, err := dao.OpsAlertEvents.Ctx(ctx).Count() + if err != nil { + return 0, err + } + if _, err := g.DB().Ctx(ctx).Exec(ctx, "TRUNCATE TABLE ops_alert_events RESTART IDENTITY"); err != nil { + return 0, err + } + if err := clearAlertFiringState(ctx); err != nil { + g.Log().Warningf(ctx, "clear alert events: reset firing state: %v", err) + } + return int64(count), nil +} + +// clearAlertFiringState 清理 Redis 中所有告警规则的触发状态(ops:alert:firing:{ruleID})。 +// 事件表清空后,若引擎仍持有旧 eventID 的 firing 状态,会持续尝试 auto-resolve 一个 +// 不存在的记录(产生 404 告警日志),且同一规则即便继续越界也不再生成新事件。 +// 触发状态键按 rule_id 命名,遍历规则表逐个 DEL 即可;已删除规则残留的键无引擎读取、1h 自愈。 +func clearAlertFiringState(ctx context.Context) error { + redis := g.Redis() + var ruleIDs []struct { + Id int64 `json:"id"` + } + if err := dao.OpsAlertRules.Ctx(ctx).Fields("id").Scan(&ruleIDs); err != nil { + return err + } + for _, r := range ruleIDs { + if r.Id <= 0 { + continue + } + if _, err := redis.Do(ctx, "DEL", fmt.Sprintf("ops:alert:firing:%d", r.Id)); err != nil { + g.Log().Warningf(ctx, "clear alert firing state for rule %d: %v", r.Id, err) + } + } + return nil +} + // SendTestAlert sends a test notification for a given rule. func SendTestAlert(ctx context.Context, ruleID int64) error { rule, err := GetAlertRule(ctx, ruleID) diff --git a/internal/logic/monitor/monitor.go b/internal/logic/monitor/monitor.go index 56275d3..36d09c4 100644 --- a/internal/logic/monitor/monitor.go +++ b/internal/logic/monitor/monitor.go @@ -328,3 +328,11 @@ func (s *sMonitor) ResolveAlert(ctx context.Context, req *v1.AlertEventResolveRe } return nil, nil } + +func (s *sMonitor) AlertEventClear(ctx context.Context, _ *v1.AlertEventClearReq) (*v1.AlertEventClearRes, error) { + deleted, err := ClearAlertEvents(ctx) + if err != nil { + return nil, err + } + return &v1.AlertEventClearRes{Deleted: deleted}, nil +} diff --git a/internal/middleware/rbac.go b/internal/middleware/rbac.go index 86ef52d..8ee0fdc 100644 --- a/internal/middleware/rbac.go +++ b/internal/middleware/rbac.go @@ -216,10 +216,12 @@ var adminPermissionRules = []permissionRule{ {method: "POST", prefix: "/api/admin/alert/rules/", suffix: "/test", perm: "monitor:edit"}, {method: "GET", path: "/api/admin/alert/events", perm: "monitor:view"}, {method: "PUT", prefix: "/api/admin/alert/events/", perm: "monitor:edit"}, + {method: "DELETE", path: "/api/admin/alert/events/clear", perm: "monitor:edit"}, {method: "GET", path: "/api/admin/error-logs", perm: "monitor:view"}, {method: "GET", prefix: "/api/admin/error-logs/", perm: "monitor:view"}, {method: "PUT", prefix: "/api/admin/error-logs/", perm: "monitor:edit"}, {method: "PUT", path: "/api/admin/error-logs/batch-resolve", perm: "monitor:edit"}, + {method: "DELETE", path: "/api/admin/error-logs/clear", perm: "monitor:edit"}, {method: "GET", path: "/api/admin/error-logs/stats", perm: "monitor:view"}, {method: "GET", path: "/api/admin/cron-jobs", perm: "system:view"}, {method: "POST", prefix: "/api/admin/cron-jobs/", suffix: "/trigger", perm: "system:edit"}, diff --git a/internal/service/admin.go b/internal/service/admin.go index 4ae30d3..8f066d3 100644 --- a/internal/service/admin.go +++ b/internal/service/admin.go @@ -202,6 +202,11 @@ type ( ErrorLogResolve(ctx context.Context, req *v1.ErrorLogResolveReq) (*v1.ErrorLogResolveRes, error) // ErrorLogBatchResolve marks multiple error logs as resolved. ErrorLogBatchResolve(ctx context.Context, req *v1.ErrorLogBatchResolveReq) (*v1.ErrorLogBatchResolveRes, error) + // ErrorLogClear 硬删除全部错误日志。 + // 系统报错大量堆积时用于快速释放数据库空间:用 TRUNCATE 而非逐行 DELETE, + // 秒级清空并立即归还磁盘空间(DELETE 需等 VACUUM 回收)。TRUNCATE 不返回行数, + // 故先取删除前条数作为反馈。表无数据库级外键,TRUNCATE 安全。 + ErrorLogClear(ctx context.Context, _ *v1.ErrorLogClearReq) (*v1.ErrorLogClearRes, error) // ErrorLogStats returns error log statistics. ErrorLogStats(ctx context.Context, _ *v1.ErrorLogStatsReq) (*v1.ErrorLogStatsRes, error) // ListAllFeedbacks 管理后台反馈列表 diff --git a/internal/service/monitor.go b/internal/service/monitor.go index db734ac..939b973 100644 --- a/internal/service/monitor.go +++ b/internal/service/monitor.go @@ -34,6 +34,7 @@ type ( AlertEventList(ctx context.Context, req *v1.AlertEventListReq) (*v1.AlertEventListRes, error) AcknowledgeAlert(ctx context.Context, req *v1.AlertEventAcknowledgeReq) (*v1.AlertEventAcknowledgeRes, error) ResolveAlert(ctx context.Context, req *v1.AlertEventResolveReq) (*v1.AlertEventResolveRes, error) + AlertEventClear(ctx context.Context, _ *v1.AlertEventClearReq) (*v1.AlertEventClearRes, error) } ) diff --git a/web/admin/src/views/monitor/AlertEventsPage.vue b/web/admin/src/views/monitor/AlertEventsPage.vue index 4411469..3ba5d74 100644 --- a/web/admin/src/views/monitor/AlertEventsPage.vue +++ b/web/admin/src/views/monitor/AlertEventsPage.vue @@ -1,10 +1,11 @@