host_disk_io.go 2.24 KB
Newer Older
Lei Li's avatar
Lei Li committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
package resources

import (
	"sort"
	"time"

	"github.com/shirou/gopsutil/disk"
)

type HostDiskIOUsage struct {
	Device     string
	ReadBytes  uint64
	WriteBytes uint64
	ReadUsage  uint64
	WriteUsage uint64
}

type HostDiskIOUsageList []HostDiskIOUsage

func (e HostDiskIOUsageList) Len() int {
	return len(e)
}

func (e HostDiskIOUsageList) Less(i, j int) bool {
	return e[i].Device < e[j].Device
}

func (e HostDiskIOUsageList) Swap(i, j int) {
	e[i], e[j] = e[j], e[i]
}

type HostDiskIOCountersStatWrap struct {
	IOStat map[string]disk.IOCountersStat
	Ts     int64
}

func GetHostDiskIOUsageWithInterval(d time.Duration) ([]HostDiskIOUsage, error) {
	usages := make([]HostDiskIOUsage, 0)

	pre, err := disk.IOCounters()
	if err != nil {
		return usages, err
	}
	preWrap := HostDiskIOCountersStatWrap{IOStat: pre, Ts: time.Now().Unix()}

	time.Sleep(d)

	now, err := disk.IOCounters()
	if err != nil {
		return usages, err
	}
	nowWrap := HostDiskIOCountersStatWrap{IOStat: now, Ts: time.Now().Unix()}

	return calculateDiskIOUsage(&preWrap, &nowWrap), nil
}

func GetHostDiskIOUsageWithPre(preWrap *HostDiskIOCountersStatWrap) (
	[]HostDiskIOUsage, *HostDiskIOCountersStatWrap, error) {
	usages := make([]HostDiskIOUsage, 0)

	now, err := disk.IOCounters()
	if err != nil {
		return usages, nil, err
	}
	nowWrap := HostDiskIOCountersStatWrap{IOStat: now, Ts: time.Now().Unix()}

	if preWrap == nil {
		return calculateDiskIOUsage(&nowWrap, &nowWrap), &nowWrap, nil
	}

	return calculateDiskIOUsage(preWrap, &nowWrap), &nowWrap, nil
}

func calculateDiskIOUsage(preWrap, nowWrap *HostDiskIOCountersStatWrap) []HostDiskIOUsage {
	usages := make([]HostDiskIOUsage, 0)

	duration := nowWrap.Ts - preWrap.Ts
	for dev, nowStat := range nowWrap.IOStat {
		usage := HostDiskIOUsage{
			Device:     dev,
			ReadBytes:  nowStat.ReadBytes,
			WriteBytes: nowStat.WriteBytes,
		}

		if preStat, ok := preWrap.IOStat[dev]; ok {
			rdiff := (nowStat.ReadBytes - preStat.ReadBytes)
			if rdiff > 0 && duration > 0 {
				usage.ReadUsage = rdiff / uint64(duration)
			}

			wdiff := (nowStat.WriteBytes - preStat.WriteBytes)
			if wdiff > 0 && duration > 0 {
				usage.WriteUsage = wdiff / uint64(duration)
			}
		}

		usages = append(usages, usage)
	}

	sort.Sort(HostDiskIOUsageList(usages))
	return usages
}