package sender import ( "bytes" "context" "encoding/json" "net/http" "time" "bugs.watch/agent/internal/config" "bugs.watch/agent/internal/aggregate" ) type HTTPSender struct { client *http.Client endpoint string token string hostID string env string } func NewHTTPSender(cfg config.Config) *HTTPSender { return &HTTPSender{ client: &http.Client{ Timeout: 5 * time.Second, }, endpoint: cfg.Endpoint + "/api/v1/agents/" + cfg.AgentID, token: cfg.APIToken, hostID: cfg.HostID, env: cfg.Env, } } func (s *HTTPSender) Send(ctx context.Context, snap aggregate.Snapshot) error { payload := SnapshotPayload{ Timestamp: snap.Timestamp, CPUAvg: snap.CPUAvg, MemAvg: snap.MemAvg, DiskAvg: snap.DiskAvg, Uptime: snap.Uptime, Load: snap.Load, HostID: s.hostID, Environment: s.env, DBDriver: snap.DBDriver, DBConnPct: snap.DBConnPct, DBThreadsRunning: snap.DBThreadsRunning, DBSlowQueries: snap.DBSlowQueries, DBSizeBytes: snap.DBSizeBytes, } body, err := json.Marshal(payload) if err != nil { return err } req, err := http.NewRequestWithContext( ctx, http.MethodPut, s.endpoint, bytes.NewReader(body), ) if err != nil { return err } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer " + s.token) resp, err := s.client.Do(req) if err != nil { return err } defer resp.Body.Close() // We do not retry or branch yet. // Any non-2xx is treated as a failure. if resp.StatusCode < 200 || resp.StatusCode >= 300 { return nil } return nil }