Agent-Status und Inaktivitaets-Erkennung implementiert
- Status wird aus last_heartbeat berechnet (online/stale/offline/unknown)
- GET /agents und GET /agents/{id} liefern status Feld
- agent_events Tabelle fuer Event-Tracking (Migration automatisch)
- Inaktivitaets-Monitor als Goroutine (prueft alle 60s, schreibt Events bei Statuswechsel)
- WebSocket Connect/Disconnect Events werden automatisch geschrieben
- API-Endpoints: GET /agents/events und GET /agents/{id}/events (?limit=N&type=X)
- DB-Methoden: InsertAgentEvent, GetAgentEvents, GetAllAgentEvents, GetAgentStatus
- README aktualisiert (Status-Doku, Events API, Dateistruktur)
This commit is contained in:
@@ -0,0 +1,77 @@
|
||||
package monitor
|
||||
|
||||
import (
|
||||
"log"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/cynfo/rmm-backend/db"
|
||||
"github.com/cynfo/rmm-backend/models"
|
||||
)
|
||||
|
||||
// Monitor prueft periodisch den Agent-Status und schreibt Events bei Statuswechsel
|
||||
type Monitor struct {
|
||||
db *db.Database
|
||||
lastStatus map[string]string
|
||||
lastStatusMu sync.Mutex
|
||||
interval time.Duration
|
||||
}
|
||||
|
||||
// New erstellt einen neuen Monitor
|
||||
func New(database *db.Database) *Monitor {
|
||||
return &Monitor{
|
||||
db: database,
|
||||
lastStatus: make(map[string]string),
|
||||
interval: 60 * time.Second,
|
||||
}
|
||||
}
|
||||
|
||||
// Run startet den Monitor als Goroutine — blockiert, also mit go aufrufen
|
||||
func (m *Monitor) Run() {
|
||||
log.Println("Inaktivitaets-Monitor gestartet (Intervall: 60s)")
|
||||
|
||||
// Initialen Status laden
|
||||
m.checkAgents()
|
||||
|
||||
ticker := time.NewTicker(m.interval)
|
||||
defer ticker.Stop()
|
||||
|
||||
for range ticker.C {
|
||||
m.checkAgents()
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Monitor) checkAgents() {
|
||||
agents, err := m.db.GetAgents()
|
||||
if err != nil {
|
||||
log.Printf("Monitor: Fehler beim Laden der Agents: %v", err)
|
||||
return
|
||||
}
|
||||
|
||||
m.lastStatusMu.Lock()
|
||||
defer m.lastStatusMu.Unlock()
|
||||
|
||||
for _, agent := range agents {
|
||||
newStatus := models.CalculateAgentStatus(agent.LastHeartbeat)
|
||||
oldStatus, known := m.lastStatus[agent.ID]
|
||||
|
||||
if !known {
|
||||
// Erster Check — Status merken, kein Event
|
||||
m.lastStatus[agent.ID] = newStatus
|
||||
log.Printf("Monitor: Agent %s (%s) initialer Status: %s", agent.Name, agent.ID, newStatus)
|
||||
continue
|
||||
}
|
||||
|
||||
if oldStatus == newStatus {
|
||||
continue
|
||||
}
|
||||
|
||||
// Statuswechsel erkannt
|
||||
log.Printf("Monitor: Agent %s (%s) Status-Wechsel: %s -> %s", agent.Name, agent.ID, oldStatus, newStatus)
|
||||
m.lastStatus[agent.ID] = newStatus
|
||||
|
||||
// Event schreiben
|
||||
message := "Status-Wechsel: " + oldStatus + " -> " + newStatus
|
||||
m.db.InsertAgentEvent(agent.ID, newStatus, message)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user