Files
finally-a-monolithic-linux-…/app/mem/drivers/meminfo.go
T
2026-08-07 14:49:21 -07:00

84 lines
1.6 KiB
Go

package drivers
import (
"bufio"
"finally-a-monolithic-linux-hw-monitor/app/common"
"fmt"
"os"
"strconv"
"strings"
)
type MemInfoDriver struct{}
func NewMemInfoDriver() (*MemInfoDriver, error) {
r := MemInfoDriver{}
_, err := r.Read()
return &r, err
}
func (r *MemInfoDriver) Render(term common.Terminal) error {
u, err := r.Read()
if err != nil {
return err
}
usage := u.(MemoryUsage)
term.Subheader("Usage")
term.Print(fmt.Sprintf("%-16s | %.2f GiB", "Total", usage.TotalGB))
term.Print(fmt.Sprintf("%-16s | %.2f GiB (%.2f%%)", "Used", usage.UsedGB, usage.UsedPercent))
term.Print(fmt.Sprintf("%-16s | %.2f GiB", "Avail", usage.AvailableGB))
return nil
}
// Read /proc/meminfo for active system memory statistics
func (r *MemInfoDriver) Read() (any, error) {
usage := MemoryUsage{}
file, err := os.Open("/proc/meminfo")
if err != nil {
return usage, err
}
defer file.Close()
var memTotal, memAvailable float64
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
fields := strings.Fields(line)
if len(fields) < 2 {
continue
}
val, err := strconv.ParseFloat(fields[1], 64)
if err != nil {
continue
}
switch fields[0] {
case "MemTotal:":
memTotal = val // stored in kB
case "MemAvailable:":
memAvailable = val // stored in kB
}
}
if err := scanner.Err(); err != nil {
return usage, err
}
used := memTotal - memAvailable
usedPct := (used / memTotal) * 100
usage = MemoryUsage{
TotalGB: memTotal / (1024 * 1024),
AvailableGB: memAvailable / (1024 * 1024),
UsedGB: used / (1024 * 1024),
UsedPercent: usedPct,
}
return usage, nil
}