package reporter import ( "bytes" "encoding/json" "fmt" "io" "net/http" "time" ) type Reporter struct { serverURL string token string client *http.Client } func NewReporter(serverURL, token string) *Reporter { return &Reporter{ serverURL: serverURL, token: token, client: &http.Client{ Timeout: 10 * time.Second, }, } } type RegisterRequest struct { Hostname string `json:"hostname"` OS string `json:"os"` IP string `json:"ip"` } type RegisterResponse struct { Device struct { ID string `json:"id"` Token string `json:"token"` } `json:"device"` } func (r *Reporter) Register(hostname, osName, ip string) (string, error) { req := RegisterRequest{ Hostname: hostname, OS: osName, IP: ip, } body, err := json.Marshal(req) if err != nil { return "", err } resp, err := r.client.Post(r.serverURL+"/api/v1/register", "application/json", bytes.NewBuffer(body)) if err != nil { return "", fmt.Errorf("failed to register: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { respBody, _ := io.ReadAll(resp.Body) return "", fmt.Errorf("registration failed: %s", string(respBody)) } var regResp RegisterResponse if err := json.NewDecoder(resp.Body).Decode(®Resp); err != nil { return "", err } return regResp.Device.ID, nil } func (r *Reporter) Report(metrics interface{}) error { body, err := json.Marshal(metrics) if err != nil { return err } req, err := http.NewRequest("POST", r.serverURL+"/api/v1/report", bytes.NewBuffer(body)) if err != nil { return err } req.Header.Set("Content-Type", "application/json") if r.token != "" { req.Header.Set("Authorization", "Bearer "+r.token) } resp, err := r.client.Do(req) if err != nil { return fmt.Errorf("failed to report: %v", err) } defer resp.Body.Close() if resp.StatusCode != http.StatusOK { respBody, _ := io.ReadAll(resp.Body) return fmt.Errorf("report failed: %s", string(respBody)) } return nil } func (r *Reporter) Heartbeat(deviceID string) error { req, err := http.NewRequest("POST", r.serverURL+"/api/v1/devices/"+deviceID+"/heartbeat", nil) if err != nil { return err } if r.token != "" { req.Header.Set("Authorization", "Bearer "+r.token) } resp, err := r.client.Do(req) if err != nil { return err } defer resp.Body.Close() return nil }