feat: implement cross-platform metric collector with gopsutil, rename module to nexusrmm.local/agent

This commit is contained in:
Claude Agent
2026-03-19 12:14:14 +01:00
parent 7c85afe39b
commit 51052261f5
5 changed files with 183 additions and 11 deletions

View File

@@ -0,0 +1,100 @@
package collector
import (
"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"
psnet "github.com/shirou/gopsutil/v3/net"
)
type Metrics struct {
CPUPercent float64
MemoryPercent float64
MemoryTotal uint64
MemoryAvailable uint64
Disks []DiskInfo
Networks []NetInfo
UptimeSeconds float64
}
type DiskInfo struct {
MountPoint string
Total uint64
Free uint64
Filesystem string
}
type NetInfo struct {
Name string
IPAddress string
MAC string
BytesSent uint64
BytesRecv uint64
}
func Collect() (*Metrics, error) {
cpuPercent, err := cpu.Percent(time.Second, false)
if err != nil {
return nil, err
}
memInfo, err := mem.VirtualMemory()
if err != nil {
return nil, err
}
uptime, _ := host.Uptime()
m := &Metrics{
CPUPercent: cpuPercent[0],
MemoryPercent: memInfo.UsedPercent,
MemoryTotal: memInfo.Total,
MemoryAvailable: memInfo.Available,
UptimeSeconds: float64(uptime),
}
// Disks
partitions, _ := disk.Partitions(false)
for _, p := range partitions {
usage, err := disk.Usage(p.Mountpoint)
if err != nil {
continue
}
m.Disks = append(m.Disks, DiskInfo{
MountPoint: p.Mountpoint,
Total: usage.Total,
Free: usage.Free,
Filesystem: p.Fstype,
})
}
// Network
interfaces, _ := psnet.Interfaces()
counters, _ := psnet.IOCounters(true)
counterMap := make(map[string]psnet.IOCountersStat)
for _, c := range counters {
counterMap[c.Name] = c
}
for _, iface := range interfaces {
if len(iface.Addrs) == 0 {
continue
}
ni := NetInfo{
Name: iface.Name,
MAC: iface.HardwareAddr,
}
if len(iface.Addrs) > 0 {
ni.IPAddress = iface.Addrs[0].Addr
}
if c, ok := counterMap[iface.Name]; ok {
ni.BytesSent = c.BytesSent
ni.BytesRecv = c.BytesRecv
}
m.Networks = append(m.Networks, ni)
}
return m, nil
}

View File

@@ -0,0 +1,19 @@
package collector
import "testing"
func TestCollect(t *testing.T) {
metrics, err := Collect()
if err != nil {
t.Fatalf("Collect() error: %v", err)
}
if metrics.CPUPercent < 0 || metrics.CPUPercent > 100 {
t.Errorf("CPU percent out of range: %f", metrics.CPUPercent)
}
if metrics.MemoryTotal == 0 {
t.Error("MemoryTotal should not be 0")
}
if len(metrics.Disks) == 0 {
t.Error("Expected at least one disk")
}
}