feat: Initial OPHION structure
- Go backend with Fiber framework - Agent for metrics collection - Docker Compose for self-hosted - Auth middleware (JWT + API Keys) - Rate limiting - Install script
This commit is contained in:
135
cmd/agent/main.go
Normal file
135
cmd/agent/main.go
Normal file
@@ -0,0 +1,135 @@
|
||||
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)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user