Testing for linux cpuinfo

This commit is contained in:
lin committed 2026-10-05 18:19:36 +02:00
1 parent cbc9e4a0b4
commit ea5e79a46a
8 files changed
+172 -20

No files matched your search

+11 -2
View File
@@ -4,14 +4,15 @@ import (
"log"
"rpi5-health/internal/cli"
"rpi5-health/internal/http_internal"
"rpi5-health/internal/system_check"
"rpi5-health/internal/memory"
"rpi5-health/internal/processor"
)
func main() {
srv := http_internal.NewAppServer()
go srv.Start()
memInfo, _ := system_check.GetRamInformation()
memInfo, _ := memory.GetRamInformation()
const GB = 1024 * 1024 * 1024
@@ -19,5 +20,13 @@ func main() {
log.Printf("Available memory: %.2fGB\n", float64(memInfo.AvailableMemory)/GB)
log.Printf("Used memory: %.2fGB\n", float64(memInfo.GetUsedMemory())/GB)
_, kernel, usage, idle := processor.GetCPUInformation().Usage()
const HOUR = 60 * 60
log.Printf("Total time spent idling: %.2f%%\n", idle)
log.Printf("Total time spent in kernel mode: %.2f%%\n", kernel)
log.Printf("Total time spent in user mode: %.2f%%\n", usage)
cli.Listen()
}
@@ -1,6 +1,6 @@
//go:build linux
package system_check
package memory
import (
"bufio"
@@ -1,4 +1,4 @@
package system_check
package memory
type MemoryInformation struct {
/*
@@ -1,29 +1,34 @@
//go:build windows
package system_check
package memory
import (
"log"
"unsafe"
"rpi5-health/internal/windows_system"
"golang.org/x/sys/windows"
)
type DWORD uint32
type DWORDLONG uint64
type memoryStatusEx struct {
/*
* Struct for storing memory status information.
*
* It gets populated via syscall.
*/
dwLength uint32
dwMemoryLoad uint32
ullTotalPhys uint64
ullAvailPhys uint64
ullTotalPageFile uint64
ullAvailPageFile uint64
ullTotalVirtual uint64
ullAvailVirtual uint64
ullAvailExtendedVirtual uint64
dwLength DWORD
dwMemoryLoad DWORD
ullTotalPhys DWORDLONG
ullAvailPhys DWORDLONG
ullTotalPageFile DWORDLONG
ullAvailPageFile DWORDLONG
ullTotalVirtual DWORDLONG
ullAvailVirtual DWORDLONG
ullAvailExtendedVirtual DWORDLONG
}
func getWinRamInfo(procGlobalMemoryStatusEx *windows.LazyProc) MemoryInformation {
@@ -31,7 +36,7 @@ func getWinRamInfo(procGlobalMemoryStatusEx *windows.LazyProc) MemoryInformation
// * Windows requires the dwLength field to be set to the struct's size
// * before execution so it knows which OS struct version is being used.
mem.dwLength = uint32(unsafe.Sizeof(mem))
mem.dwLength = DWORD(unsafe.Sizeof(mem))
ret, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&mem))) // exec syscall
@@ -40,11 +45,11 @@ func getWinRamInfo(procGlobalMemoryStatusEx *windows.LazyProc) MemoryInformation
}
return MemoryInformation{
SystemMemory: mem.ullTotalPhys,
AvailableMemory: mem.ullAvailPhys,
SystemMemory: uint64(mem.ullTotalPhys),
AvailableMemory: uint64(mem.ullAvailPhys),
}
}
func GetRamInformation() (MemoryInformation, error) {
return getWinRamInfo(getWindowsTools().ProcGlobalMemoryStatusEx), nil
return getWinRamInfo(windows_system.GetWindowsTools().ProcGlobalMemoryStatusEx), nil
}
+34
View File
@@ -0,0 +1,34 @@
package processor
import "time"
type ProcessorInformation struct {
IdleTimeSinceBoot uint64
KernelTimeSinceBoot uint64
UserTimeSinceBoot uint64
}
func (procInfo ProcessorInformation) Usage() (
TotalCPUUsage float64,
KernelCPUUsage float64,
UserCPUUsage float64,
IdleCPUUsage float64,
) {
first := GetCPUInformation()
time.Sleep(time.Second)
second := GetCPUInformation()
deltaIdleTime := second.IdleTimeSinceBoot - first.IdleTimeSinceBoot
deltaKernelTime := second.KernelTimeSinceBoot - first.KernelTimeSinceBoot
deltaUserTime := second.UserTimeSinceBoot - first.UserTimeSinceBoot
deltaTotalTime := deltaIdleTime + deltaKernelTime + deltaUserTime
if deltaTotalTime > 0 {
TotalCPUUsage = ((float64(deltaKernelTime) + float64(deltaUserTime)) / float64(deltaTotalTime)) * 100
UserCPUUsage = (float64(deltaUserTime) / float64(deltaTotalTime)) * 100
KernelCPUUsage = (float64(deltaKernelTime) / float64(deltaTotalTime)) * 100
IdleCPUUsage = (float64(deltaIdleTime) / float64(deltaTotalTime)) * 100
}
return TotalCPUUsage, KernelCPUUsage, UserCPUUsage, IdleCPUUsage
}
+50
View File
@@ -0,0 +1,50 @@
//go:build linux
package processor
import (
"bufio"
"fmt"
"log"
"os"
"regexp"
"strings"
)
var numberRegex *regexp.Regexp = regexp.MustCompile(`\d+`)
func getLinuxCpuInfo() (ProcessorInformation, error) {
procFile, err := os.Open("/proc/meminfo")
if err != nil {
return ProcessorInformation{}, fmt.Errorf("Could not find /proc/meminfo. Are you sure you are on linux?")
}
defer procFile.Close()
fileReader := bufio.NewScanner(procFile)
//var idleTime uint64
//var kernelTime uint64
//var userTime uint64
for fileReader.Scan() {
line := fileReader.Text()
if strings.HasPrefix(line, "cpu ") {
fields := strings.Split(line, " ")
for _, field := range fields {
fmt.Print(field)
}
}
}
return ProcessorInformation{}, nil
}
func GetCPUInformation() ProcessorInformation {
info, err := getLinuxCpuInfo()
if err != nil {
log.Printf("Could not read processor info. Error: %v", err)
return ProcessorInformation{}
}
return info
}
+48
View File
@@ -0,0 +1,48 @@
//go:build windows
package processor
import (
"rpi5-health/internal/windows_system"
"unsafe"
"golang.org/x/sys/windows"
)
type DWORD uint32
type PFILETIME struct {
dwLowDateTime DWORD
dwHighDateTime DWORD
}
func getWinCpuInfo(getSystemTimes *windows.LazyProc) ProcessorInformation {
var lpIdleTime PFILETIME
var lpKernelTime PFILETIME
var lpUserTime PFILETIME
getSystemTimes.Call(
uintptr(unsafe.Pointer(&lpIdleTime)),
uintptr(unsafe.Pointer(&lpKernelTime)),
uintptr(unsafe.Pointer(&lpUserTime)),
)
timeSpentIdlingTicks := fileTimeToTicks(lpIdleTime)
timeSpentByKernelTicks := fileTimeToTicks(lpKernelTime) - timeSpentIdlingTicks // kernel time includes idling by default
timeSpentByUserTicks := fileTimeToTicks(lpUserTime)
return ProcessorInformation{
IdleTimeSinceBoot: timeSpentIdlingTicks,
KernelTimeSinceBoot: timeSpentByKernelTicks,
UserTimeSinceBoot: timeSpentByUserTicks,
}
}
func fileTimeToTicks(filetime PFILETIME) uint64 {
// 100 nanosecond intervals since 1601, january 1
return (uint64(filetime.dwHighDateTime) << 32) | uint64(filetime.dwLowDateTime)
}
func GetCPUInformation() ProcessorInformation {
return getWinCpuInfo(windows_system.GetWindowsTools().SystemTimes)
}
@@ -1,6 +1,6 @@
//go:build windows
package system_check
package windows_system
import (
"sync"
@@ -17,14 +17,20 @@ type WindowsSystemCheckTools struct {
* Windows memory information
*/
ProcGlobalMemoryStatusEx *windows.LazyProc
/*
* Windows processor information
*/
SystemTimes *windows.LazyProc
}
func getWindowsTools() WindowsSystemCheckTools {
func GetWindowsTools() WindowsSystemCheckTools {
kernel32 := sync.OnceValue(func() *windows.LazyDLL { return windows.NewLazySystemDLL("kernel32.dll") })
procGlobalMemoryStatusEx := sync.OnceValue(func() *windows.LazyProc { return kernel32().NewProc("GlobalMemoryStatusEx") })
systemTimes := sync.OnceValue(func() *windows.LazyProc { return kernel32().NewProc("GetSystemTimes") })
return WindowsSystemCheckTools{
Kernel32: kernel32(),
ProcGlobalMemoryStatusEx: procGlobalMemoryStatusEx(),
SystemTimes: systemTimes(),
}
}