- Go backend with Fiber framework - Agent for metrics collection - Docker Compose for self-hosted - Auth middleware (JWT + API Keys) - Rate limiting - Install script
136 lines
3.0 KiB
Go
136 lines
3.0 KiB
Go
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)
|
|
}
|
|
}
|