Files
kandev/apps/backend/internal/system/metrics/collector_windows.go
T
2026-06-15 18:54:16 +01:00

77 lines
2.2 KiB
Go

//go:build windows
package metrics
import (
"errors"
"fmt"
"unsafe"
"golang.org/x/sys/windows"
)
var (
kernel32 = windows.NewLazySystemDLL("kernel32.dll")
procGetSystemTimes = kernel32.NewProc("GetSystemTimes")
procGlobalMemoryStatusEx = kernel32.NewProc("GlobalMemoryStatusEx")
)
// memoryStatusEx mirrors MEMORYSTATUSEX from windows.h. The first field is the
// struct length in bytes and must be set by the caller before invoking
// GlobalMemoryStatusEx.
type memoryStatusEx struct {
Length uint32
MemoryLoad uint32
TotalPhys uint64
AvailPhys uint64
TotalPageFile uint64
AvailPageFile uint64
TotalVirtual uint64
AvailVirtual uint64
AvailExtendedVirtual uint64
}
// readCPUTimes uses GetSystemTimes. On Windows kernelTime includes idleTime,
// so total non-idle = (kernel + user) - idle and we return total = kernel + user.
func readCPUTimes(_ *Collector) (cpuTimes, error) {
var idle, kernel, user windows.Filetime
r1, _, e := procGetSystemTimes.Call(
uintptr(unsafe.Pointer(&idle)),
uintptr(unsafe.Pointer(&kernel)),
uintptr(unsafe.Pointer(&user)),
)
if r1 == 0 {
return cpuTimes{}, fmt.Errorf("GetSystemTimes: %w", e)
}
return cpuTimes{
total: filetimeToUint64(kernel) + filetimeToUint64(user),
idle: filetimeToUint64(idle),
}, nil
}
func filetimeToUint64(ft windows.Filetime) uint64 {
return (uint64(ft.HighDateTime) << 32) | uint64(ft.LowDateTime)
}
func (c *Collector) memoryPercent() (float64, error) {
var status memoryStatusEx
status.Length = uint32(unsafe.Sizeof(status))
r1, _, e := procGlobalMemoryStatusEx.Call(uintptr(unsafe.Pointer(&status)))
if r1 == 0 {
return 0, fmt.Errorf("GlobalMemoryStatusEx: %w", e)
}
if status.TotalPhys == 0 {
return 0, errors.New("total physical memory is zero")
}
used := status.TotalPhys - status.AvailPhys
return float64(used) / float64(status.TotalPhys) * 100, nil
}
func (c *Collector) cpuTempValue() (float64, error) {
return 0, errors.New("cpu temperature unavailable on windows")
}
func (c *Collector) ioLoadValue() (float64, error) {
return 0, errors.New("load average unavailable on windows")
}