| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189 |
- package system
- import (
- "bufio"
- "fmt"
- "os"
- "strconv"
- "strings"
- "github.com/vishvananda/netlink"
- )
- type SystemStatus struct {
- Hostname string `json:"hostname"`
- OS string `json:"os"`
- Kernel string `json:"kernel"`
- UptimeSeconds float64 `json:"uptime_seconds"`
- UptimeHuman string `json:"uptime_human"`
- CPULoad []string `json:"cpu_load"` // 1m, 5m, 15m
- MemTotalMB uint64 `json:"mem_total_mb"`
- MemUsedMB uint64 `json:"mem_used_mb"`
- MemUsagePct float64 `json:"mem_usage_pct"`
- TotalIfaces int `json:"total_ifaces"`
- UpIfaces int `json:"up_ifaces"`
- DownIfaces int `json:"down_ifaces"`
- VlanIfaces int `json:"vlan_ifaces"`
- DefaultGateway string `json:"default_gateway"`
- }
- type RouteInfo struct {
- Destination string `json:"destination"`
- Gateway string `json:"gateway"`
- Interface string `json:"interface"`
- Protocol int `json:"protocol"`
- Scope int `json:"scope"`
- }
- // GetStatus returns system-level metrics and router telemetry.
- func GetStatus() (*SystemStatus, error) {
- hostname, _ := os.Hostname()
- osName := "Debian Linux"
- if f, err := os.Open("/etc/os-release"); err == nil {
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- if strings.HasPrefix(line, "PRETTY_NAME=") {
- osName = strings.Trim(strings.TrimPrefix(line, "PRETTY_NAME="), "\"")
- break
- }
- }
- _ = f.Close()
- }
- kernel := "Linux"
- if data, err := os.ReadFile("/proc/sys/kernel/osrelease"); err == nil {
- kernel = strings.TrimSpace(string(data))
- }
- uptimeSec, uptimeHuman := getUptime()
- cpuLoads := getCPULoad()
- memTotal, memUsed, memPct := getMemory()
- defGateway := getDefaultGateway()
- return &SystemStatus{
- Hostname: hostname,
- OS: osName,
- Kernel: kernel,
- UptimeSeconds: uptimeSec,
- UptimeHuman: uptimeHuman,
- CPULoad: cpuLoads,
- MemTotalMB: memTotal,
- MemUsedMB: memUsed,
- MemUsagePct: memPct,
- DefaultGateway: defGateway,
- }, nil
- }
- func getUptime() (float64, string) {
- data, err := os.ReadFile("/proc/uptime")
- if err != nil {
- return 0, "Unknown"
- }
- parts := strings.Fields(string(data))
- if len(parts) == 0 {
- return 0, "Unknown"
- }
- sec, _ := strconv.ParseFloat(parts[0], 64)
- days := int(sec) / 86400
- hours := (int(sec) % 86400) / 3600
- minutes := (int(sec) % 3600) / 60
- if days > 0 {
- return sec, fmt.Sprintf("%dd %dh %dm", days, hours, minutes)
- }
- return sec, fmt.Sprintf("%dh %dm", hours, minutes)
- }
- func getCPULoad() []string {
- data, err := os.ReadFile("/proc/loadavg")
- if err != nil {
- return []string{"0.00", "0.00", "0.00"}
- }
- parts := strings.Fields(string(data))
- if len(parts) >= 3 {
- return parts[:3]
- }
- return []string{"0.00", "0.00", "0.00"}
- }
- func getMemory() (totalMB uint64, usedMB uint64, pct float64) {
- f, err := os.Open("/proc/meminfo")
- if err != nil {
- return 0, 0, 0
- }
- defer f.Close()
- var total, available uint64
- scanner := bufio.NewScanner(f)
- for scanner.Scan() {
- line := scanner.Text()
- if strings.HasPrefix(line, "MemTotal:") {
- parts := strings.Fields(line)
- if len(parts) >= 2 {
- total, _ = strconv.ParseUint(parts[1], 10, 64)
- }
- } else if strings.HasPrefix(line, "MemAvailable:") {
- parts := strings.Fields(line)
- if len(parts) >= 2 {
- available, _ = strconv.ParseUint(parts[1], 10, 64)
- }
- }
- }
- totalMB = total / 1024
- usedMB = (total - available) / 1024
- if total > 0 {
- pct = (float64(total-available) / float64(total)) * 100.0
- }
- return
- }
- func getDefaultGateway() string {
- routes, err := netlink.RouteList(nil, netlink.FAMILY_V4)
- if err != nil {
- return ""
- }
- for _, r := range routes {
- if r.Dst == nil && r.Gw != nil {
- return r.Gw.String()
- }
- }
- return ""
- }
- // GetRoutingTable returns the list of active routes.
- func GetRoutingTable() ([]RouteInfo, error) {
- routes, err := netlink.RouteList(nil, netlink.FAMILY_ALL)
- if err != nil {
- return nil, err
- }
- links, _ := netlink.LinkList()
- linkMap := make(map[int]string)
- for _, l := range links {
- linkMap[l.Attrs().Index] = l.Attrs().Name
- }
- result := make([]RouteInfo, 0)
- for _, r := range routes {
- dst := "default"
- if r.Dst != nil {
- dst = r.Dst.String()
- }
- gw := ""
- if r.Gw != nil {
- gw = r.Gw.String()
- }
- result = append(result, RouteInfo{
- Destination: dst,
- Gateway: gw,
- Interface: linkMap[r.LinkIndex],
- Protocol: int(r.Protocol),
- Scope: int(r.Scope),
- })
- }
- return result, nil
- }
|