diff --git a/api/nodes.go b/api/nodes.go index 5ed88d6b0..9913f47ce 100644 --- a/api/nodes.go +++ b/api/nodes.go @@ -118,10 +118,11 @@ type Node struct { // HostStats represents resource usage stats of the host running a Nomad client type HostStats struct { - Memory *HostMemoryStats - CPU []*HostCPUStats - DiskStats []*HostDiskStats - Uptime uint64 + Memory *HostMemoryStats + CPU []*HostCPUStats + DiskStats []*HostDiskStats + Uptime uint64 + CPUTicksConsumed float64 } type HostMemoryStats struct { diff --git a/client/stats/cpu.go b/client/stats/cpu.go index e4f11bd15..15e7b8d09 100644 --- a/client/stats/cpu.go +++ b/client/stats/cpu.go @@ -4,7 +4,7 @@ import ( "runtime" "time" - "github.com/shirou/gopsutil/cpu" + shelpers "github.com/hashicorp/nomad/helper/stats" ) // CpuStats calculates cpu usage percentage @@ -23,8 +23,9 @@ func NewCpuStats() *CpuStats { totalCpus: numCpus, } - // Caluclate the total cpu ticks available across all cores - cpuStats.totalTicks() + if clkSpeed, err := shelpers.TotalTicksAvailable(); err == nil { + cpuStats.clkSpeed = clkSpeed + } return cpuStats } @@ -52,7 +53,9 @@ func (c *CpuStats) Percent(cpuTime float64) float64 { // cpu cores func (c *CpuStats) TicksConsumed(percent float64) float64 { if c.clkSpeed == 0.0 { - c.totalTicks() + if clkSpeed, err := shelpers.TotalTicksAvailable(); err == nil { + c.clkSpeed = clkSpeed + } } return (percent / 100) * c.clkSpeed } @@ -66,14 +69,3 @@ func (c *CpuStats) calculatePercent(t1, t2 float64, timeDelta int64) float64 { overall_percent := (vDelta / float64(timeDelta)) * 100.0 return overall_percent } - -// totalTicks calculates the total frequency available across all cores -func (c *CpuStats) totalTicks() { - var clkSpeed float64 - if cpuInfo, err := cpu.Info(); err == nil { - for _, cpu := range cpuInfo { - clkSpeed += cpu.Mhz - } - } - c.clkSpeed = clkSpeed -} diff --git a/client/stats/host.go b/client/stats/host.go index a14126f35..8b79df04b 100644 --- a/client/stats/host.go +++ b/client/stats/host.go @@ -1,21 +1,25 @@ package stats import ( + "runtime" "time" "github.com/shirou/gopsutil/cpu" "github.com/shirou/gopsutil/disk" "github.com/shirou/gopsutil/host" "github.com/shirou/gopsutil/mem" + + shelpers "github.com/hashicorp/nomad/helper/stats" ) // HostStats represents resource usage stats of the host running a Nomad client type HostStats struct { - Memory *MemoryStats - CPU []*CPUStats - DiskStats []*DiskStats - Uptime uint64 - Timestamp int64 + Memory *MemoryStats + CPU []*CPUStats + DiskStats []*DiskStats + Uptime uint64 + Timestamp int64 + CPUTicksConsumed float64 } // MemoryStats represnts stats related to virtual memory usage @@ -48,13 +52,23 @@ type DiskStats struct { // HostStatsCollector collects host resource usage stats type HostStatsCollector struct { + clkSpeed float64 + numCores int statsCalculator map[string]*HostCpuStatsCalculator } // NewHostStatsCollector returns a HostStatsCollector func NewHostStatsCollector() *HostStatsCollector { + numCores := runtime.NumCPU() statsCalculator := make(map[string]*HostCpuStatsCalculator) - return &HostStatsCollector{statsCalculator: statsCalculator} + collector := &HostStatsCollector{ + statsCalculator: statsCalculator, + numCores: numCores, + } + if clkSpeed, err := shelpers.TotalTicksAvailable(); err == nil { + collector.clkSpeed = clkSpeed + } + return collector } // Collect collects stats related to resource usage of a host @@ -70,6 +84,12 @@ func (h *HostStatsCollector) Collect() (*HostStats, error) { hs.Memory = ms } + ticksConsumed := 0.0 + if h.clkSpeed == 0.0 { + if clkSpeed, err := shelpers.TotalTicksAvailable(); err == nil { + h.clkSpeed = clkSpeed + } + } if cpuStats, err := cpu.Times(true); err == nil { cs := make([]*CPUStats, len(cpuStats)) for idx, cpuStat := range cpuStats { @@ -89,8 +109,10 @@ func (h *HostStatsCollector) Collect() (*HostStats, error) { cs[idx].System = system cs[idx].User = user cs[idx].Total = total + ticksConsumed += (total / 100) * h.clkSpeed } hs.CPU = cs + hs.CPUTicksConsumed = ticksConsumed } if partitions, err := disk.Partitions(false); err == nil { diff --git a/command/node_status.go b/command/node_status.go index 2595d3a7c..72302834d 100644 --- a/command/node_status.go +++ b/command/node_status.go @@ -2,6 +2,7 @@ package command import ( "fmt" + "math" "sort" "strconv" "strings" @@ -405,18 +406,6 @@ func getActualResources(hostStats *api.HostStats, node *api.Node) ([]string, err } var resources []string - // Calculate cpu usage - usedCPUTicks := 0.0 - if freq, ok := node.Attributes["cpu.frequency"]; ok { - - if clkSpeed, err := strconv.ParseFloat(freq, 64); err == nil { - for _, cpu := range hostStats.CPU { - usedCPUPercent := (cpu.User + cpu.System) - usedCPUTicks += (clkSpeed * usedCPUPercent / 100) - } - } - } - // calculate disk usage storageDevice := node.Attributes["unique.storage.volume"] var diskUsed, diskSize uint64 @@ -430,7 +419,7 @@ func getActualResources(hostStats *api.HostStats, node *api.Node) ([]string, err resources = make([]string, 2) resources[0] = "CPU|Memory|Disk" resources[1] = fmt.Sprintf("%v/%v|%v/%v|%v/%v", - int64(usedCPUTicks), + math.Floor(hostStats.CPUTicksConsumed), node.Resources.CPU, humanize.Bytes(hostStats.Memory.Used), humanize.Bytes(hostStats.Memory.Total),