This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
package hostcollect
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/itworx/pulse/internal/host"
|
||||
)
|
||||
|
||||
// parseMeminfo converts /proc/meminfo into bytes.
|
||||
//
|
||||
// meminfo is kB based ("MemTotal: 16316420 kB"), where kB means KiB, and a handful of
|
||||
// counters carry no unit at all. Treating either as bytes is the classic off-by-1024
|
||||
// bug, so the unit is read per line instead of assumed.
|
||||
func parseMeminfo(data []byte) (host.RawMemory, error) {
|
||||
values := make(map[string]uint64, 8)
|
||||
for _, line := range lines(data) {
|
||||
key, rest, found := strings.Cut(line, ":")
|
||||
if !found {
|
||||
continue
|
||||
}
|
||||
fields := strings.Fields(rest)
|
||||
if len(fields) == 0 {
|
||||
continue
|
||||
}
|
||||
amount, ok := parseUint(fields[0])
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
if len(fields) > 1 && strings.EqualFold(fields[1], "kB") {
|
||||
const kib = 1024
|
||||
if amount > (1<<64-1)/kib {
|
||||
continue
|
||||
}
|
||||
amount *= kib
|
||||
}
|
||||
values[strings.TrimSpace(key)] = amount
|
||||
}
|
||||
total := values["MemTotal"]
|
||||
if total == 0 {
|
||||
return host.RawMemory{}, errNoMemTotal
|
||||
}
|
||||
available, ok := values["MemAvailable"]
|
||||
if !ok {
|
||||
// Kernels before 3.14 have no MemAvailable. The traditional approximation is
|
||||
// free plus the reclaimable page cache; it is an estimate, never above total.
|
||||
available = values["MemFree"] + values["Buffers"] + values["Cached"] + values["SReclaimable"]
|
||||
}
|
||||
if available > total {
|
||||
available = total
|
||||
}
|
||||
memory := host.RawMemory{TotalBytes: total, AvailableBytes: available}
|
||||
swapTotal := values["SwapTotal"]
|
||||
if swapTotal > 0 {
|
||||
swapFree := values["SwapFree"]
|
||||
if swapFree > swapTotal {
|
||||
swapFree = swapTotal
|
||||
}
|
||||
memory.SwapTotalBytes = swapTotal
|
||||
memory.SwapUsedBytes = swapTotal - swapFree
|
||||
}
|
||||
return memory, nil
|
||||
}
|
||||
|
||||
func (c *Collector) memory() (host.RawMemory, error) {
|
||||
data, err := readLimited(c.procPath("meminfo"), maxFileBytes)
|
||||
if err != nil {
|
||||
return host.RawMemory{}, fmt.Errorf("hostcollect: read meminfo: %w", err)
|
||||
}
|
||||
return parseMeminfo(data)
|
||||
}
|
||||
Reference in New Issue
Block a user