2016-05-19 20:32:03 +00:00
|
|
|
package stats
|
|
|
|
|
|
|
|
import (
|
2016-05-20 09:05:48 +00:00
|
|
|
"runtime"
|
|
|
|
"time"
|
2016-06-10 14:42:42 +00:00
|
|
|
|
2016-06-10 21:14:33 +00:00
|
|
|
shelpers "github.com/hashicorp/nomad/helper/stats"
|
2021-03-30 18:47:33 +00:00
|
|
|
"github.com/shirou/gopsutil/v3/cpu"
|
2016-05-19 20:32:03 +00:00
|
|
|
)
|
|
|
|
|
2016-05-20 18:38:15 +00:00
|
|
|
// CpuStats calculates cpu usage percentage
|
2016-05-19 20:32:03 +00:00
|
|
|
type CpuStats struct {
|
2016-06-10 17:38:29 +00:00
|
|
|
prevCpuTime float64
|
|
|
|
prevTime time.Time
|
2016-05-19 20:32:03 +00:00
|
|
|
|
|
|
|
totalCpus int
|
|
|
|
}
|
|
|
|
|
2016-05-20 18:38:15 +00:00
|
|
|
// NewCpuStats returns a cpu stats calculator
|
2016-05-21 06:16:24 +00:00
|
|
|
func NewCpuStats() *CpuStats {
|
2016-05-20 09:05:48 +00:00
|
|
|
numCpus := runtime.NumCPU()
|
2016-06-10 14:42:42 +00:00
|
|
|
cpuStats := &CpuStats{
|
|
|
|
totalCpus: numCpus,
|
|
|
|
}
|
|
|
|
return cpuStats
|
2016-05-19 20:32:03 +00:00
|
|
|
}
|
|
|
|
|
2016-05-20 18:38:15 +00:00
|
|
|
// Percent calculates the cpu usage percentage based on the current cpu usage
|
2016-06-10 17:38:29 +00:00
|
|
|
// and the previous cpu usage where usage is given as time in nanoseconds spend
|
|
|
|
// in the cpu
|
|
|
|
func (c *CpuStats) Percent(cpuTime float64) float64 {
|
2016-05-20 09:10:50 +00:00
|
|
|
now := time.Now()
|
|
|
|
|
2016-06-10 17:38:29 +00:00
|
|
|
if c.prevCpuTime == 0.0 {
|
2016-05-20 09:10:50 +00:00
|
|
|
// invoked first time
|
2016-06-10 17:38:29 +00:00
|
|
|
c.prevCpuTime = cpuTime
|
2016-05-20 09:10:50 +00:00
|
|
|
c.prevTime = now
|
|
|
|
return 0.0
|
|
|
|
}
|
|
|
|
|
2016-06-10 17:38:29 +00:00
|
|
|
timeDelta := now.Sub(c.prevTime).Nanoseconds()
|
|
|
|
ret := c.calculatePercent(c.prevCpuTime, cpuTime, timeDelta)
|
|
|
|
c.prevCpuTime = cpuTime
|
2016-05-20 09:10:50 +00:00
|
|
|
c.prevTime = now
|
|
|
|
return ret
|
2016-06-10 14:42:42 +00:00
|
|
|
}
|
2016-05-20 09:10:50 +00:00
|
|
|
|
2016-06-10 14:42:42 +00:00
|
|
|
// TicksConsumed calculates the total ticks consumes by the process across all
|
|
|
|
// cpu cores
|
|
|
|
func (c *CpuStats) TicksConsumed(percent float64) float64 {
|
2016-06-12 16:08:35 +00:00
|
|
|
return (percent / 100) * shelpers.TotalTicksAvailable() / float64(c.totalCpus)
|
2016-05-20 09:10:50 +00:00
|
|
|
}
|
2016-05-20 09:05:48 +00:00
|
|
|
|
2016-06-10 17:38:29 +00:00
|
|
|
func (c *CpuStats) calculatePercent(t1, t2 float64, timeDelta int64) float64 {
|
|
|
|
vDelta := t2 - t1
|
|
|
|
if timeDelta <= 0 || vDelta <= 0.0 {
|
|
|
|
return 0.0
|
2016-05-20 09:10:50 +00:00
|
|
|
}
|
2016-06-10 17:38:29 +00:00
|
|
|
|
|
|
|
overall_percent := (vDelta / float64(timeDelta)) * 100.0
|
2016-05-20 09:10:50 +00:00
|
|
|
return overall_percent
|
2016-05-19 20:32:03 +00:00
|
|
|
}
|
2020-01-27 18:36:38 +00:00
|
|
|
|
|
|
|
func (h *HostStatsCollector) collectCPUStats() (cpus []*CPUStats, totalTicks float64, err error) {
|
|
|
|
|
|
|
|
ticksConsumed := 0.0
|
|
|
|
cpuStats, err := cpu.Times(true)
|
|
|
|
if err != nil {
|
|
|
|
return nil, 0.0, err
|
|
|
|
}
|
|
|
|
cs := make([]*CPUStats, len(cpuStats))
|
|
|
|
for idx, cpuStat := range cpuStats {
|
|
|
|
percentCalculator, ok := h.statsCalculator[cpuStat.CPU]
|
|
|
|
if !ok {
|
|
|
|
percentCalculator = NewHostCpuStatsCalculator()
|
|
|
|
h.statsCalculator[cpuStat.CPU] = percentCalculator
|
|
|
|
}
|
|
|
|
idle, user, system, total := percentCalculator.Calculate(cpuStat)
|
|
|
|
cs[idx] = &CPUStats{
|
|
|
|
CPU: cpuStat.CPU,
|
|
|
|
User: user,
|
|
|
|
System: system,
|
|
|
|
Idle: idle,
|
|
|
|
Total: total,
|
|
|
|
}
|
|
|
|
ticksConsumed += (total / 100.0) * (shelpers.TotalTicksAvailable() / float64(len(cpuStats)))
|
|
|
|
}
|
|
|
|
|
|
|
|
return cs, ticksConsumed, nil
|
|
|
|
}
|