owpengram-server/internal/hoststats/mem_unix.go
2026-08-07 04:26:56 +03:00

61 lines
1.5 KiB
Go

//go:build !windows
package hoststats
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
// memStats reads host RAM usage from /proc/meminfo. used is derived from
// MemAvailable (kernel's own "usable without swapping" estimate, accounts
// for reclaimable cache/buffers) rather than MemTotal-MemFree, which would
// count page cache as "used" and make a healthy box look starved.
func memStats() (used, total int64, err error) {
f, err := os.Open("/proc/meminfo")
if err != nil {
return 0, 0, err
}
defer f.Close()
var totalKB, availKB int64
haveTotal, haveAvail := false, false
scanner := bufio.NewScanner(f)
for scanner.Scan() {
line := scanner.Text()
switch {
case strings.HasPrefix(line, "MemTotal:"):
totalKB, err = parseMeminfoKB(line)
haveTotal = err == nil
case strings.HasPrefix(line, "MemAvailable:"):
availKB, err = parseMeminfoKB(line)
haveAvail = err == nil
}
if haveTotal && haveAvail {
break
}
}
if scanErr := scanner.Err(); scanErr != nil {
return 0, 0, scanErr
}
if !haveTotal || !haveAvail {
return 0, 0, fmt.Errorf("hoststats: MemTotal/MemAvailable not found in /proc/meminfo")
}
total = totalKB * 1024
used = total - availKB*1024
if used < 0 {
used = 0
}
return used, total, nil
}
func parseMeminfoKB(line string) (int64, error) {
fields := strings.Fields(line)
if len(fields) < 2 {
return 0, fmt.Errorf("hoststats: malformed /proc/meminfo line %q", line)
}
return strconv.ParseInt(fields[1], 10, 64)
}