func DiskIOCounters() (map[string]DiskIOCountersStat, error) { filename := "/proc/diskstats" lines, err := common.ReadLines(filename) if err != nil { return nil, err } ret := make(map[string]DiskIOCountersStat, 0) empty := DiskIOCountersStat{} for _, line := range lines { fields := strings.Fields(line) name := fields[2] reads, err := strconv.ParseUint((fields[3]), 10, 64) if err != nil { return ret, err } rbytes, err := strconv.ParseUint((fields[5]), 10, 64) if err != nil { return ret, err } rtime, err := strconv.ParseUint((fields[6]), 10, 64) if err != nil { return ret, err } writes, err := strconv.ParseUint((fields[7]), 10, 64) if err != nil { return ret, err } wbytes, err := strconv.ParseUint((fields[9]), 10, 64) if err != nil { return ret, err } wtime, err := strconv.ParseUint((fields[10]), 10, 64) if err != nil { return ret, err } iotime, err := strconv.ParseUint((fields[12]), 10, 64) if err != nil { return ret, err } d := DiskIOCountersStat{ ReadBytes: rbytes * SectorSize, WriteBytes: wbytes * SectorSize, ReadCount: reads, WriteCount: writes, ReadTime: rtime, WriteTime: wtime, IoTime: iotime, } if d == empty { continue } d.Name = name d.SerialNumber = GetDiskSerialNumber(name) ret[name] = d } return ret, nil }
func VirtualMemory() (*VirtualMemoryStat, error) { filename := "/proc/meminfo" lines, _ := common.ReadLines(filename) // flag if MemAvailable is in /proc/meminfo (kernel 3.14+) memavail := false ret := &VirtualMemoryStat{} for _, line := range lines { fields := strings.Split(line, ":") if len(fields) != 2 { continue } key := strings.TrimSpace(fields[0]) value := strings.TrimSpace(fields[1]) value = strings.Replace(value, " kB", "", -1) t, err := strconv.ParseUint(value, 10, 64) if err != nil { return ret, err } switch key { case "MemTotal": ret.Total = t * 1024 case "MemFree": ret.Free = t * 1024 case "MemAvailable": memavail = true ret.Available = t * 1024 case "Buffers": ret.Buffers = t * 1024 case "Cached": ret.Cached = t * 1024 case "Active": ret.Active = t * 1024 case "Inactive": ret.Inactive = t * 1024 } } if !memavail { ret.Available = ret.Free + ret.Buffers + ret.Cached } ret.Used = ret.Total - ret.Free ret.UsedPercent = float64(ret.Total-ret.Available) / float64(ret.Total) * 100.0 return ret, nil }
func SwapMemory() (*SwapMemoryStat, error) { sysinfo := &syscall.Sysinfo_t{} if err := syscall.Sysinfo(sysinfo); err != nil { return nil, err } ret := &SwapMemoryStat{ Total: uint64(sysinfo.Totalswap), Free: uint64(sysinfo.Freeswap), } ret.Used = ret.Total - ret.Free //check Infinity if ret.Total != 0 { ret.UsedPercent = float64(ret.Total-ret.Free) / float64(ret.Total) * 100.0 } else { ret.UsedPercent = 0 } lines, _ := common.ReadLines("/proc/vmstat") for _, l := range lines { fields := strings.Fields(l) if len(fields) < 2 { continue } switch fields[0] { case "pswpin": value, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { continue } ret.Sin = value * 4 * 1024 case "pswpout": value, err := strconv.ParseUint(fields[1], 10, 64) if err != nil { continue } ret.Sout = value * 4 * 1024 } } return ret, nil }
// Get disk partitions. // should use setmntent(3) but this implement use /etc/mtab file func DiskPartitions(all bool) ([]DiskPartitionStat, error) { filename := "/etc/mtab" lines, err := common.ReadLines(filename) if err != nil { return nil, err } ret := make([]DiskPartitionStat, 0, len(lines)) for _, line := range lines { fields := strings.Fields(line) d := DiskPartitionStat{ Device: fields[0], Mountpoint: fields[1], Fstype: fields[2], Opts: fields[3], } ret = append(ret, d) } return ret, nil }