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" "log"
"rpi5-health/internal/cli" "rpi5-health/internal/cli"
"rpi5-health/internal/http_internal" "rpi5-health/internal/http_internal"
"rpi5-health/internal/system_check" "rpi5-health/internal/memory"
"rpi5-health/internal/processor"
) )
func main() { func main() {
srv := http_internal.NewAppServer() srv := http_internal.NewAppServer()
go srv.Start() go srv.Start()
memInfo, _ := system_check.GetRamInformation() memInfo, _ := memory.GetRamInformation()
const GB = 1024 * 1024 * 1024 const GB = 1024 * 1024 * 1024
@@ -19,5 +20,13 @@ func main() {
log.Printf("Available memory: %.2fGB\n", float64(memInfo.AvailableMemory)/GB) log.Printf("Available memory: %.2fGB\n", float64(memInfo.AvailableMemory)/GB)
log.Printf("Used memory: %.2fGB\n", float64(memInfo.GetUsedMemory())/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() cli.Listen()
} }
@@ -1,6 +1,6 @@
//go:build linux //go:build linux
package system_check package memory
import ( import (
"bufio" "bufio"
@@ -1,4 +1,4 @@
package system_check package memory
type MemoryInformation struct { type MemoryInformation struct {
/* /*
@@ -1,29 +1,34 @@
//go:build windows //go:build windows
package system_check package memory
import ( import (
"log" "log"
"unsafe" "unsafe"
"rpi5-health/internal/windows_system"
"golang.org/x/sys/windows" "golang.org/x/sys/windows"
) )
type DWORD uint32
type DWORDLONG uint64
type memoryStatusEx struct { type memoryStatusEx struct {
/* /*
* Struct for storing memory status information. * Struct for storing memory status information.
* *
* It gets populated via syscall. * It gets populated via syscall.
*/ */
dwLength uint32 dwLength DWORD
dwMemoryLoad uint32 dwMemoryLoad DWORD
ullTotalPhys uint64 ullTotalPhys DWORDLONG
ullAvailPhys uint64 ullAvailPhys DWORDLONG
ullTotalPageFile uint64 ullTotalPageFile DWORDLONG
ullAvailPageFile uint64 ullAvailPageFile DWORDLONG
ullTotalVirtual uint64 ullTotalVirtual DWORDLONG
ullAvailVirtual uint64 ullAvailVirtual DWORDLONG
ullAvailExtendedVirtual uint64 ullAvailExtendedVirtual DWORDLONG
} }
func getWinRamInfo(procGlobalMemoryStatusEx *windows.LazyProc) MemoryInformation { 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 // * 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. // * 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 ret, _, err := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&mem))) // exec syscall
@@ -40,11 +45,11 @@ func getWinRamInfo(procGlobalMemoryStatusEx *windows.LazyProc) MemoryInformation
} }
return MemoryInformation{ return MemoryInformation{
SystemMemory: mem.ullTotalPhys, SystemMemory: uint64(mem.ullTotalPhys),
AvailableMemory: mem.ullAvailPhys, AvailableMemory: uint64(mem.ullAvailPhys),
} }
} }
func GetRamInformation() (MemoryInformation, error) { 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 //go:build windows
package system_check package windows_system
import ( import (
"sync" "sync"
@@ -17,14 +17,20 @@ type WindowsSystemCheckTools struct {
* Windows memory information * Windows memory information
*/ */
ProcGlobalMemoryStatusEx *windows.LazyProc 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") }) kernel32 := sync.OnceValue(func() *windows.LazyDLL { return windows.NewLazySystemDLL("kernel32.dll") })
procGlobalMemoryStatusEx := sync.OnceValue(func() *windows.LazyProc { return kernel32().NewProc("GlobalMemoryStatusEx") }) procGlobalMemoryStatusEx := sync.OnceValue(func() *windows.LazyProc { return kernel32().NewProc("GlobalMemoryStatusEx") })
systemTimes := sync.OnceValue(func() *windows.LazyProc { return kernel32().NewProc("GetSystemTimes") })
return WindowsSystemCheckTools{ return WindowsSystemCheckTools{
Kernel32: kernel32(), Kernel32: kernel32(),
ProcGlobalMemoryStatusEx: procGlobalMemoryStatusEx(), ProcGlobalMemoryStatusEx: procGlobalMemoryStatusEx(),
SystemTimes: systemTimes(),
} }
} }