123 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			123 lines
		
	
	
		
			2.5 KiB
		
	
	
	
		
			Go
		
	
	
	
| // +build linux
 | |
| 
 | |
| package disk
 | |
| 
 | |
| import (
 | |
| 	"fmt"
 | |
| 	"os/exec"
 | |
| 	"strconv"
 | |
| 	"strings"
 | |
| 
 | |
| 	common "github.com/influxdb/telegraf/plugins/system/ps/common"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	SectorSize = 512
 | |
| )
 | |
| 
 | |
| // 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
 | |
| }
 | |
| 
 | |
| 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 GetDiskSerialNumber(name string) string {
 | |
| 	n := fmt.Sprintf("--name=%s", name)
 | |
| 	out, err := exec.Command("/sbin/udevadm", "info", "--query=property", n).Output()
 | |
| 
 | |
| 	// does not return error, just an empty string
 | |
| 	if err != nil {
 | |
| 		return ""
 | |
| 	}
 | |
| 	lines := strings.Split(string(out), "\n")
 | |
| 	for _, line := range lines {
 | |
| 		values := strings.Split(line, "=")
 | |
| 		if len(values) < 2 || values[0] != "ID_SERIAL" {
 | |
| 			// only get ID_SERIAL, not ID_SERIAL_SHORT
 | |
| 			continue
 | |
| 		}
 | |
| 		return values[1]
 | |
| 	}
 | |
| 	return ""
 | |
| }
 |