// MemoryUsage - XXX func MemoryUsage() MemoryStruct { mem, _ := psmem.VirtualMemory() swap, _ := psmem.SwapMemory() TotalMB, _ := util.ConvertBytesTo(mem.Total, "mb", 0) FreeMB, _ := util.ConvertBytesTo(mem.Free, "mb", 0) UsedMB, _ := util.ConvertBytesTo(mem.Used, "mb", 0) UsedPercent, _ := util.FloatDecimalPoint(mem.UsedPercent, 0) SwapUsedMB, _ := util.ConvertBytesTo(swap.Used, "mb", 0) SwapTotalMB, _ := util.ConvertBytesTo(swap.Total, "mb", 0) SwapFreeMB, _ := util.ConvertBytesTo(swap.Free, "mb", 0) SwapUsedPercent, _ := util.FloatDecimalPoint(swap.UsedPercent, 0) m := MemoryStruct{ UsedMB: UsedMB, TotalMB: TotalMB, FreeMB: FreeMB, UsedPercent: UsedPercent, SwapUsedMB: SwapUsedMB, SwapTotalMB: SwapTotalMB, SwapFreeMB: SwapFreeMB, SwapUsedPercent: SwapUsedPercent, } return m }
// CPUUsage - return a map with CPU usage stats func CPUUsage() CPUUsageStruct { c1, _ := exec.Command("sar", "1", "1").Output() sarOutput := string(c1) sarLines := strings.Split(sarOutput, "\n") header := []string{} values := []float64{} result := make(map[string]float64) // Get the header for _, line := range sarLines { // Replace the regex with something faster matches := headerRE.FindAllStringSubmatch(line, -1) for _, m := range matches { if len(m) == 2 { result := strings.Replace(m[0], "%", "", -1) // replace % in idle (%idle) result = strings.Trim(result, " ") // remove white space header = append(header, result) } } } // Get values for _, line := range sarLines { if strings.Contains(line, "Average") { matches := valueRE.FindAllStringSubmatch(line, -1) for _, m := range matches { if len(m) == 1 { valueFloat, _ := strconv.ParseFloat(m[0], 64) valueDecimal, _ := util.FloatDecimalPoint(valueFloat, 2) values = append(values, valueDecimal) } } } } if len(header) == len(values) { for i := range header { result[header[i]] = values[i] } } c := CPUUsageStruct{ User: result["user"], Idle: result["idle"], Nice: result["nice"], Steal: result["steal"], System: result["system"], IOWait: result["iowait"], } return c }
// DiskUsage - return a list with disk usage structs func DiskUsage() (DiskUsageList, error) { parts, err := disk.DiskPartitions(false) if err != nil { diskLogger.Errorf("Error getting disk usage info: %v", err) } var usage DiskUsageList for _, p := range parts { if _, err := os.Stat(p.Mountpoint); err == nil { du, err := disk.DiskUsage(p.Mountpoint) if err != nil { diskLogger.Errorf("Error getting disk usage for Mount: %v", err) } if !isPseudoFS(du.Fstype) && !removableFs(du.Path) { TotalMB, _ := util.ConvertBytesTo(du.Total, "mb", 0) FreeMB, _ := util.ConvertBytesTo(du.Free, "mb", 0) UsedMB, _ := util.ConvertBytesTo(du.Used, "mb", 0) UsedPercent := 0.0 if TotalMB > 0 && UsedMB > 0 { UsedPercent = (float64(du.Used) / float64(du.Total)) * 100.0 UsedPercent, _ = util.FloatDecimalPoint(UsedPercent, 2) DeviceName := strings.Replace(p.Device, "/dev/", "", -1) TotalMBFormatted, _ := util.FloatToString(TotalMB) FreeMBFormatted, _ := util.FloatToString(FreeMB) UsedMBFormatted, _ := util.FloatToString(UsedMB) d := DiskUsageStruct{ Name: DeviceName, Path: du.Path, Fstype: du.Fstype, Total: TotalMBFormatted, Free: FreeMBFormatted, Used: UsedMBFormatted, UsedPercent: UsedPercent, } usage = append(usage, d) } } } } return usage, err }
// Processes - get data from sysstat, format and return the result func Processes() (ProcessesList, error) { c1, _ := exec.Command("pidstat", "-ruhtd").Output() var ps ProcessesList v, _ := mem.VirtualMemory() memoryTotalMB, _ := util.ConvertBytesTo(float64(v.Total), "mb", 0) // Find header and ignore headerRegex, _ := regexp.Compile("d+") pidstatOutput := string(c1) pidstatLines := strings.Split(pidstatOutput, "\n") // Helper // Time(0) UID(1) TGID(2) TID(3) // %usr{4} %system{5} %guest{6} %CPU{7} CPU{8} // minflt/s{9} majflt/s{10} VSZ{11} RSS{12} // %MEM{13} kB_rd/s{14} kB_wr/s{15} kB_ccwr/s{16} Command{17} var headerData []string for _, processLine := range pidstatLines { // Get the header if strings.Contains(processLine, "%CPU") || strings.Contains(processLine, "%Command") { headerData = strings.Fields(processLine) if len(headerData) > 0 { // remove the first column, if it has the # sign if headerData[0] == "#" { headerData = append(headerData[:0], headerData[0+1:]...) } } break } } for _, processLine := range pidstatLines { if len(headerRegex.FindString(processLine)) == 0 { processData := strings.Fields(processLine) if len(processData) == len(headerData) { masterthreadIDIndex := SliceFindStringIndex(headerData, "TID") if masterthreadIDIndex != -1 { masterthreadID := processData[masterthreadIDIndex] masterthreadIDtoINT, _ := strconv.Atoi(masterthreadID) // It is a master thread, proceed with the actual data if masterthreadIDtoINT == 0 { CPUIndex := SliceFindStringIndex(headerData, "%CPU") MEMIndex := SliceFindStringIndex(headerData, "%MEM") if CPUIndex != -1 && MEMIndex != -1 { cpuPercent := processData[CPUIndex] cpuPercenttoINT, _ := strconv.ParseFloat(cpuPercent, 64) memPercent := processData[MEMIndex] memPercenttoINT, _ := strconv.ParseFloat(memPercent, 64) var processMemoryMB, _ = util.FloatDecimalPoint(memoryTotalMB/100*memPercenttoINT, 2) ReadKBIndex := SliceFindStringIndex(headerData, "kB_rd/s") WriteKBIndex := SliceFindStringIndex(headerData, "kB_wr/s") var ReadKBytes = 0.0 var WriteKBytes = 0.0 if ReadKBIndex != -1 && WriteKBIndex != -1 { ReadPerSecond := processData[ReadKBIndex] ReadKBytes, _ = strconv.ParseFloat(ReadPerSecond, 64) WritePerSecond := processData[WriteKBIndex] WriteKBytes, _ = strconv.ParseFloat(WritePerSecond, 64) if ReadKBytes == -1.0 && WriteKBytes == -1.0 { ReadKBytes = 0.0 WriteKBytes = 0.0 } } processNameIndex := SliceFindStringIndex(headerData, "command") // Everything is find up to this point, append if processNameIndex != -1 { processName := processData[processNameIndex] formattedprocessMemoryMB, _ := util.FloatToString(processMemoryMB) c := ProcessStruct{ CPU: cpuPercenttoINT, Memory: formattedprocessMemoryMB, Name: processName, KBRead: ReadKBytes, KBWrite: WriteKBytes, } ps = append(ps, c) } } else { processLogger.Info("Can't find mem/cpu data") } } } } //fmt.Print(headerData) } } return ps, nil }