package handlers import ( "encoding/json" "fmt" "net/http" "time" "ezops/internal/models" "github.com/gin-gonic/gin" "gorm.io/gorm" ) // AgentHandler 处理 Agent 上报数据 // Logan.Li type AgentHandler struct { db *gorm.DB } func NewAgentHandler(db *gorm.DB) *AgentHandler { return &AgentHandler{db: db} } // ReceiveReport 接收 Agent 上报的指标数据 // POST /api/v1/agent/report func (h *AgentHandler) ReceiveReport(c *gin.Context) { var req models.AgentReportRequest if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, models.Response{Code: 400, Message: "请求格式错误: " + err.Error()}) return } // 解析上报时间 reportTime := time.Now() if req.Timestamp != "" { if t, err := time.Parse(time.RFC3339, req.Timestamp); err == nil { reportTime = t } } // 序列化磁盘和端口信息 diskJSON, _ := json.Marshal(req.Disks) portJSON, _ := json.Marshal(req.Ports) // 存储到数据库 report := models.AgentReport{ Hostname: req.Hostname, CPUUsage: req.CPU.UsagePercent, CPUCores: req.CPU.CoreCount, Load1: req.CPU.Load1, Load5: req.CPU.Load5, Load15: req.CPU.Load15, MemTotal: req.Memory.TotalGB, MemUsed: req.Memory.UsedGB, MemUsage: req.Memory.UsagePercent, DiskInfo: string(diskJSON), PortInfo: string(portJSON), ReportTime: reportTime, } if err := h.db.Create(&report).Error; err != nil { c.JSON(http.StatusInternalServerError, models.Response{Code: 500, Message: "保存失败: " + err.Error()}) return } // 保存成功 c.JSON(http.StatusOK, models.Response{Code: 200, Message: "ok"}) } // GetLatestReports 获取各主机最新上报 // GET /api/v1/agent/latest func (h *AgentHandler) GetLatestReports(c *gin.Context) { // 子查询:每个 hostname 最新的一条记录 var reports []models.AgentReport h.db.Raw(` SELECT * FROM agent_reports WHERE id IN ( SELECT MAX(id) FROM agent_reports GROUP BY hostname ) ORDER BY report_time DESC `).Scan(&reports) c.JSON(http.StatusOK, models.Response{ Code: 200, Message: "success", Data: reports, }) } // GetHostHistory 获取指定主机的历史指标 // GET /api/v1/agent/history/:hostname?hours=1 func (h *AgentHandler) GetHostHistory(c *gin.Context) { hostname := c.Param("hostname") hours := 1 if v := c.Query("hours"); v != "" { fmt.Sscanf(v, "%d", &hours) } since := time.Now().Add(-time.Duration(hours) * time.Hour) var reports []models.AgentReport h.db.Where("hostname = ? AND report_time >= ?", hostname, since). Order("report_time ASC"). Find(&reports) c.JSON(http.StatusOK, models.Response{ Code: 200, Message: "success", Data: reports, }) }