feat(collectors) basic implementation of boring collectors; sender via http(s) to hard coded api route

This commit is contained in:
2026-01-18 19:21:16 +00:00
parent e64f597fab
commit db6ed003f1
12 changed files with 611 additions and 0 deletions

66
internal/sender/http.go Normal file
View File

@@ -0,0 +1,66 @@
package sender
import (
"bytes"
"context"
"encoding/json"
"net/http"
"time"
"bugs.watch/agent/internal/aggregate"
)
type HTTPSender struct {
client *http.Client
endpoint string
}
func NewHTTPSender(endpoint string) *HTTPSender {
return &HTTPSender{
client: &http.Client{
Timeout: 5 * time.Second,
},
endpoint: endpoint,
}
}
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,
}
body, err := json.Marshal(payload)
if err != nil {
return err
}
req, err := http.NewRequestWithContext(
ctx,
http.MethodPost,
s.endpoint,
bytes.NewReader(body),
)
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
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
}

View File

@@ -0,0 +1,33 @@
package sender
import (
"context"
"log"
"bugs.watch/agent/internal/aggregate"
)
// LoggingSender sends snapshots to the local log.
// This is a stand-in for HTTP or disk-backed senders.
type LoggingSender struct{}
func NewLoggingSender() *LoggingSender {
return &LoggingSender{}
}
func (s *LoggingSender) Send(ctx context.Context, snap aggregate.Snapshot) error {
select {
case <-ctx.Done():
// Context cancelled. Best effort: do not block shutdown.
return ctx.Err()
default:
log.Printf(
"SEND cpu=%.2f%% mem=%.2f%% disk=%.2f%% uptime=%ds",
snap.CPUAvg,
snap.MemAvg,
snap.DiskAvg,
snap.Uptime,
)
return nil
}
}

View File

@@ -0,0 +1,14 @@
package sender
import "time"
// SnapshotPayload is the wire format sent to bugs.watch.
type SnapshotPayload struct {
Timestamp time.Time `json:"timestamp"`
CPUAvg float64 `json:"cpu_avg"`
MemAvg float64 `json:"mem_avg"`
DiskAvg float64 `json:"disk_avg"`
Uptime uint64 `json:"uptime"`
}

12
internal/sender/sender.go Normal file
View File

@@ -0,0 +1,12 @@
package sender
import (
"context"
"bugs.watch/agent/internal/aggregate"
)
// Sender sends snapshots somewhere.
type Sender interface {
Send(ctx context.Context, snap aggregate.Snapshot) error
}