- Go agent: CPU/mem/disk/port collectors, HTTP report, static binary - Cross-compile: linux/amd64 + linux/arm64 (statically linked) - One-line install script for all Linux distros - Backend: POST /api/v1/agent/report (no JWT) + GET /agent/latest,history (JWT) - CloudBilling.tsx: fixed syntax errors, stats/trends/records/alerts - K8s menu renamed to Kubernetes管理 Signed-off-by: Logan.Li
111 lines
2.7 KiB
Go
111 lines
2.7 KiB
Go
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,
|
|
})
|
|
}
|