fix: 完善Agent系统信息上报
- 持续上报系统元数据并动态更新运行时长 - 兼容旧版心跳补齐资产运行时长 - 修复监控指标当前值重复显示单位
This commit is contained in:
1 parent
0c7c63017c
commit
699560a270
4 files changed
+77
-15
No files matched your search
@@ -150,6 +150,10 @@ func (h *AgentHandler) ReceiveReport(c *gin.Context) {
|
||||
updates["uptime"] = req.System.Uptime
|
||||
}
|
||||
}
|
||||
// 兼容旧版 Agent:系统信息缺席时使用心跳中的运行时长补齐资产元数据。 // Logan.Li
|
||||
if _, ok := updates["uptime"]; !ok && req.Heartbeat.UptimeSec > 0 {
|
||||
updates["uptime"] = req.Heartbeat.UptimeSec
|
||||
}
|
||||
var result *gorm.DB
|
||||
if assetMatched {
|
||||
result = h.db.Model(&model.Server{}).Where("id = ?", matchedServer.ID).Updates(updates)
|
||||
@@ -162,19 +166,32 @@ func (h *AgentHandler) ReceiveReport(c *gin.Context) {
|
||||
// 避免 Agent 每次上报(10s)都新建记录导致资产越来越多。
|
||||
if result.Error == nil && result.RowsAffected == 0 {
|
||||
osName := ""
|
||||
kernel := ""
|
||||
uptime := req.Heartbeat.UptimeSec
|
||||
if req.System != nil {
|
||||
osName = req.System.OSVersion
|
||||
kernel = req.System.Kernel
|
||||
if req.System.Uptime > 0 {
|
||||
uptime = req.System.Uptime
|
||||
}
|
||||
}
|
||||
var existing model.Server
|
||||
if h.db.Where("hostname = ?", req.Hostname).Take(&existing).Error == nil {
|
||||
// 已自动注册过 → 仅更新实时指标,不重复创建
|
||||
h.db.Model(&existing).Updates(map[string]interface{}{
|
||||
existingUpdates := map[string]interface{}{
|
||||
"ip": matchIP, "os": osName, "cpu": req.CPU.CoreCount,
|
||||
"memory": memMB, "disk": diskGB, "status": "running",
|
||||
"agent_status": "online", "agent_version": req.AgentVersion,
|
||||
"cpu_usage": req.CPU.UsagePercent, "memory_usage": req.Memory.UsagePercent,
|
||||
"disk_usage": diskAvg,
|
||||
})
|
||||
}
|
||||
if kernel != "" {
|
||||
existingUpdates["kernel"] = kernel
|
||||
}
|
||||
if uptime > 0 {
|
||||
existingUpdates["uptime"] = uptime
|
||||
}
|
||||
h.db.Model(&existing).Updates(existingUpdates)
|
||||
} else {
|
||||
// 真正的新主机 → 注册,hostname 无唯一索引时不使用 OnConflict。 // Logan.Li
|
||||
newServer := model.Server{
|
||||
@@ -190,6 +207,8 @@ func (h *AgentHandler) ReceiveReport(c *gin.Context) {
|
||||
Status: "running",
|
||||
AgentStatus: "online",
|
||||
AgentVersion: req.AgentVersion,
|
||||
Kernel: kernel,
|
||||
Uptime: uptime,
|
||||
CPUUsage: req.CPU.UsagePercent,
|
||||
MemoryUsage: req.Memory.UsagePercent,
|
||||
DiskUsage: diskAvg,
|
||||
|
||||
@@ -79,6 +79,51 @@ func TestReceiveReportMatchesExistingAssetByIP(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReceiveReportUsesHeartbeatUptimeWithoutSystemPayload(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db, err := gorm.Open(sqlite.Open("file:agent_report_heartbeat_uptime?mode=memory&cache=shared"), &gorm.Config{
|
||||
Logger: gormlogger.Default.LogMode(gormlogger.Silent),
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("打开测试数据库失败: %v", err)
|
||||
}
|
||||
if err := db.AutoMigrate(&model.Server{}, &model.AgentReport{}, &model.HealthProbe{}); err != nil {
|
||||
t.Fatalf("迁移测试表失败: %v", err)
|
||||
}
|
||||
|
||||
server := model.Server{Hostname: "c-monitor", IP: "172.19.16.113", Status: "running"}
|
||||
if err := db.Create(&server).Error; err != nil {
|
||||
t.Fatalf("创建测试资产失败: %v", err)
|
||||
}
|
||||
|
||||
body := []byte(`{
|
||||
"hostname":"c-monitor",
|
||||
"ip":"172.19.16.113",
|
||||
"agent_version":"v2.1.0",
|
||||
"cpu":{"usage_percent":1.5,"core_count":4},
|
||||
"memory":{"total_gb":15.1,"used_gb":1.8,"available_gb":13.3,"usage_percent":11.9},
|
||||
"heartbeat":{"uptime_sec":7200}
|
||||
}`)
|
||||
req := httptest.NewRequest(http.MethodPost, "/api/v1/agent/report", bytes.NewReader(body))
|
||||
req.Header.Set("Content-Type", "application/json")
|
||||
recorder := httptest.NewRecorder()
|
||||
c, _ := gin.CreateTestContext(recorder)
|
||||
c.Request = req
|
||||
|
||||
NewAgentHandler(db, nil, nil).ReceiveReport(c)
|
||||
if recorder.Code != http.StatusOK {
|
||||
t.Fatalf("上报返回码 = %d, body=%s", recorder.Code, recorder.Body.String())
|
||||
}
|
||||
|
||||
var gotServer model.Server
|
||||
if err := db.Take(&gotServer, server.ID).Error; err != nil {
|
||||
t.Fatalf("读取资产失败: %v", err)
|
||||
}
|
||||
if gotServer.Uptime != 7200 {
|
||||
t.Fatalf("心跳运行时长未写入资产: got=%d want=7200", gotServer.Uptime)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetLatestReportsUsesUTCTimeBoundary(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
db, err := gorm.Open(sqlite.Open("file:agent_latest_utc?mode=memory&cache=shared"), &gorm.Config{
|
||||
|
||||
Reference in new issue
Block a user