package agent import ( "bytes" "encoding/json" "fmt" "net/http" "time" ) type Heartbeat struct { cfg Config nodeID string client *http.Client } type HeartbeatPayload struct { NodeID string `json:"node_id"` CPUPct float64 `json:"cpu_percent"` MemPct float64 `json:"memory_percent"` BandwidthMbps float64 `json:"bandwidth_mbps"` ActiveConnections int `json:"active_connections"` HlsReaders int `json:"hls_readers"` } type RegisterPayload struct { NodeID string `json:"node_id"` Name string `json:"name"` Host string `json:"host"` HlsPort int `json:"hls_port"` ApiPort int `json:"api_port"` Weight int `json:"weight"` Subnet string `json:"subnet"` } func NewHeartbeat(cfg Config, nodeID string) *Heartbeat { return &Heartbeat{ cfg: cfg, nodeID: nodeID, client: &http.Client{Timeout: 10 * time.Second}, } } func (h *Heartbeat) Register() error { payload := RegisterPayload{ NodeID: h.nodeID, Name: h.cfg.NodeName, Host: h.cfg.OriginURL, HlsPort: h.cfg.HlsPort, ApiPort: h.cfg.ApiPort, Weight: h.cfg.Weight, Subnet: h.cfg.Subnet, } return h.post("/api/nodes/register", payload) } func (h *Heartbeat) Send(m Metrics) error { payload := HeartbeatPayload{ NodeID: h.nodeID, CPUPct: m.CPU, MemPct: m.Memory, BandwidthMbps: m.Bandwidth, ActiveConnections: m.ActiveConns, HlsReaders: m.HlsReaders, } return h.post("/api/nodes/heartbeat", payload) } func (h *Heartbeat) post(path string, payload interface{}) error { body, err := json.Marshal(payload) if err != nil { return err } url := h.cfg.OriginURL + path resp, err := h.client.Post(url, "application/json", bytes.NewReader(body)) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode >= 400 { return fmt.Errorf("status %d", resp.StatusCode) } return nil }