| package meminfo | |
| import ( | |
| "bufio" | |
| "io" | |
| "os" | |
| "strconv" | |
| "strings" | |
| ) | |
| // readMemInfo retrieves memory statistics of the host system and returns a | |
| // Memory type. | |
| func readMemInfo() (*Memory, error) { | |
| file, err := os.Open("/proc/meminfo") | |
| if err != nil { | |
| return nil, err | |
| } | |
| defer file.Close() | |
| return parseMemInfo(file) | |
| } | |
| // parseMemInfo parses the /proc/meminfo file into | |
| // a Memory object given an io.Reader to the file. | |
| // Throws error if there are problems reading from the file | |
| func parseMemInfo(reader io.Reader) (*Memory, error) { | |
| meminfo := &Memory{} | |
| scanner := bufio.NewScanner(reader) | |
| memAvailable := int64(-1) | |
| for scanner.Scan() { | |
| // Expected format: ["MemTotal:", "1234", "kB"] | |
| parts := strings.Fields(scanner.Text()) | |
| // Sanity checks: Skip malformed entries. | |
| if len(parts) < 3 || parts[2] != "kB" { | |
| continue | |
| } | |
| // Convert to bytes. | |
| size, err := strconv.Atoi(parts[1]) | |
| if err != nil { | |
| continue | |
| } | |
| // Convert to KiB | |
| bytes := int64(size) * 1024 | |
| switch parts[0] { | |
| case "MemTotal:": | |
| meminfo.MemTotal = bytes | |
| case "MemFree:": | |
| meminfo.MemFree = bytes | |
| case "MemAvailable:": | |
| memAvailable = bytes | |
| case "SwapTotal:": | |
| meminfo.SwapTotal = bytes | |
| case "SwapFree:": | |
| meminfo.SwapFree = bytes | |
| } | |
| } | |
| if memAvailable != -1 { | |
| meminfo.MemFree = memAvailable | |
| } | |
| // Handle errors that may have occurred during the reading of the file. | |
| if err := scanner.Err(); err != nil { | |
| return nil, err | |
| } | |
| return meminfo, nil | |
| } |