90 lines
1.9 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"strconv"
"time"
"metis/pkg/sentinel"
)
func main() {
interval := time.Duration(getenvInt("METIS_SENTINEL_INTERVAL_SEC", 300)) * time.Second
pushURL := os.Getenv("METIS_SENTINEL_PUSH_URL")
runOnce := os.Getenv("METIS_SENTINEL_RUN_ONCE") == "1"
for {
snap := sentinel.Collect()
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err := enc.Encode(snap); err != nil {
log.Fatalf("encode: %v", err)
}
if out := os.Getenv("METIS_SENTINEL_OUT"); out != "" {
writeHistory(out, snap)
}
if pushURL != "" {
if err := pushSnapshot(pushURL, snap); err != nil {
log.Printf("push snapshot failed: %v", err)
}
}
if runOnce || pushURL == "" {
break
}
time.Sleep(interval)
}
}
func writeHistory(path string, snap *sentinel.Snapshot) {
if path == "" {
return
}
if err := os.MkdirAll(path, 0o755); err != nil {
return
}
ts := time.Now().UTC().Format("20060102T150405Z")
b, _ := json.MarshalIndent(snap, "", " ")
_ = os.WriteFile(filepath.Join(path, "snapshot-"+ts+".json"), b, 0o644)
}
func pushSnapshot(url string, snap *sentinel.Snapshot) error {
payload := map[string]any{
"node": snap.Hostname,
"collected_at": time.Now().UTC(),
"snapshot": snap,
}
body, err := json.Marshal(payload)
if err != nil {
return err
}
req, err := http.NewRequest(http.MethodPost, url, bytes.NewReader(body))
if err != nil {
return err
}
req.Header.Set("Content-Type", "application/json")
resp, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 300 {
return fmt.Errorf("push snapshot: %s", resp.Status)
}
return nil
}
func getenvInt(key string, fallback int) int {
if raw := os.Getenv(key); raw != "" {
if value, err := strconv.Atoi(raw); err == nil {
return value
}
}
return fallback
}