chore: sync local updates
This commit is contained in:
127
mengyamonitor-backend-client/memory.go
Normal file
127
mengyamonitor-backend-client/memory.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// readMemory 读取内存信息
|
||||
func readMemory() (MemoryMetrics, error) {
|
||||
totals := map[string]uint64{}
|
||||
f, err := os.Open("/proc/meminfo")
|
||||
if err != nil {
|
||||
return MemoryMetrics{}, err
|
||||
}
|
||||
defer f.Close()
|
||||
scanner := bufio.NewScanner(f)
|
||||
for scanner.Scan() {
|
||||
line := scanner.Text()
|
||||
parts := strings.Split(line, ":")
|
||||
if len(parts) < 2 {
|
||||
continue
|
||||
}
|
||||
key := strings.TrimSpace(parts[0])
|
||||
fields := strings.Fields(strings.TrimSpace(parts[1]))
|
||||
if len(fields) == 0 {
|
||||
continue
|
||||
}
|
||||
value, err := strconv.ParseUint(fields[0], 10, 64)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
totals[key] = value * 1024 // kB to bytes
|
||||
}
|
||||
total := totals["MemTotal"]
|
||||
|
||||
// 优先使用 MemAvailable(Linux 3.14+),如果没有则计算
|
||||
var free uint64
|
||||
if available, ok := totals["MemAvailable"]; ok && available > 0 {
|
||||
free = available
|
||||
} else {
|
||||
// 回退到 MemFree + Buffers + Cached(适用于较老的系统)
|
||||
free = totals["MemFree"]
|
||||
if buffers, ok := totals["Buffers"]; ok {
|
||||
free += buffers
|
||||
}
|
||||
if cached, ok := totals["Cached"]; ok {
|
||||
free += cached
|
||||
}
|
||||
}
|
||||
|
||||
used := total - free
|
||||
usedPercent := 0.0
|
||||
if total > 0 {
|
||||
usedPercent = (float64(used) / float64(total)) * 100
|
||||
}
|
||||
|
||||
swapTotal := totals["SwapTotal"]
|
||||
swapFree := totals["SwapFree"]
|
||||
swapUsed := uint64(0)
|
||||
if swapTotal >= swapFree {
|
||||
swapUsed = swapTotal - swapFree
|
||||
}
|
||||
swapUsedPct := 0.0
|
||||
if swapTotal > 0 {
|
||||
swapUsedPct = (float64(swapUsed) / float64(swapTotal)) * 100
|
||||
}
|
||||
swapType := summarizeSwapTypes(swapTotal)
|
||||
|
||||
return MemoryMetrics{
|
||||
TotalBytes: total,
|
||||
UsedBytes: used,
|
||||
FreeBytes: free,
|
||||
UsedPercent: round(usedPercent, 2),
|
||||
SwapTotalBytes: swapTotal,
|
||||
SwapUsedBytes: swapUsed,
|
||||
SwapFreeBytes: swapFree,
|
||||
SwapUsedPercent: round(swapUsedPct, 2),
|
||||
SwapType: swapType,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// summarizeSwapTypes 根据 /proc/swaps 汇总交换区类型(file / partition / zram 等);无 swap 时为「无」
|
||||
func summarizeSwapTypes(swapTotalFromMeminfo uint64) string {
|
||||
if swapTotalFromMeminfo == 0 {
|
||||
return "无"
|
||||
}
|
||||
f, err := os.Open("/proc/swaps")
|
||||
if err != nil {
|
||||
return "未知"
|
||||
}
|
||||
defer f.Close()
|
||||
scanner := bufio.NewScanner(f)
|
||||
lineNum := 0
|
||||
seen := map[string]struct{}{}
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
lineNum++
|
||||
if lineNum == 1 || line == "" {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(line)
|
||||
if len(fields) < 2 {
|
||||
continue
|
||||
}
|
||||
filename := fields[0]
|
||||
typ := fields[1]
|
||||
if strings.Contains(strings.ToLower(filename), "zram") {
|
||||
typ = "zram"
|
||||
}
|
||||
seen[typ] = struct{}{}
|
||||
}
|
||||
if len(seen) == 0 {
|
||||
if swapTotalFromMeminfo > 0 {
|
||||
return "未知"
|
||||
}
|
||||
return "无"
|
||||
}
|
||||
list := make([]string, 0, len(seen))
|
||||
for t := range seen {
|
||||
list = append(list, t)
|
||||
}
|
||||
sort.Strings(list)
|
||||
return strings.Join(list, " + ")
|
||||
}
|
||||
Reference in New Issue
Block a user