feat(monitor): active push loop replacing standalone monitor
Adds a periodic POST loop to <backend>/monitor/server/heartbeat so HF plugin can take over the standalone harborforge-monitor daemon's job — same X-API-Key header, same flat telemetry shape (cpu_pct / mem_pct / disk_pct / swap_pct / load_avg / uptime_seconds / plugin_version / agents[]). HF backend stays unchanged. Config: monitor_push_enabled (default false; opt-in to avoid surprise heartbeats from existing deployments), monitor_push_interval_seconds (default 30), reuses apiKey for the X-API-Key header. Lift the container's HF_MONITER_API_KEY into config.apiKey, flip monitor_push_enabled true, then docker rm -f the container — DB last_seen_at keeps advancing under the plugin's loop. Collector grew swap + cpu sampling (two reads of /proc/stat over a 1-second window when SampleCPU=true). Bridge endpoint stays cheap (SampleCPU=false on demand); push loop is the only caller paying the sampling cost. E2E in sim: monitor_push_enabled=true + apiKey from injected MonitoredServer row → server_states.last_seen_at advances exactly every interval_seconds (10s configured, 10s observed). cpu/mem/disk/ swap_pct all populate correctly.
This commit is contained in:
@@ -35,6 +35,17 @@ type Config struct {
|
||||
// server listens on. Zero/missing disables the bridge entirely.
|
||||
MonitorPort int `json:"monitor_port,omitempty"`
|
||||
|
||||
// MonitorPushEnabled toggles the active push loop that uploads
|
||||
// system telemetry to BackendURL /monitor/server/heartbeat. Lets
|
||||
// HF plugin replace the standalone harborforge-monitor container.
|
||||
// nil (unset) defaults to false; operators must opt in explicitly
|
||||
// since they need to provision APIKey too.
|
||||
MonitorPushEnabled *bool `json:"monitor_push_enabled,omitempty"`
|
||||
|
||||
// MonitorPushIntervalSeconds — defaults to 30s when ≤0. Mirrors
|
||||
// the standalone monitor's HF_MONITER_REPORT_INTERVAL knob.
|
||||
MonitorPushIntervalSeconds int `json:"monitor_push_interval_seconds,omitempty"`
|
||||
|
||||
// CalendarHeartbeatIntervalSeconds — defaults to 30s when ≤0.
|
||||
CalendarHeartbeatIntervalSeconds int `json:"calendar_heartbeat_interval_seconds,omitempty"`
|
||||
|
||||
@@ -57,6 +68,8 @@ type Resolved struct {
|
||||
Identifier string
|
||||
APIKey string
|
||||
MonitorPort int
|
||||
MonitorPushEnabled bool
|
||||
MonitorPushIntervalSeconds int
|
||||
CalendarEnabled bool
|
||||
CalendarHeartbeatIntervalSeconds int
|
||||
CalendarBackendURL string
|
||||
@@ -104,6 +117,8 @@ func Resolve(c Config) Resolved {
|
||||
Identifier: c.Identifier,
|
||||
APIKey: c.APIKey,
|
||||
MonitorPort: c.MonitorPort,
|
||||
MonitorPushEnabled: false,
|
||||
MonitorPushIntervalSeconds: 30,
|
||||
CalendarEnabled: true,
|
||||
CalendarHeartbeatIntervalSeconds: 30,
|
||||
CalendarBackendURL: c.CalendarBackendURL,
|
||||
@@ -127,6 +142,12 @@ func Resolve(c Config) Resolved {
|
||||
if c.CalendarHeartbeatIntervalSeconds > 0 {
|
||||
out.CalendarHeartbeatIntervalSeconds = c.CalendarHeartbeatIntervalSeconds
|
||||
}
|
||||
if c.MonitorPushEnabled != nil {
|
||||
out.MonitorPushEnabled = *c.MonitorPushEnabled
|
||||
}
|
||||
if c.MonitorPushIntervalSeconds > 0 {
|
||||
out.MonitorPushIntervalSeconds = c.MonitorPushIntervalSeconds
|
||||
}
|
||||
if c.RestartPollIntervalSeconds > 0 {
|
||||
out.RestartPollIntervalSeconds = c.RestartPollIntervalSeconds
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user