host_cpu.go 3.01 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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package resources

import (
	"time"

	"github.com/shirou/gopsutil/cpu"
	"github.com/shirou/gopsutil/load"
)

type HostCPUStatesPct cpu.TimesStat

type HostCPUTimesStatWrap struct {
	CPUTimesStats []cpu.TimesStat
	Ts            int64
}

func GetHostCPUCount() (int, error) {
	return cpu.Counts(true)
}

func GetHostCPULoad() (*load.AvgStat, error) {
	return load.Avg()
}

// GetHostCPUUsage calc now and last call within gopsutil/cpu
func GetHostCPUUsage() (float64, error) {
	return GetHostCPUUsageWithInterval(0)
}

// GetHostCPUUsageWithInterval if d is 0, calc now and last call within gopsutil/cpu.
// if d is not 0, calc two call that need sleep within gopsutil/cpu.
func GetHostCPUUsageWithInterval(d time.Duration) (float64, error) {
	var total float64
	usages, err := cpu.Percent(d, false)
	if err != nil {
		return total, err
	}

	for _, usage := range usages {
		total += usage
	}
	return total, nil
}

func GetHostCPUStatesWithInterval(d time.Duration) ([]HostCPUStatesPct, error) {
	states := make([]HostCPUStatesPct, 0)

	pre, err := cpu.Times(false)
	if err != nil {
		return states, err
	}
	preWrap := HostCPUTimesStatWrap{CPUTimesStats: pre, Ts: time.Now().Unix()}

	time.Sleep(d)

	now, err := cpu.Times(false)
	if err != nil {
		return states, err
	}
	nowWrap := HostCPUTimesStatWrap{CPUTimesStats: now, Ts: time.Now().Unix()}

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

func GetHostCPUStatesWithPre(preWrap *HostCPUTimesStatWrap) (
	[]HostCPUStatesPct, *HostCPUTimesStatWrap, error) {
	states := make([]HostCPUStatesPct, 0)

	now, err := cpu.Times(false)
	if err != nil {
		return states, nil, err
	}
	nowWrap := HostCPUTimesStatWrap{CPUTimesStats: now, Ts: time.Now().Unix()}

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

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

func calculateCPUStates(preWrap, nowWrap *HostCPUTimesStatWrap) []HostCPUStatesPct {
	states := make([]HostCPUStatesPct, 0)

	duration := nowWrap.Ts - preWrap.Ts
	for _, now := range nowWrap.CPUTimesStats {
		state := HostCPUStatesPct{
			CPU: now.CPU,
		}
		for _, pre := range preWrap.CPUTimesStats {
			if pre.CPU == now.CPU {
				state.User = calcPct(pre.User, now.User, float64(duration))
				state.System = calcPct(pre.System, now.System, float64(duration))
				state.Nice = calcPct(pre.Nice, now.Nice, float64(duration))
				state.Idle = calcPct(pre.Idle, now.Idle, float64(duration))
				state.Iowait = calcPct(pre.Iowait, now.Iowait, float64(duration))
				state.Irq = calcPct(pre.Irq, now.Irq, float64(duration))
				state.Softirq = calcPct(pre.Softirq, now.Softirq, float64(duration))
				state.Steal = calcPct(pre.Steal, now.Steal, float64(duration))
				state.Guest = calcPct(pre.Guest, now.Guest, float64(duration))
				state.GuestNice = calcPct(pre.GuestNice, now.GuestNice, float64(duration))
				break
			}
		}
		states = append(states, state)
	}

	return states
}

func calcPct(pre, now, second float64) float64 {
	diff := now - pre
	if diff > 0 && second > 0 {
		return (diff / second) * 100
	}
	return 0
}