feat: 监控告警体系统一重构 + 自动化任务调度引擎 + 监控大屏拆分

告警中心
- 新增统一告警(alert_unified)、监控告警规则(monitor_alert_rule)、指标目录(alert_metric_catalog)
- 通知策略与消息分发(alert_notify_policy/dispatch/message)、静默规则
- 告警引擎按阈值/SNMP 拆分(alert_engine_monitor/snmp)

监控采集
- SNMP 常量/模板与历史指标(snmp templates/constants、snmp_metrics_history、snmp_collect)
- 中间件监控 Redis 采集与种子(middleware_monitor_redis/seed)
- 站点探测 pkg(siteprobe) + 站点视图(site_view)

自动化任务
- cron 调度器(cronscheduler)、脚本运行器(scriptrunner)、系统任务(systask)及运行记录(cron_job_run、system_task)

审计与凭证
- 审计设置(audit_setting) + 历史清理(auditcleaner)

前端
- 监控页面(host/middleware/site/snmp)拆分为子模块并大屏化
- 告警中心多 Tab(规则/指标目录/通知策略/静默)、任务管理组件重构、Agent CLI Markdown 渲染
- 移除旧脚本卡片/详情/日志组件,统一为 ScriptTable/ScriptCodeEditor/TerminalOutput

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
LoganandClaude committed 2026-07-01 23:44:45 +08:00
1 parent 092d0e4b9e
commit 471353e3d7
190 files changed
+16640 -3484

No files matched your search

+96 -5
View File
@@ -12,11 +12,17 @@ import (
"syscall"
"time"
"ezops/controller"
"ezops/router"
"ezops/config"
"ezops/model"
"ezops/seed"
"ezops/pkg/appdir"
"ezops/pkg/auditcleaner"
"ezops/pkg/database"
snmppkg "ezops/pkg/snmp"
"ezops/pkg/cronscheduler"
"ezops/pkg/systask"
"ezops/pkg/logger"
ezredis "ezops/pkg/redis"
@@ -144,6 +150,8 @@ func main() {
// 初始化种子数据
seed.SeedData(db)
// 中间件监控默认目标(aiops-redis / aiops-mysql)// Logan.Li
controller.SeedDefaultMiddlewareTargets(db)
// 初始化缓存(Redka 内嵌 / Redis 外部)// Logan.Li
cache, err := ezredis.New(ezredis.Config{
@@ -197,19 +205,102 @@ func main() {
c.JSON(http.StatusOK, resp)
})
systask.Init(db)
// 注册路由
router.Register(r, db, log, cfg, cache)
// 用户定时任务调度(Linux 5 段 crontab)// Logan.Li
cronSched := cronscheduler.Start(db, func(jobID uint) {
if _, err := controller.RunCronJobByID(db, jobID); err != nil {
log.Warn("定时任务自动执行失败", zap.Uint("job_id", jobID), zap.Error(err))
}
})
defer cronSched.Stop()
// 定期清理旧的 agent 上报数据(保留 7 天,防止表膨胀影响查询性能)// Logan.Li
go func() {
ticker := time.NewTicker(24 * time.Hour)
defer ticker.Stop()
cleanupSQL := database.CleanupAgentReportsSQL(cfg.Database.Driver)
for range ticker.C {
rows := db.Exec(cleanupSQL).RowsAffected
if rows > 0 {
log.Info("清理过期的 agent 上报数据", zap.Int64("rows", rows))
runAgentCleanup := func() {
start := time.Now()
cleanupSQL := database.CleanupAgentReportsSQL(cfg.Database.Driver)
r := db.Exec(cleanupSQL)
msg := fmt.Sprintf("清理 %d 条记录", r.RowsAffected)
status := "success"
if r.Error != nil {
status = "failed"
msg = r.Error.Error()
log.Warn("Agent 上报清理失败", zap.Error(r.Error))
} else if r.RowsAffected > 0 {
log.Info("清理过期的 agent 上报数据", zap.Int64("rows", r.RowsAffected))
}
systask.Record("agent_report_cleanup", status, msg, time.Since(start))
}
time.Sleep(2 * time.Minute)
runAgentCleanup()
for range ticker.C {
runAgentCleanup()
}
}()
// 定期清理超期 SNMP 采集指标(保留 7 天) // Logan.Li
go func() {
ticker := time.NewTicker(24 * time.Hour)
defer ticker.Stop()
runSNMPCleanup := func() {
start := time.Now()
cleanupSQL := database.CleanupSNMPMetricsSQL(cfg.Database.Driver, snmppkg.MetricsRetentionDays)
r := db.Exec(cleanupSQL)
msg := fmt.Sprintf("清理 %d 条 SNMP 指标(保留 %d 天)", r.RowsAffected, snmppkg.MetricsRetentionDays)
status := "success"
if r.Error != nil {
status = "failed"
msg = r.Error.Error()
log.Warn("SNMP 指标清理失败", zap.Error(r.Error))
} else if r.RowsAffected > 0 {
log.Info("清理过期的 SNMP 指标", zap.Int64("rows", r.RowsAffected))
}
systask.Record("snmp_metrics_cleanup", status, msg, time.Since(start))
}
time.Sleep(3 * time.Minute)
runSNMPCleanup()
for range ticker.C {
runSNMPCleanup()
}
}()
// 每日按审计保留策略清理操作/登录/终端审计日志 // Logan.Li
go func() {
ticker := time.NewTicker(24 * time.Hour)
defer ticker.Stop()
runAuditRetentionCleanup := func() {
start := time.Now()
result, err := auditcleaner.RunFromSettings(db)
if err != nil {
systask.Record("audit_log_cleanup", "failed", err.Error(), time.Since(start))
log.Warn("审计日志定时清理失败", zap.Error(err))
return
}
msg := fmt.Sprintf("清理 %d 条(保留 %d 天)", result.Total, result.RetentionDays)
systask.Record("audit_log_cleanup", "success", msg, time.Since(start))
if result.Total > 0 {
log.Info("审计日志定时清理完成",
zap.Int("retention_days", result.RetentionDays),
zap.Int64("total", result.Total),
)
}
now := time.Now()
summary := result.SummaryJSON()
db.Model(&model.AuditSettings{}).Where("id > 0").Updates(map[string]interface{}{
"last_cleanup_at": now,
"last_cleanup_summary": summary,
})
}
time.Sleep(time.Minute)
runAuditRetentionCleanup()
for range ticker.C {
runAuditRetentionCleanup()
}
}()