package main import ( "bytes" "encoding/json" "fmt" "log" "net/http" "os" "runtime" "time" "github.com/shirou/gopsutil/v3/cpu" "github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/host" "github.com/shirou/gopsutil/v3/mem" "github.com/shirou/gopsutil/v3/net" ) type Metrics struct { Hostname string `json:"hostname"` Timestamp time.Time `json:"timestamp"` CPU CPUMetric `json:"cpu"` Memory MemMetric `json:"memory"` Disk []DiskMetric `json:"disk"` Network NetMetric `json:"network"` } type CPUMetric struct { UsagePercent float64 `json:"usage_percent"` Cores int `json:"cores"` } type MemMetric struct { Total uint64 `json:"total"` Used uint64 `json:"used"` UsedPercent float64 `json:"used_percent"` } type DiskMetric struct { Path string `json:"path"` Total uint64 `json:"total"` Used uint64 `json:"used"` UsedPercent float64 `json:"used_percent"` } type NetMetric struct { BytesSent uint64 `json:"bytes_sent"` BytesRecv uint64 `json:"bytes_recv"` } func main() { serverURL := os.Getenv("OPHION_SERVER") if serverURL == "" { serverURL = "http://localhost:8080" } apiKey := os.Getenv("OPHION_API_KEY") if apiKey == "" { log.Fatal("OPHION_API_KEY is required") } interval := 30 * time.Second log.Printf("🐍 OPHION Agent starting - reporting to %s every %s", serverURL, interval) ticker := time.NewTicker(interval) for range ticker.C { metrics := collectMetrics() sendMetrics(serverURL, apiKey, metrics) } } func collectMetrics() Metrics { hostname, _ := os.Hostname() cpuPercent, _ := cpu.Percent(time.Second, false) cpuUsage := 0.0 if len(cpuPercent) > 0 { cpuUsage = cpuPercent[0] } memInfo, _ := mem.VirtualMemory() diskInfo, _ := disk.Usage("/") disks := []DiskMetric{{ Path: "/", Total: diskInfo.Total, Used: diskInfo.Used, UsedPercent: diskInfo.UsedPercent, }} netIO, _ := net.IOCounters(false) netMetric := NetMetric{} if len(netIO) > 0 { netMetric.BytesSent = netIO[0].BytesSent netMetric.BytesRecv = netIO[0].BytesRecv } return Metrics{ Hostname: hostname, Timestamp: time.Now(), CPU: CPUMetric{ UsagePercent: cpuUsage, Cores: runtime.NumCPU(), }, Memory: MemMetric{ Total: memInfo.Total, Used: memInfo.Used, UsedPercent: memInfo.UsedPercent, }, Disk: disks, Network: netMetric, } } func sendMetrics(serverURL, apiKey string, metrics Metrics) { data, _ := json.Marshal(metrics) req, _ := http.NewRequest("POST", serverURL+"/api/v1/metrics", bytes.NewBuffer(data)) req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer "+apiKey) client := &http.Client{Timeout: 10 * time.Second} resp, err := client.Do(req) if err != nil { log.Printf("Error sending metrics: %v", err) return } defer resp.Body.Close() if resp.StatusCode == 200 { log.Printf("✓ Metrics sent: CPU=%.1f%% MEM=%.1f%%", metrics.CPU.UsagePercent, metrics.Memory.UsedPercent) } }