feat(api): add system resource monitoring functionality
- implement getSystemInfo to gather CPU and memory usage - add platform-specific implementations for memory and CPU usage - enhance OpenAPI documentation to include system resource metrics
This commit is contained in:
@@ -0,0 +1,104 @@
|
||||
//go:build darwin
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
func getMemoryInfo() (total, used uint64) {
|
||||
total = sysctl64("hw.memsize")
|
||||
if total == 0 {
|
||||
return 0, 0
|
||||
}
|
||||
|
||||
pageSize, err := syscall.SysctlUint32("hw.pagesize")
|
||||
if err != nil {
|
||||
return total, 0
|
||||
}
|
||||
|
||||
freeCount, _ := syscall.SysctlUint32("vm.page_free_count")
|
||||
purgeableCount, _ := syscall.SysctlUint32("vm.page_purgeable_count")
|
||||
speculativeCount, _ := syscall.SysctlUint32("vm.page_speculative_count")
|
||||
|
||||
// inactive pages not available via sysctl, parse vm_stat
|
||||
inactiveCount := vmStatPages("Pages inactive")
|
||||
|
||||
available := uint64(freeCount+purgeableCount+speculativeCount)*uint64(pageSize) +
|
||||
inactiveCount*uint64(pageSize)
|
||||
if available > total {
|
||||
return total, 0
|
||||
}
|
||||
return total, total - available
|
||||
}
|
||||
|
||||
// vmStatPages parses vm_stat output for a specific counter
|
||||
func vmStatPages(key string) uint64 {
|
||||
out, err := exec.Command("vm_stat").Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
for _, line := range strings.Split(string(out), "\n") {
|
||||
if strings.HasPrefix(line, key) {
|
||||
// format: "Pages inactive: 479321."
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
s := strings.TrimSpace(parts[1])
|
||||
s = strings.TrimSuffix(s, ".")
|
||||
val, err := strconv.ParseUint(s, 10, 64)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
return val
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
func sysctl64(name string) uint64 {
|
||||
s, err := syscall.Sysctl(name)
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
b := []byte(s)
|
||||
for len(b) < 8 {
|
||||
b = append(b, 0)
|
||||
}
|
||||
return *(*uint64)(unsafe.Pointer(&b[0]))
|
||||
}
|
||||
|
||||
func getCPUUsage() float64 {
|
||||
s, err := syscall.Sysctl("vm.loadavg")
|
||||
if err != nil {
|
||||
return 0
|
||||
}
|
||||
|
||||
raw := []byte(s)
|
||||
for len(raw) < 24 {
|
||||
raw = append(raw, 0)
|
||||
}
|
||||
|
||||
// struct loadavg { fixpt_t ldavg[3]; long fscale; }
|
||||
ldavg0 := *(*uint32)(unsafe.Pointer(&raw[0]))
|
||||
fscale := *(*int64)(unsafe.Pointer(&raw[16]))
|
||||
|
||||
if fscale == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
load1 := float64(ldavg0) / float64(fscale)
|
||||
numCPU := float64(runtime.NumCPU())
|
||||
|
||||
usage := load1 / numCPU * 100
|
||||
if usage > 100 {
|
||||
usage = 100
|
||||
}
|
||||
return usage
|
||||
}
|
||||
Reference in New Issue
Block a user