Skip to content
5 changes: 3 additions & 2 deletions metric/system/cgroup/cgstats.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"fmt"
"time"

"github.com/elastic/elastic-agent-libs/logp"
"github.com/elastic/elastic-agent-libs/mapstr"
"github.com/elastic/elastic-agent-libs/opt"
"github.com/elastic/elastic-agent-libs/transform/typeconv"
Expand Down Expand Up @@ -73,7 +74,7 @@ func (stat *StatsV1) FillPercentages(prev CGStats, curTime, prevTime time.Time)
if len(stat.CPUAccounting.UsagePerCPU) > 0 {
cpuCount = len(stat.CPUAccounting.UsagePerCPU)
} else {
cpuCount = numcpu.NumCPU()
cpuCount = numcpu.NumCPU(logp.NewLogger(""))
}

// if you look at the raw cgroup stats, the following normalized value is literally an average of per-cpu numbers.
Expand Down Expand Up @@ -129,7 +130,7 @@ func (stat *StatsV2) FillPercentages(prev CGStats, curTime, prevTime time.Time)

pct := float64(totalCPUDeltaNanos) / float64(timeDeltaNanos)

cpuCount := numcpu.NumCPU()
cpuCount := numcpu.NumCPU(logp.NewLogger(""))

// if you look at the raw cgroup stats, the following normalized value is literally an average of per-cpu numbers.
normalizedPct := pct / float64(cpuCount)
Expand Down
8 changes: 5 additions & 3 deletions metric/system/cpu/cpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,24 +23,26 @@ package cpu
import (
"github.com/shirou/gopsutil/v4/load"

"github.com/elastic/elastic-agent-libs/logp"
"github.com/elastic/elastic-agent-system-metrics/metric"
"github.com/elastic/elastic-agent-system-metrics/metric/system/numcpu"
)

// Load returns CPU load information for the previous 1, 5, and 15 minute
// periods.
func Load() (*LoadMetrics, error) {
func Load(logger *logp.Logger) (*LoadMetrics, error) {
avg, err := load.Avg()
if err != nil {
return nil, err
}

return &LoadMetrics{avg}, nil
return &LoadMetrics{avg, logger}, nil
}

// LoadMetrics stores the sampled load average values of the host.
type LoadMetrics struct {
sample *load.AvgStat
logger *logp.Logger
}

// LoadAverages stores the values of load averages of the last 1, 5 and 15 minutes.
Expand All @@ -63,7 +65,7 @@ func (m *LoadMetrics) Averages() LoadAverages {
// NormalizedAverages return the CPU load averages normalized by the NumCPU.
// These values should range from 0 to 1.
func (m *LoadMetrics) NormalizedAverages() LoadAverages {
cpus := numcpu.NumCPU()
cpus := numcpu.NumCPU(m.logger)
return LoadAverages{
OneMinute: metric.Round(m.sample.Load1 / float64(cpus)),
FiveMinute: metric.Round(m.sample.Load5 / float64(cpus)),
Expand Down
3 changes: 2 additions & 1 deletion metric/system/diskio/diskstat_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/disk"

"github.com/elastic/elastic-agent-libs/logp"
"github.com/elastic/elastic-agent-system-metrics/metric"
"github.com/elastic/elastic-agent-system-metrics/metric/system/numcpu"
)
Expand Down Expand Up @@ -95,7 +96,7 @@ func (stat *IOStat) CalcIOStatistics(counter disk.IOCountersStat) (IOMetric, err
}

// calculate the delta ms between the CloseSampling and OpenSampling
deltams := 1000.0 * (float64(uint64(total(stat.curCPU)) - uint64(total(stat.lastCPU)))) / float64(numcpu.NumCPU())
deltams := 1000.0 * (float64(uint64(total(stat.curCPU)) - uint64(total(stat.lastCPU)))) / float64(numcpu.NumCPU(logp.NewLogger("")))
if deltams <= 0 {
return IOMetric{}, errors.New("the delta cpu time between close sampling and open sampling is less or equal to 0")
}
Expand Down
6 changes: 3 additions & 3 deletions metric/system/numcpu/numcpu.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,14 @@ import (
// this number will not reflect the system config.
// Because this is drop-in, it will not return an error.
// if it can't fetch the CPU count the "correct" way, it'll fallback to runtime.NumCPU().
func NumCPU() int {
func NumCPU(logger *logp.Logger) int {
count, exists, err := getCPU()
if err != nil {
logp.L().Debugf("Error fetching CPU count: %s", err)
logger.Debugf("Error fetching CPU count: %v", err)
return runtime.NumCPU()
}
if !exists {
logp.L().Debugf("Accurate CPU counts not available on platform, falling back to runtime.NumCPU for metrics")
logger.Debugf("Accurate CPU counts not available on platform, falling back to runtime.NumCPU for metrics")
return runtime.NumCPU()
}

Expand Down
4 changes: 3 additions & 1 deletion metric/system/numcpu/numcpu_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ import (
"testing"

"github.com/stretchr/testify/assert"

"github.com/elastic/elastic-agent-libs/logp/logptest"
)

func TestGetCPU(t *testing.T) {
Expand All @@ -36,7 +38,7 @@ func TestGetCPU(t *testing.T) {
}

func TestNumCPU(t *testing.T) {
cpuCount := NumCPU()
cpuCount := NumCPU(logptest.NewTestingLogger(t, ""))
assert.NotEqual(t, -1, cpuCount)
t.Logf("CPU Count: %d", cpuCount)
}
3 changes: 2 additions & 1 deletion metric/system/process/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"math"
"time"

"github.com/elastic/elastic-agent-libs/logp"
"github.com/elastic/elastic-agent-libs/opt"
"github.com/elastic/elastic-agent-libs/transform/typeconv"
"github.com/elastic/elastic-agent-system-metrics/metric"
Expand Down Expand Up @@ -90,7 +91,7 @@ func GetProcCPUPercentage(s0, s1 ProcState) ProcState {
if math.IsNaN(pct) {
return s1
}
normalizedPct := pct / float64(numcpu.NumCPU())
normalizedPct := pct / float64(numcpu.NumCPU(logp.NewLogger("")))

s1.CPU.Total.Norm.Pct = opt.FloatWith(metric.Round(normalizedPct))
s1.CPU.Total.Pct = opt.FloatWith(metric.Round(pct))
Expand Down
16 changes: 9 additions & 7 deletions report/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ import (
func MemStatsReporter(logger *logp.Logger, processStats *process.Stats) func(monitoring.Mode, monitoring.Visitor) {
pid, err := process.GetSelfPid(processStats.Hostfs)
if err != nil {
logger.Error("Error while retrieving pid: %v", err)
logger.Errorf("Error while retrieving pid: %v", err)
return nil
}
p := psprocess.Process{
Expand Down Expand Up @@ -80,7 +80,7 @@ func MemStatsReporter(logger *logp.Logger, processStats *process.Stats) func(mon
func InstanceCPUReporter(logger *logp.Logger, processStats *process.Stats) func(monitoring.Mode, monitoring.Visitor) {
pid, err := process.GetSelfPid(processStats.Hostfs)
if err != nil {
logger.Error("Error while retrieving pid: %v", err)
logger.Errorf("Error while retrieving pid: %v", err)
return nil
}
p := psprocess.Process{
Expand Down Expand Up @@ -133,7 +133,7 @@ func ReportSystemLoadAverage(logger *logp.Logger) func(monitoring.Mode, monitori
V.OnRegistryStart()
defer V.OnRegistryFinished()

load, err := cpu.Load()
load, err := cpu.Load(logger)
if err != nil {
logger.Errorf("Error retrieving load average: %v", err)
return
Expand All @@ -152,11 +152,13 @@ func ReportSystemLoadAverage(logger *logp.Logger) func(monitoring.Mode, monitori
}
}

func ReportSystemCPUUsage(_ monitoring.Mode, V monitoring.Visitor) {
V.OnRegistryStart()
defer V.OnRegistryFinished()
func ReportSystemCPUUsage(logger *logp.Logger) func(monitoring.Mode, monitoring.Visitor) {
return func(m monitoring.Mode, V monitoring.Visitor) {
V.OnRegistryStart()
defer V.OnRegistryFinished()

monitoring.ReportInt(V, "cores", int64(numcpu.NumCPU()))
monitoring.ReportInt(V, "cores", int64(numcpu.NumCPU(logger)))
}
}

func ReportRuntime(_ monitoring.Mode, V monitoring.Visitor) {
Expand Down
6 changes: 5 additions & 1 deletion report/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ func SetupMetrics(logger *logp.Logger, name, version string) error {

// SetupMetricsOptions performs creation of metrics handlers using specified options.
func SetupMetricsOptions(opts MetricOptions) error {
monitoring.NewFunc(opts.SystemMetrics, "cpu", ReportSystemCPUUsage, monitoring.Report)
if opts.Logger == nil {
opts.Logger = logp.NewLogger("")
}

monitoring.NewFunc(opts.SystemMetrics, "cpu", ReportSystemCPUUsage(opts.Logger), monitoring.Report)

opts.Name = processName(opts.Name)
processStats = &process.Stats{
Expand Down
Loading