//go:build windows package stats import ( "os" "runtime" "sync" "syscall" "unsafe" ) type memoryStatusEx struct { Length uint32 MemoryLoad uint32 TotalPhys uint64 AvailPhys uint64 TotalPageFile uint64 AvailPageFile uint64 TotalVirtual uint64 AvailVirtual uint64 AvailExtendedVirtual uint64 } var ( kernel32 = syscall.NewLazyDLL("kernel32.dll") procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx") ) type Reporter struct { mu sync.Mutex lastIdle uint64 lastKernel uint64 lastUser uint64 hasSample bool } func NewReporter() *Reporter { return &Reporter{} } func (r *Reporter) SystemInfo() (hostname string, cpuCores int, memoryGB int) { hostname, _ = os.Hostname() cpuCores = runtime.NumCPU() total, _ := r.memoryStatus() memoryGB = int(total / (1024 * 1024 * 1024)) if memoryGB < 1 { memoryGB = 1 } return hostname, cpuCores, memoryGB } func (r *Reporter) Usage() (cpuPct float64, memPct float64) { total, avail := r.memoryStatus() if total > 0 { memPct = float64(total-avail) / float64(total) * 100 } cpuPct = 0 return cpuPct, memPct } func (r *Reporter) FreeMemoryMB() uint64 { _, avail := r.memoryStatus() return avail / (1024 * 1024) } func (r *Reporter) TotalMemoryMB() uint64 { total, _ := r.memoryStatus() return total / (1024 * 1024) } func (r *Reporter) memoryStatus() (total, avail uint64) { var stat memoryStatusEx stat.Length = uint32(unsafe.Sizeof(stat)) ret, _, _ := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&stat))) if ret == 0 { return 0, 0 } return stat.TotalPhys, stat.AvailPhys }