Files
finally-a-monolithic-linux-…/app/mem/drivers/meminfo.go
T
2026-08-07 09:29:17 -07:00

83 lines
1.6 KiB
Go

package drivers
import (
"bufio"
"fmt"
"os"
"strconv"
"strings"
)
type MemInfoDriver struct{}
func NewMemInfoDriver() (*MemInfoDriver, error) {
r := MemInfoDriver{}
_, err := r.Read()
return &r, err
}
func (r *MemInfoDriver) Render(console *strings.Builder) error {
u, err := r.Read()
if err != nil {
return err
}
usage := u.(MemoryUsage)
fmt.Fprintf(console, "--- Usage ---\n")
fmt.Fprintf(console, "%-16s | %.2f GiB\033[K\n", "Total", usage.TotalGB)
fmt.Fprintf(console, "%-16s | %.2f GiB (%.2f%%) \033[K\n", "Used", usage.UsedGB, usage.UsedPercent)
fmt.Fprintf(console, "%-16s | %.2f GiB\033[K\n", "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
}