consul/lib/hoststats/cpu.go

89 lines
2.6 KiB
Go
Raw Normal View History

[COMPLIANCE] License changes (#18443) * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Adding explicit MPL license for sub-package This directory and its subdirectories (packages) contain files licensed with the MPLv2 `LICENSE` file in this directory and are intentionally licensed separately from the BSL `LICENSE` file at the root of this repository. * Updating the license from MPL to Business Source License Going forward, this project will be licensed under the Business Source License v1.1. Please see our blog post for more details at <Blog URL>, FAQ at www.hashicorp.com/licensing-faq, and details of the license at www.hashicorp.com/bsl. * add missing license headers * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 * Update copyright file headers to BUSL-1.1 --------- Co-authored-by: hashicorp-copywrite[bot] <110428419+hashicorp-copywrite[bot]@users.noreply.github.com>
2023-08-11 13:12:13 +00:00
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: BUSL-1.1
package hoststats
import (
"math"
"github.com/shirou/gopsutil/v3/cpu"
)
// cpuStatsCalculator calculates cpu usage percentages
type cpuStatsCalculator struct {
prev cpu.TimesStat
prevBusy float64
prevTotal float64
}
// calculate the current cpu usage percentages.
// Since the cpu.TimesStat captures the total time a cpu spent in various states
// this function tracks the last seen stat and derives each cpu state's utilization
// as a percentage of the total change in cpu time between calls.
// The first time calculate is called CPUStats will report %100 idle
// usage since there is not a previous value to calculate against
func (h *cpuStatsCalculator) calculate(times cpu.TimesStat) *CPUStats {
// sum all none idle counters to get the total busy cpu time
currentBusy := times.User + times.System + times.Nice + times.Iowait + times.Irq +
times.Softirq + times.Steal + times.Guest + times.GuestNice
// sum of the total cpu time
currentTotal := currentBusy + times.Idle
// calculate how much cpu time has passed since last calculation
deltaTotal := currentTotal - h.prevTotal
stats := &CPUStats{
CPU: times.CPU,
// calculate each percentage as the ratio of the change
// in each state's time to the total change in cpu time
Idle: ((times.Idle - h.prev.Idle) / deltaTotal) * 100,
User: ((times.User - h.prev.User) / deltaTotal) * 100,
System: ((times.System - h.prev.System) / deltaTotal) * 100,
Iowait: ((times.Iowait - h.prev.Iowait) / deltaTotal) * 100,
Total: ((currentBusy - h.prevBusy) / deltaTotal) * 100,
}
// Protect against any invalid values
if math.IsNaN(stats.Idle) || math.IsInf(stats.Idle, 0) {
stats.Idle = 100.0
}
if math.IsNaN(stats.User) || math.IsInf(stats.User, 0) {
stats.User = 0.0
}
if math.IsNaN(stats.System) || math.IsInf(stats.System, 0) {
stats.System = 0.0
}
if math.IsNaN(stats.Iowait) || math.IsInf(stats.Iowait, 0) {
stats.Iowait = 0.0
}
if math.IsNaN(stats.Total) || math.IsInf(stats.Total, 0) {
stats.Total = 0.0
}
h.prev = times
h.prevTotal = currentTotal
h.prevBusy = currentBusy
return stats
}
func (c *Collector) collectCPUStats() (cpus []*CPUStats, err error) {
cpuStats, err := cpu.Times(true)
if err != nil {
return nil, err
}
cs := make([]*CPUStats, len(cpuStats))
for idx, cpuStat := range cpuStats {
percentCalculator, ok := c.cpuCalculator[cpuStat.CPU]
if !ok {
percentCalculator = &cpuStatsCalculator{}
c.cpuCalculator[cpuStat.CPU] = percentCalculator
}
cs[idx] = percentCalculator.calculate(cpuStat)
}
return cs, nil
}