docs: update README, API reference, dev-log, project structure with Agent monitoring + quick-alarm + latest fixes

- README.md: React 19, default pwd 123456, Docker Compose deploy, correct module list
- api-reference.md: add Agent monitoring section (report/latest/rules/quick-setup/alerts/tasks/kline)
- dev-log.md: new entry documenting hostname/IP fix, system collector, offline detection, quick alarm
- project-structure.md: add agent/ directory, dev-log.md link, React 19
This commit is contained in:
attacker committed 2026-06-18 16:11:13 +00:00
1 parent c51d0b8b8b
commit 4e3f8cb306
20 files changed
+1315 -1344

No files matched your search

@@ -152,6 +152,82 @@ func (h *AgentTaskHandler) GetTask(c *gin.Context) {
// ===== Agent 告警规则 =====
// QuickSetupRules POST /api/v1/agent/rules/quick-setup
// 一键创建默认告警规则(CPU/内存/磁盘/网络带宽),作用于所有在线主机
func (h *AgentTaskHandler) QuickSetupRules(c *gin.Context) {
var req struct {
Type string `json:"type"` // "ecs" 或留空
}
c.ShouldBindJSON(&req)
// 获取所有在线主机
var onlineHosts []string
h.db.Model(&models.Server{}).
Where("agent_status = ?", "online").
Pluck("hostname", &onlineHosts)
if len(onlineHosts) == 0 {
// 如果没有在线主机,尝试从 agent_reports 中获取最近 3 分钟活跃的主机名
h.db.Model(&models.AgentReport{}).
Where("report_time >= ?", time.Now().Add(-3*time.Minute)).
Distinct("hostname").
Pluck("hostname", &onlineHosts)
}
if len(onlineHosts) == 0 {
c.JSON(400, models.Response{Code: 400, Message: "没有在线的主机,请先安装并启动 Agent"})
return
}
type ruleDef struct {
Name string
Metric string
Operator string
Threshold float64
Duration int
}
defaultRules := []ruleDef{
{Name: "CPU使用率(Warn)", Metric: "cpu", Operator: ">", Threshold: 80},
{Name: "内存使用率(Warn)", Metric: "mem", Operator: ">", Threshold: 80},
{Name: "磁盘使用率(Warn)", Metric: "disk", Operator: ">", Threshold: 80},
{Name: "网络带宽使用率(Warn)", Metric: "net", Operator: ">", Threshold: 80},
}
created := 0
skipped := 0
for _, host := range onlineHosts {
for _, def := range defaultRules {
// 检查是否已存在同名同主机的规则,避免重复创建
var existing models.AgentRule
h.db.Where("name = ? AND hostname = ?", def.Name, host).First(&existing)
if existing.ID > 0 {
skipped++
continue
}
rule := models.AgentRule{
Name: def.Name,
Hostname: host,
Metric: def.Metric,
Operator: def.Operator,
Threshold: def.Threshold,
Enabled: true,
}
if err := h.db.Create(&rule).Error; err != nil {
continue
}
created++
}
}
c.JSON(200, models.Response{
Code: 200,
Message: fmt.Sprintf("已为 %d 台主机创建 %d 条规则(跳过 %d 条已存在的)", len(onlineHosts), created, skipped),
Data: gin.H{"hosts": len(onlineHosts), "created": created, "skipped": skipped},
})
}
// ListRules GET /api/v1/agent/rules
func (h *AgentTaskHandler) ListRules(c *gin.Context) {
var rules []models.AgentRule