Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
db6f666ff7 |
@@ -626,11 +626,16 @@ func probeStatIface(agentID int64) string {
|
||||
}
|
||||
|
||||
// probeReport ingests one fast report (V2.0.1): a probe metrics
|
||||
// block and nothing else. It deliberately does NOT touch the
|
||||
// agent's last-seen stamp — liveness stays the 60 s heartbeat's
|
||||
// signal, and the traffic ledger's unseen-boot rule keeps measuring
|
||||
// reboots against heartbeat sightings exactly as before. Agents on
|
||||
// older masters never see this endpoint (404) and simply keep
|
||||
// block and nothing else. Since V2.0.3 it also touches the agent's
|
||||
// last-seen stamp, like every other report channel: the hub's
|
||||
// themes gate each batch on the node's last_seen being newer than
|
||||
// the last one they applied, so a metrics-only channel that never
|
||||
// advanced the stamp froze the public cards between the 10 s
|
||||
// traffic reports. Liveness now means "any report from the agent"
|
||||
// — all channels come from the same process — and the traffic
|
||||
// ledger's unseen-boot rule is unaffected: Record still receives
|
||||
// the pre-touch stamp, so gaps measure exactly as before. Agents
|
||||
// on older masters never see this endpoint (404) and simply keep
|
||||
// reporting metrics on the heartbeat; masters accept metrics on
|
||||
// either channel.
|
||||
func (a *AgentController) probeReport(c *gin.Context) {
|
||||
@@ -644,9 +649,13 @@ func (a *AgentController) probeReport(c *gin.Context) {
|
||||
ProbeMetrics *heartbeatProbeMetrics `json:"probeMetrics"`
|
||||
}
|
||||
_ = c.ShouldBindJSON(&req)
|
||||
// The last-seen stamp as it stood before this report (see the
|
||||
// heartbeat handler): captured before touchAgent overwrites it.
|
||||
prevLastSeen := agent.LastSeen
|
||||
a.touchAgent(uint(agent.Id), "")
|
||||
if req.ProbeMetrics != nil {
|
||||
a.updateAgentProbe(uint(agent.Id), nil, req.ProbeMetrics)
|
||||
probe.Record(int64(agent.Id), probeSample(req.ProbeMetrics), agent.LastSeen)
|
||||
probe.Record(int64(agent.Id), probeSample(req.ProbeMetrics), prevLastSeen)
|
||||
}
|
||||
jsonObj(c, gin.H{"message": "ok"}, nil)
|
||||
}
|
||||
|
||||
@@ -18,9 +18,10 @@ import (
|
||||
)
|
||||
|
||||
// V2.0.1 probe batch, master side: the fast-report endpoint ingests
|
||||
// metrics without touching liveness (last-seen stays the
|
||||
// heartbeat's), and the config poll carries the cadence + the
|
||||
// node's counted-interface pin.
|
||||
// metrics, and the config poll carries the cadence + the node's
|
||||
// counted-interface pin. Since V2.0.3 the fast report also stamps
|
||||
// last-seen (the hub's themes gate batches on its freshness); it
|
||||
// originally did not — see the probeReport handler comment.
|
||||
func TestAgentFastReportAndConfigKeys(t *testing.T) {
|
||||
gin.SetMode(gin.TestMode)
|
||||
dbDir := t.TempDir()
|
||||
@@ -71,6 +72,12 @@ func TestAgentFastReportAndConfigKeys(t *testing.T) {
|
||||
|
||||
metrics := `{"probeMetrics":{"bootId":"boot-f/0123456789abcdef","uptime":60,` +
|
||||
`"memTotal":1000,"memUsed":400,"netRxTotal":10,"netTxTotal":20}}`
|
||||
// Age the stamp first so the fast report's touch is observable
|
||||
// even within the same millisecond as the heartbeat's.
|
||||
stale := seenAfterHeartbeat - 120_000
|
||||
if err := db.Model(&model.AgentNode{}).Where("id = ?", agent.Id).Update("last_seen", stale).Error; err != nil {
|
||||
t.Fatalf("age last-seen: %v", err)
|
||||
}
|
||||
if code, body := call(http.MethodPost, "/panel/api/agent/probe-report", metrics); code != http.StatusOK {
|
||||
t.Fatalf("probe-report: %d (%s)", code, body)
|
||||
}
|
||||
@@ -78,8 +85,8 @@ func TestAgentFastReportAndConfigKeys(t *testing.T) {
|
||||
if row.ProbeMemUsed != 400 || row.ProbeAt == 0 {
|
||||
t.Errorf("fast report metrics not stored: %+v", row)
|
||||
}
|
||||
if row.LastSeen != seenAfterHeartbeat {
|
||||
t.Errorf("fast report moved last-seen: %d -> %d (liveness is the heartbeat's signal)", seenAfterHeartbeat, row.LastSeen)
|
||||
if row.LastSeen <= stale {
|
||||
t.Errorf("fast report did not stamp last-seen: %d -> %d (V2.0.3: themes gate on it)", stale, row.LastSeen)
|
||||
}
|
||||
|
||||
// Unauthorized callers are refused.
|
||||
|
||||
@@ -29,9 +29,11 @@ import (
|
||||
// 150 s absorbs one lost beat plus jitter.
|
||||
const ProbeOnlineThresholdMs = 150_000
|
||||
|
||||
// ProbeSnapshotTTL mirrors the hub's 1900 ms frame reuse: just under
|
||||
// the 2 s push interval, so a frame is built at most once per tick.
|
||||
const ProbeSnapshotTTL = 1900 * time.Millisecond
|
||||
// ProbeSnapshotTTL mirrors the hub's frame reuse, shortened in
|
||||
// V2.0.3 from the hub's 1900 ms: just under the fastest (1 s) push
|
||||
// cadence, so a 1 s stream still gets a fresh frame every tick
|
||||
// instead of repeating the previous one half the time.
|
||||
const ProbeSnapshotTTL = 900 * time.Millisecond
|
||||
|
||||
// ---- public-surface settings (main settings KV, hub key names) ----
|
||||
|
||||
|
||||
Reference in New Issue
Block a user