diff --git a/Agent/go.mod b/Agent/go.mod index f323ee1..af7fd3e 100644 --- a/Agent/go.mod +++ b/Agent/go.mod @@ -1,24 +1,26 @@ module github.com/nexusrmm/agent -go 1.22 +go 1.26 require ( - github.com/shirou/gopsutil/v4 v4.24.0 + github.com/shirou/gopsutil/v3 v3.24.5 google.golang.org/grpc v1.60.0 google.golang.org/protobuf v1.32.0 gopkg.in/yaml.v3 v3.0.1 ) require ( - github.com/ebitengine/purego v0.7.0 // indirect + github.com/go-ole/go-ole v1.2.6 // indirect github.com/golang/protobuf v1.5.3 // indirect - github.com/lufia/plan9stats v0.0.0-20240513124658-fba389f38bae // indirect - github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d84 // indirect - github.com/tklauser/go-sysconf v0.3.14 // indirect - github.com/tklauser/numcpus v0.8.0 // indirect - github.com/yusufpapurcu/info v0.0.0-20240514213526-8f62d0eb11ac // indirect + github.com/google/go-cmp v0.6.0 // indirect + github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect + github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect + github.com/shoenig/go-m1cpu v0.1.6 // indirect + github.com/tklauser/go-sysconf v0.3.12 // indirect + github.com/tklauser/numcpus v0.6.1 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect golang.org/x/net v0.21.0 // indirect - golang.org/x/sys v0.17.0 // indirect + golang.org/x/sys v0.20.0 // indirect golang.org/x/text v0.14.0 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240221002015-b0ce06bbee7c // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect ) diff --git a/Agent/go.sum b/Agent/go.sum new file mode 100644 index 0000000..57ba827 --- /dev/null +++ b/Agent/go.sum @@ -0,0 +1,51 @@ +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/golang/protobuf v1.5.3 h1:KESQyS83zrBXM35gw0xMqGD/8xf9AZf6GR9pWqJBKqw= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2rrLzc1mTrFQ63LlQEbvLSi8aE= +github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4= +github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= +github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= +github.com/shirou/gopsutil/v3 v3.24.5 h1:i0t8kL+kQTvpAYToeuiVk3TgDeKOFioZO3Ztz/iZ9pI= +github.com/shirou/gopsutil/v3 v3.24.5/go.mod h1:bsoOS1aStSs9ErQ1WWfxllSeS1K5D+U30r2NfcubMVk= +github.com/shoenig/go-m1cpu v0.1.6 h1:nxdKQNcEB6vzgA2E2bvzKIYRuNj7XNJ4S/aRSwKzFtM= +github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ= +github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= +github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= +github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= +github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= +github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= +github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= +github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= +golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7v2A13j3pWY9+33e/9vnzlU7epo6pCKQ= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/text v0.14.0 h1:ScX5w1eTa60QWvxHNAJo0c1V8AcQ+XO1zNY/e3FFCs= +golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itlqbqQBLa3VwOU= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:3xiWY+VwXwWNwfYXSZR2ysTbLB0WXIM8j3t2nXEd9k4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60ntMRR/VsD2xjcStor2M= +google.golang.org/grpc v1.60.0 h1:6DUVg+gIvjLCktBoNt4d7+fJ/onRuLi1+vyYR5g0gY= +google.golang.org/grpc v1.60.0/go.mod h1:OlCHIeLYqLSIlD9rQ0Drv3KfMAy5fxYvb/dgVzlj0g= +google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex/HNYcPYe3EkladybiguVstpQQelQR5bkY= +google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GDeJLau1oL+D3tIQCmnaqTuStpLJ3XZ+T5+wqE= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/Agent/internal/collector/collector.go b/Agent/internal/collector/collector.go new file mode 100644 index 0000000..68c3463 --- /dev/null +++ b/Agent/internal/collector/collector.go @@ -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 +} diff --git a/Agent/internal/collector/collector_test.go b/Agent/internal/collector/collector_test.go new file mode 100644 index 0000000..c86a968 --- /dev/null +++ b/Agent/internal/collector/collector_test.go @@ -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") + } +} diff --git a/Protos/nexusrmm/agent_service.proto b/Protos/nexusrmm/agent_service.proto index b3afb00..5a59026 100644 --- a/Protos/nexusrmm/agent_service.proto +++ b/Protos/nexusrmm/agent_service.proto @@ -3,7 +3,7 @@ syntax = "proto3"; package nexusrmm; option csharp_namespace = "NexusRMM.Protos"; -option go_package = "github.com/nexusrmm/agent/pkg/proto"; +option go_package = "nexusrmm.local/agent/pkg/proto"; // --- Agent Enrollment --- message EnrollRequest {