Public source validation / validate (push) Failing after 3m8s
72 lines
1.9 KiB
Go
72 lines
1.9 KiB
Go
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)
|
|
}
|