113 lines
2.5 KiB
Go
113 lines
2.5 KiB
Go
package stat
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
"git.loafle.net/overflow/ssh_crawler/util"
|
|
"strconv"
|
|
)
|
|
|
|
type DiskIOStat struct {
|
|
Device,
|
|
ReadCompleted,
|
|
ReadMerged,
|
|
SectorRead,
|
|
TimeSpentReading,
|
|
WritesCompleted,
|
|
WritesMerged,
|
|
SectorsWritten,
|
|
TimeSpentWriting,
|
|
IoInProg,
|
|
TimeSpentIO,
|
|
WeightedTimeSpentIO string
|
|
}
|
|
|
|
func (diskio DiskIOStat) Command() string {
|
|
return "cat /proc/diskstats"
|
|
}
|
|
|
|
func (diskio DiskIOStat) Read(r io.Reader, keys []string) (interface{}, error) {
|
|
var (
|
|
stats = []DiskIOStat{}
|
|
scanner = bufio.NewScanner(r)
|
|
)
|
|
|
|
for scanner.Scan() {
|
|
parts := strings.Fields(scanner.Text())
|
|
if len(parts) < 4 {
|
|
return nil, fmt.Errorf("invalid line in %s: %s", "/proc/diskstats", scanner.Text())
|
|
}
|
|
deviceName := parts[2]
|
|
if !strings.HasPrefix(deviceName, "sd") {
|
|
continue
|
|
}
|
|
stats = append(stats, DiskIOStat{
|
|
Device: deviceName,
|
|
ReadCompleted: parts[3],
|
|
ReadMerged: parts[4],
|
|
SectorRead: parts[5],
|
|
TimeSpentReading: parts[6],
|
|
WritesCompleted: parts[7],
|
|
WritesMerged: parts[8],
|
|
SectorsWritten: parts[9],
|
|
TimeSpentWriting: parts[10],
|
|
IoInProg: parts[11],
|
|
TimeSpentIO: parts[12],
|
|
WeightedTimeSpentIO: parts[13],
|
|
})
|
|
}
|
|
|
|
if keys == nil {
|
|
return &stats, nil
|
|
}
|
|
|
|
res, err :=diskio.parse(keys, stats)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
|
|
return &res, scanner.Err()
|
|
}
|
|
|
|
func (diskio DiskIOStat) parse(keys []string, data []DiskIOStat) (map[string]string, error) {
|
|
resMap := make(map[string]string)
|
|
|
|
for _, key := range keys {
|
|
t := strings.Split(key, ".")
|
|
suffix := t[len(t)-1]
|
|
ext := util.ExtractInBracket(key)
|
|
idx, _ := strconv.Atoi(ext)
|
|
switch suffix {
|
|
case "device":
|
|
resMap[key] = data[idx].Device
|
|
case "readcnt":
|
|
resMap[key] = data[idx].ReadCompleted
|
|
case "merged_readcnt":
|
|
resMap[key] = data[idx].ReadMerged
|
|
case "readbytes":
|
|
resMap[key] = util.Float64ToString(util.StringToFloat64(data[idx].SectorRead) * 512)
|
|
case "readtime":
|
|
resMap[key] = data[idx].TimeSpentReading
|
|
case "writecnt":
|
|
resMap[key] = data[idx].WritesCompleted
|
|
case "merged_writecnt":
|
|
resMap[key] = data[idx].WritesMerged
|
|
case "writebytes":
|
|
resMap[key] = util.Float64ToString(util.StringToFloat64(data[idx].SectorsWritten) * 512)
|
|
case "writetime":
|
|
resMap[key] = data[idx].TimeSpentWriting
|
|
case "iotime":
|
|
resMap[key] = data[idx].TimeSpentIO
|
|
case "ioweighted":
|
|
resMap[key] = data[idx].WeightedTimeSpentIO
|
|
default:
|
|
|
|
}
|
|
}
|
|
|
|
return resMap, nil
|
|
}
|