2021-08-24 04:37:44 +08:00
|
|
|
//go:build linux
|
2020-12-11 04:23:27 +08:00
|
|
|
|
|
|
|
|
package intel_powerstat
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"errors"
|
|
|
|
|
"strconv"
|
|
|
|
|
"sync"
|
|
|
|
|
"testing"
|
2023-01-18 21:10:00 +08:00
|
|
|
"time"
|
2020-12-11 04:23:27 +08:00
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/mock"
|
|
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
|
2023-01-18 21:10:00 +08:00
|
|
|
"github.com/influxdata/telegraf"
|
2020-12-11 04:23:27 +08:00
|
|
|
"github.com/influxdata/telegraf/testutil"
|
|
|
|
|
)
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
type MockServices struct {
|
|
|
|
|
fs *mockFileService
|
|
|
|
|
msr *mockMsrService
|
|
|
|
|
rapl *mockRaplService
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 04:23:27 +08:00
|
|
|
func TestInitPlugin(t *testing.T) {
|
|
|
|
|
cores := []string{"cpu0", "cpu1", "cpu2", "cpu3"}
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.On("getCPUInfoStats", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(nil, errors.New("error getting cpu stats")).Once()
|
|
|
|
|
require.Error(t, power.Init())
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.On("getCPUInfoStats", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(make(map[string]*cpuInfo), nil).Once()
|
|
|
|
|
require.Error(t, power.Init())
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.On("getCPUInfoStats", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(map[string]*cpuInfo{"0": {
|
|
|
|
|
vendorID: "GenuineIntel",
|
|
|
|
|
cpuFamily: "test",
|
|
|
|
|
}}, nil).Once()
|
|
|
|
|
require.Error(t, power.Init())
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.On("getStringsMatchingPatternOnPath", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(cores, nil).Once().
|
|
|
|
|
On("getCPUInfoStats", mock.Anything).
|
|
|
|
|
Return(map[string]*cpuInfo{"0": {
|
|
|
|
|
vendorID: "GenuineIntel",
|
|
|
|
|
cpuFamily: "6",
|
|
|
|
|
}}, nil)
|
|
|
|
|
// Verify MSR service initialization.
|
|
|
|
|
power.cpuFrequency = true
|
|
|
|
|
require.NoError(t, power.Init())
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.AssertCalled(t, "getStringsMatchingPatternOnPath", mock.Anything)
|
2020-12-11 04:23:27 +08:00
|
|
|
require.Equal(t, len(cores), len(power.msr.getCPUCoresData()))
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.On("getStringsMatchingPatternOnPath", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(nil, errors.New("error during getStringsMatchingPatternOnPath")).Once()
|
|
|
|
|
|
|
|
|
|
// In case of an error when fetching cpu cores plugin should proceed with execution.
|
|
|
|
|
require.NoError(t, power.Init())
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.fs.AssertCalled(t, "getStringsMatchingPatternOnPath", mock.Anything)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, power.msr.getCPUCoresData())
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestParseCPUMetricsConfig(t *testing.T) {
|
2022-05-24 03:02:32 +08:00
|
|
|
power, _ := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
disableCoreMetrics(power)
|
|
|
|
|
|
|
|
|
|
power.CPUMetrics = []string{
|
2022-05-24 03:02:32 +08:00
|
|
|
"cpu_frequency", "cpu_c0_state_residency", "cpu_c1_state_residency", "cpu_c6_state_residency", "cpu_busy_cycles", "cpu_temperature",
|
2020-12-11 04:23:27 +08:00
|
|
|
"cpu_busy_frequency",
|
|
|
|
|
}
|
|
|
|
|
power.parseCPUMetricsConfig()
|
|
|
|
|
verifyCoreMetrics(t, power, true)
|
|
|
|
|
disableCoreMetrics(power)
|
|
|
|
|
verifyCoreMetrics(t, power, false)
|
|
|
|
|
|
|
|
|
|
power.CPUMetrics = []string{}
|
|
|
|
|
power.parseCPUMetricsConfig()
|
|
|
|
|
|
|
|
|
|
power.CPUMetrics = []string{"cpu_c6_state_residency", "#@$sdkjdfsdf3@", "1pu_c1_state_residency"}
|
|
|
|
|
power.parseCPUMetricsConfig()
|
2023-10-25 00:45:17 +08:00
|
|
|
require.False(t, power.cpuC1StateResidency)
|
|
|
|
|
require.True(t, power.cpuC6StateResidency)
|
2020-12-11 04:23:27 +08:00
|
|
|
disableCoreMetrics(power)
|
|
|
|
|
verifyCoreMetrics(t, power, false)
|
|
|
|
|
|
|
|
|
|
power.CPUMetrics = []string{"#@$sdkjdfsdf3@", "1pu_c1_state_residency", "123"}
|
|
|
|
|
power.parseCPUMetricsConfig()
|
|
|
|
|
verifyCoreMetrics(t, power, false)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func verifyCoreMetrics(t *testing.T, power *PowerStat, enabled bool) {
|
|
|
|
|
require.Equal(t, enabled, power.cpuFrequency)
|
|
|
|
|
require.Equal(t, enabled, power.cpuC1StateResidency)
|
|
|
|
|
require.Equal(t, enabled, power.cpuC6StateResidency)
|
2022-05-24 03:02:32 +08:00
|
|
|
require.Equal(t, enabled, power.cpuC0StateResidency)
|
2020-12-11 04:23:27 +08:00
|
|
|
require.Equal(t, enabled, power.cpuBusyCycles)
|
|
|
|
|
require.Equal(t, enabled, power.cpuBusyFrequency)
|
|
|
|
|
require.Equal(t, enabled, power.cpuTemperature)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestGather(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
packageIDs := []string{"0", "1"}
|
|
|
|
|
coreIDs := []string{"0", "1", "2", "3"}
|
|
|
|
|
socketCurrentEnergy := 13213852.2
|
|
|
|
|
dramCurrentEnergy := 784552.0
|
|
|
|
|
preparedCPUData := getPreparedCPUData(coreIDs)
|
|
|
|
|
raplDataMap := prepareRaplDataMap(packageIDs, socketCurrentEnergy, dramCurrentEnergy)
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
prepareCPUInfo(power, coreIDs, packageIDs)
|
|
|
|
|
enableCoreMetrics(power)
|
|
|
|
|
power.skipFirstIteration = false
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.On("initializeRaplData", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
On("getRaplData").Return(raplDataMap).
|
|
|
|
|
On("retrieveAndCalculateData", mock.Anything).Return(nil).Times(len(raplDataMap)).
|
|
|
|
|
On("getConstraintMaxPowerWatts", mock.Anything).Return(546783852.3, nil)
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedCPUData).
|
2022-06-06 23:23:48 +08:00
|
|
|
On("isMsrLoaded", mock.Anything).Return(true).
|
2020-12-11 04:23:27 +08:00
|
|
|
On("openAndReadMsr", mock.Anything).Return(nil).
|
|
|
|
|
On("retrieveCPUFrequencyForCore", mock.Anything).Return(1200000.2, nil)
|
|
|
|
|
|
|
|
|
|
require.NoError(t, power.Gather(&acc))
|
|
|
|
|
// Number of global metrics : 3
|
2022-05-24 03:02:32 +08:00
|
|
|
// Number of per core metrics : 7
|
|
|
|
|
require.Equal(t, 3*len(packageIDs)+7*len(coreIDs), len(acc.GetTelegrafMetrics()))
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddGlobalMetricsNegative(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
socketCurrentEnergy := 13213852.2
|
|
|
|
|
dramCurrentEnergy := 784552.0
|
|
|
|
|
raplDataMap := prepareRaplDataMap([]string{"0", "1"}, socketCurrentEnergy, dramCurrentEnergy)
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
power.skipFirstIteration = false
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.On("initializeRaplData", mock.Anything).Once().
|
2020-12-11 04:23:27 +08:00
|
|
|
On("getRaplData").Return(raplDataMap).Once().
|
|
|
|
|
On("retrieveAndCalculateData", mock.Anything).Return(errors.New("error while calculating data")).Times(len(raplDataMap))
|
|
|
|
|
|
|
|
|
|
power.addGlobalMetrics(&acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.AssertNumberOfCalls(t, "retrieveAndCalculateData", len(raplDataMap))
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.On("initializeRaplData", mock.Anything).Once().
|
2020-12-11 04:23:27 +08:00
|
|
|
On("getRaplData").Return(make(map[string]*raplData)).Once()
|
|
|
|
|
|
|
|
|
|
power.addGlobalMetrics(&acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.AssertNotCalled(t, "retrieveAndCalculateData")
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.On("initializeRaplData", mock.Anything).Once().
|
2020-12-11 04:23:27 +08:00
|
|
|
On("getRaplData").Return(raplDataMap).
|
|
|
|
|
On("retrieveAndCalculateData", mock.Anything).Return(nil).Once().
|
|
|
|
|
On("retrieveAndCalculateData", mock.Anything).Return(errors.New("error while calculating data")).Once().
|
|
|
|
|
On("getConstraintMaxPowerWatts", mock.Anything).Return(12313851.5, nil).Twice()
|
|
|
|
|
|
|
|
|
|
power.addGlobalMetrics(&acc)
|
|
|
|
|
require.Equal(t, 3, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddGlobalMetricsPositive(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
socketCurrentEnergy := 3644574.4
|
|
|
|
|
dramCurrentEnergy := 124234872.5
|
|
|
|
|
raplDataMap := prepareRaplDataMap([]string{"0", "1"}, socketCurrentEnergy, dramCurrentEnergy)
|
|
|
|
|
maxPower := 546783852.9
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
power.skipFirstIteration = false
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.On("initializeRaplData", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
On("getRaplData").Return(raplDataMap).
|
|
|
|
|
On("retrieveAndCalculateData", mock.Anything).Return(nil).Times(len(raplDataMap)).
|
|
|
|
|
On("getConstraintMaxPowerWatts", mock.Anything).Return(maxPower, nil).Twice().
|
|
|
|
|
On("getCurrentDramPowerConsumption", mock.Anything).Return(dramCurrentEnergy)
|
|
|
|
|
|
|
|
|
|
power.addGlobalMetrics(&acc)
|
|
|
|
|
require.Equal(t, 6, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedResults := getGlobalMetrics(maxPower, socketCurrentEnergy, dramCurrentEnergy)
|
|
|
|
|
for _, test := range expectedResults {
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_package", test.fields, test.tags)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddMetricsForSingleCoreNegative(t *testing.T) {
|
|
|
|
|
var wg sync.WaitGroup
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
core := "0"
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("openAndReadMsr", core).Return(errors.New("error reading MSR file")).Once()
|
2020-12-11 04:23:27 +08:00
|
|
|
|
|
|
|
|
// Skip generating metric for CPU frequency.
|
|
|
|
|
power.cpuFrequency = false
|
|
|
|
|
|
|
|
|
|
wg.Add(1)
|
|
|
|
|
power.addMetricsForSingleCore(core, &acc, &wg)
|
|
|
|
|
wg.Wait()
|
|
|
|
|
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddCPUFrequencyMetric(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
2021-03-23 01:21:36 +08:00
|
|
|
cpuID := "1"
|
|
|
|
|
coreID := "3"
|
|
|
|
|
packageID := "0"
|
2020-12-11 04:23:27 +08:00
|
|
|
frequency := 1200000.2
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("retrieveCPUFrequencyForCore", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(float64(0), errors.New("error on reading file")).Once()
|
|
|
|
|
|
|
|
|
|
power.addCPUFrequencyMetric(cpuID, &acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("retrieveCPUFrequencyForCore", mock.Anything).Return(frequency, nil).Once()
|
2020-12-11 04:23:27 +08:00
|
|
|
|
|
|
|
|
power.addCPUFrequencyMetric(cpuID, &acc)
|
|
|
|
|
require.Equal(t, 1, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedFrequency := roundFloatToNearestTwoDecimalPlaces(frequency)
|
|
|
|
|
expectedMetric := getPowerCoreMetric("cpu_frequency_mhz", expectedFrequency, coreID, packageID, cpuID)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_core", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-06 23:23:48 +08:00
|
|
|
func TestReadUncoreFreq(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
cpuID := "0"
|
|
|
|
|
coreID := "0"
|
|
|
|
|
packageID := "0"
|
|
|
|
|
die := "0"
|
|
|
|
|
power, mockServices := getPowerWithMockedServices()
|
|
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
preparedData := getPreparedCPUData([]string{cpuID})
|
|
|
|
|
|
|
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedData)
|
|
|
|
|
|
|
|
|
|
mockServices.msr.On("isMsrLoaded").Return(true)
|
|
|
|
|
|
2023-01-18 21:10:00 +08:00
|
|
|
mockServices.msr.On("readSingleMsr", "0", msrUncorePerfStatusString).Return(uint64(10), nil)
|
2022-06-06 23:23:48 +08:00
|
|
|
|
|
|
|
|
mockServices.msr.On("retrieveUncoreFrequency", "0", "initial", "min", "0").
|
|
|
|
|
Return(float64(500), nil)
|
|
|
|
|
mockServices.msr.On("retrieveUncoreFrequency", "0", "initial", "max", "0").
|
|
|
|
|
Return(float64(1200), nil)
|
|
|
|
|
mockServices.msr.On("retrieveUncoreFrequency", "0", "current", "min", "0").
|
|
|
|
|
Return(float64(600), nil)
|
|
|
|
|
mockServices.msr.On("retrieveUncoreFrequency", "0", "current", "max", "0").
|
|
|
|
|
Return(float64(1100), nil)
|
|
|
|
|
|
|
|
|
|
power.readUncoreFreq("current", packageID, die, &acc)
|
|
|
|
|
power.readUncoreFreq("initial", packageID, die, &acc)
|
|
|
|
|
|
|
|
|
|
require.Equal(t, 2, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedMetric := getPowerUncoreFreqMetric("initial", float64(500), float64(1200), nil, packageID, die)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_package", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
|
|
|
|
|
expectedMetric = getPowerUncoreFreqMetric("current", float64(600), float64(1100), uint64(1000), packageID, die)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_package", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 04:23:27 +08:00
|
|
|
func TestAddCoreCPUTemperatureMetric(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
cpuID := "0"
|
|
|
|
|
coreID := "2"
|
|
|
|
|
packageID := "1"
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
preparedData := getPreparedCPUData([]string{cpuID})
|
|
|
|
|
expectedTemp := preparedData[cpuID].throttleTemp - preparedData[cpuID].temp
|
|
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedData).Once()
|
2020-12-11 04:23:27 +08:00
|
|
|
power.addCPUTemperatureMetric(cpuID, &acc)
|
|
|
|
|
require.Equal(t, 1, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedMetric := getPowerCoreMetric("cpu_temperature_celsius", expectedTemp, coreID, packageID, cpuID)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_core", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddC6StateResidencyMetric(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
cpuID := "0"
|
|
|
|
|
coreID := "2"
|
|
|
|
|
packageID := "1"
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
preparedData := getPreparedCPUData([]string{cpuID})
|
|
|
|
|
expectedC6 := roundFloatToNearestTwoDecimalPlaces(percentageMultiplier *
|
|
|
|
|
float64(preparedData[cpuID].c6Delta) / float64(preparedData[cpuID].timeStampCounterDelta))
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedData).Twice()
|
2020-12-11 04:23:27 +08:00
|
|
|
power.addCPUC6StateResidencyMetric(cpuID, &acc)
|
|
|
|
|
require.Equal(t, 1, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedMetric := getPowerCoreMetric("cpu_c6_state_residency_percent", expectedC6, coreID, packageID, cpuID)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_core", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
|
|
|
|
|
acc.ClearMetrics()
|
|
|
|
|
preparedData[cpuID].timeStampCounterDelta = 0
|
|
|
|
|
|
|
|
|
|
power.addCPUC6StateResidencyMetric(cpuID, &acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
func TestAddC0StateResidencyMetric(t *testing.T) {
|
2020-12-11 04:23:27 +08:00
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
cpuID := "0"
|
|
|
|
|
coreID := "2"
|
|
|
|
|
packageID := "1"
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
preparedData := getPreparedCPUData([]string{cpuID})
|
|
|
|
|
expectedBusyCycles := roundFloatToNearestTwoDecimalPlaces(percentageMultiplier * float64(preparedData[cpuID].mperfDelta) /
|
|
|
|
|
float64(preparedData[cpuID].timeStampCounterDelta))
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedData).Twice()
|
|
|
|
|
power.cpuBusyCycles, power.cpuC0StateResidency = true, true
|
|
|
|
|
power.addCPUC0StateResidencyMetric(cpuID, &acc)
|
|
|
|
|
require.Equal(t, 2, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedMetric := getPowerCoreMetric("cpu_c0_state_residency_percent", expectedBusyCycles, coreID, packageID, cpuID)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_core", expectedMetric.fields, expectedMetric.tags)
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
// Deprecated
|
|
|
|
|
expectedMetric = getPowerCoreMetric("cpu_busy_cycles_percent", expectedBusyCycles, coreID, packageID, cpuID)
|
2020-12-11 04:23:27 +08:00
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_core", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
|
|
|
|
|
acc.ClearMetrics()
|
|
|
|
|
preparedData[cpuID].timeStampCounterDelta = 0
|
2022-05-24 03:02:32 +08:00
|
|
|
power.addCPUC0StateResidencyMetric(cpuID, &acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddProcessorBusyFrequencyMetric(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
cpuID := "0"
|
|
|
|
|
coreID := "2"
|
|
|
|
|
packageID := "1"
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
preparedData := getPreparedCPUData([]string{cpuID})
|
|
|
|
|
power.skipFirstIteration = false
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedData).Twice()
|
2020-12-11 04:23:27 +08:00
|
|
|
power.addCPUBusyFrequencyMetric(cpuID, &acc)
|
|
|
|
|
require.Equal(t, 1, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
acc.ClearMetrics()
|
|
|
|
|
preparedData[cpuID].mperfDelta = 0
|
|
|
|
|
power.addCPUBusyFrequencyMetric(cpuID, &acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddC1StateResidencyMetric(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
cpuID := "0"
|
|
|
|
|
coreID := "2"
|
|
|
|
|
packageID := "1"
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
prepareCPUInfoForSingleCPU(power, cpuID, coreID, packageID)
|
|
|
|
|
preparedData := getPreparedCPUData([]string{cpuID})
|
|
|
|
|
c1 := preparedData[cpuID].timeStampCounterDelta - preparedData[cpuID].mperfDelta - preparedData[cpuID].c3Delta -
|
|
|
|
|
preparedData[cpuID].c6Delta - preparedData[cpuID].c7Delta
|
|
|
|
|
expectedC1 := roundFloatToNearestTwoDecimalPlaces(percentageMultiplier * float64(c1) / float64(preparedData[cpuID].timeStampCounterDelta))
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.msr.On("getCPUCoresData").Return(preparedData).Twice()
|
2020-12-11 04:23:27 +08:00
|
|
|
|
|
|
|
|
power.addCPUC1StateResidencyMetric(cpuID, &acc)
|
|
|
|
|
require.Equal(t, 1, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedMetric := getPowerCoreMetric("cpu_c1_state_residency_percent", expectedC1, coreID, packageID, cpuID)
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_core", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
|
|
|
|
|
acc.ClearMetrics()
|
|
|
|
|
preparedData[cpuID].timeStampCounterDelta = 0
|
|
|
|
|
power.addCPUC1StateResidencyMetric(cpuID, &acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddThermalDesignPowerMetric(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
sockets := []string{"0"}
|
|
|
|
|
maxPower := 195720672.1
|
2022-05-24 03:02:32 +08:00
|
|
|
power, mockServices := getPowerWithMockedServices()
|
2020-12-11 04:23:27 +08:00
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
mockServices.rapl.On("getConstraintMaxPowerWatts", mock.Anything).
|
2020-12-11 04:23:27 +08:00
|
|
|
Return(float64(0), errors.New("getConstraintMaxPowerWatts error")).Once().
|
|
|
|
|
On("getConstraintMaxPowerWatts", mock.Anything).Return(maxPower, nil).Once()
|
|
|
|
|
|
|
|
|
|
power.addThermalDesignPowerMetric(sockets[0], &acc)
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, acc.GetTelegrafMetrics())
|
2020-12-11 04:23:27 +08:00
|
|
|
|
|
|
|
|
power.addThermalDesignPowerMetric(sockets[0], &acc)
|
|
|
|
|
require.Equal(t, 1, len(acc.GetTelegrafMetrics()))
|
|
|
|
|
|
|
|
|
|
expectedTDP := roundFloatToNearestTwoDecimalPlaces(maxPower)
|
|
|
|
|
expectedMetric := getPowerGlobalMetric("thermal_design_power_watts", expectedTDP, sockets[0])
|
|
|
|
|
acc.AssertContainsTaggedFields(t, "powerstat_package", expectedMetric.fields, expectedMetric.tags)
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
func TestCalculateTurboRatioGroup(t *testing.T) {
|
|
|
|
|
coreCounts := uint64(0x0807060504030201)
|
|
|
|
|
msr := uint64(0x0807060504030201)
|
|
|
|
|
turboRatioLimitGroups := make(map[int]uint64)
|
|
|
|
|
|
|
|
|
|
calculateTurboRatioGroup(coreCounts, msr, turboRatioLimitGroups)
|
|
|
|
|
require.Equal(t, 8, len(turboRatioLimitGroups))
|
|
|
|
|
require.Equal(t, uint64(100), turboRatioLimitGroups[1])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[2])
|
|
|
|
|
require.Equal(t, uint64(300), turboRatioLimitGroups[3])
|
|
|
|
|
require.Equal(t, uint64(400), turboRatioLimitGroups[4])
|
|
|
|
|
require.Equal(t, uint64(500), turboRatioLimitGroups[5])
|
|
|
|
|
require.Equal(t, uint64(600), turboRatioLimitGroups[6])
|
|
|
|
|
require.Equal(t, uint64(700), turboRatioLimitGroups[7])
|
|
|
|
|
require.Equal(t, uint64(800), turboRatioLimitGroups[8])
|
|
|
|
|
|
|
|
|
|
coreCounts = uint64(0x100e0c0a08060402)
|
|
|
|
|
calculateTurboRatioGroup(coreCounts, msr, turboRatioLimitGroups)
|
|
|
|
|
require.Equal(t, 16, len(turboRatioLimitGroups))
|
|
|
|
|
require.Equal(t, uint64(100), turboRatioLimitGroups[1])
|
|
|
|
|
require.Equal(t, uint64(100), turboRatioLimitGroups[2])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[3])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[4])
|
|
|
|
|
require.Equal(t, uint64(300), turboRatioLimitGroups[5])
|
|
|
|
|
require.Equal(t, uint64(300), turboRatioLimitGroups[6])
|
|
|
|
|
require.Equal(t, uint64(400), turboRatioLimitGroups[7])
|
|
|
|
|
require.Equal(t, uint64(400), turboRatioLimitGroups[8])
|
|
|
|
|
require.Equal(t, uint64(500), turboRatioLimitGroups[9])
|
|
|
|
|
require.Equal(t, uint64(500), turboRatioLimitGroups[10])
|
|
|
|
|
require.Equal(t, uint64(600), turboRatioLimitGroups[11])
|
|
|
|
|
require.Equal(t, uint64(600), turboRatioLimitGroups[12])
|
|
|
|
|
require.Equal(t, uint64(700), turboRatioLimitGroups[13])
|
|
|
|
|
require.Equal(t, uint64(700), turboRatioLimitGroups[14])
|
|
|
|
|
require.Equal(t, uint64(800), turboRatioLimitGroups[15])
|
|
|
|
|
require.Equal(t, uint64(800), turboRatioLimitGroups[16])
|
|
|
|
|
coreCounts = uint64(0x1211)
|
|
|
|
|
msr = uint64(0xfffe)
|
|
|
|
|
calculateTurboRatioGroup(coreCounts, msr, turboRatioLimitGroups)
|
|
|
|
|
require.Equal(t, 18, len(turboRatioLimitGroups))
|
|
|
|
|
require.Equal(t, uint64(25400), turboRatioLimitGroups[17])
|
|
|
|
|
require.Equal(t, uint64(25500), turboRatioLimitGroups[18])
|
|
|
|
|
|
|
|
|
|
coreCounts = uint64(0x1201)
|
|
|
|
|
msr = uint64(0x0202)
|
|
|
|
|
calculateTurboRatioGroup(coreCounts, msr, turboRatioLimitGroups)
|
|
|
|
|
require.Equal(t, 18, len(turboRatioLimitGroups))
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[1])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[2])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[3])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[4])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[5])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[6])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[7])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[8])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[9])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[10])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[11])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[12])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[13])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[14])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[15])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[16])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[17])
|
|
|
|
|
require.Equal(t, uint64(200), turboRatioLimitGroups[18])
|
|
|
|
|
|
|
|
|
|
coreCounts = uint64(0x1211)
|
|
|
|
|
msr = uint64(0xfffe)
|
|
|
|
|
turboRatioLimitGroups = make(map[int]uint64)
|
|
|
|
|
calculateTurboRatioGroup(coreCounts, msr, turboRatioLimitGroups)
|
|
|
|
|
require.Equal(t, 2, len(turboRatioLimitGroups))
|
|
|
|
|
require.Equal(t, uint64(25400), turboRatioLimitGroups[17])
|
|
|
|
|
require.Equal(t, uint64(25500), turboRatioLimitGroups[18])
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 04:23:27 +08:00
|
|
|
func getPreparedCPUData(cores []string) map[string]*msrData {
|
|
|
|
|
msrDataMap := make(map[string]*msrData)
|
|
|
|
|
|
|
|
|
|
for _, core := range cores {
|
|
|
|
|
msrDataMap[core] = &msrData{
|
|
|
|
|
mperf: 43079,
|
|
|
|
|
aperf: 82001,
|
|
|
|
|
timeStampCounter: 15514,
|
|
|
|
|
c3: 52829,
|
|
|
|
|
c6: 86930,
|
|
|
|
|
c7: 25340,
|
|
|
|
|
throttleTemp: 88150,
|
|
|
|
|
temp: 40827,
|
|
|
|
|
mperfDelta: 23515,
|
|
|
|
|
aperfDelta: 33866,
|
|
|
|
|
timeStampCounterDelta: 13686000,
|
|
|
|
|
c3Delta: 20003,
|
|
|
|
|
c6Delta: 44518,
|
|
|
|
|
c7Delta: 20979,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return msrDataMap
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getGlobalMetrics(maxPower float64, socketCurrentEnergy float64, dramCurrentEnergy float64) []struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
} {
|
|
|
|
|
return []struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
}{
|
|
|
|
|
getPowerGlobalMetric("thermal_design_power_watts", roundFloatToNearestTwoDecimalPlaces(maxPower), "0"),
|
|
|
|
|
getPowerGlobalMetric("thermal_design_power_watts", roundFloatToNearestTwoDecimalPlaces(maxPower), "1"),
|
|
|
|
|
getPowerGlobalMetric("current_power_consumption_watts", roundFloatToNearestTwoDecimalPlaces(socketCurrentEnergy), "0"),
|
|
|
|
|
getPowerGlobalMetric("current_power_consumption_watts", roundFloatToNearestTwoDecimalPlaces(socketCurrentEnergy), "1"),
|
|
|
|
|
getPowerGlobalMetric("current_dram_power_consumption_watts", roundFloatToNearestTwoDecimalPlaces(dramCurrentEnergy), "0"),
|
|
|
|
|
getPowerGlobalMetric("current_dram_power_consumption_watts", roundFloatToNearestTwoDecimalPlaces(dramCurrentEnergy), "1"),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getPowerCoreMetric(name string, value interface{}, coreID string, packageID string, cpuID string) struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
} {
|
|
|
|
|
return getPowerMetric(name, value, map[string]string{"package_id": packageID, "core_id": coreID, "cpu_id": cpuID})
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func getPowerGlobalMetric(name string, value interface{}, socketID string) struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
} {
|
|
|
|
|
return getPowerMetric(name, value, map[string]string{"package_id": socketID})
|
|
|
|
|
}
|
|
|
|
|
|
2022-06-06 23:23:48 +08:00
|
|
|
func getPowerUncoreFreqMetric(typeFreq string, limitMin interface{}, limitMax interface{}, current interface{}, socketID string, die string) struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
} {
|
|
|
|
|
var ret struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
}
|
|
|
|
|
ret.tags = make(map[string]string)
|
|
|
|
|
ret.fields = make(map[string]interface{})
|
|
|
|
|
ret.tags["package_id"] = socketID
|
|
|
|
|
ret.tags["die"] = die
|
|
|
|
|
ret.tags["type"] = typeFreq
|
|
|
|
|
ret.fields["uncore_frequency_limit_mhz_min"] = limitMin
|
|
|
|
|
ret.fields["uncore_frequency_limit_mhz_max"] = limitMax
|
|
|
|
|
if typeFreq == "current" {
|
|
|
|
|
ret.fields["uncore_frequency_mhz_cur"] = current
|
|
|
|
|
}
|
|
|
|
|
return ret
|
|
|
|
|
}
|
|
|
|
|
|
2020-12-11 04:23:27 +08:00
|
|
|
func getPowerMetric(name string, value interface{}, tags map[string]string) struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
} {
|
|
|
|
|
return struct {
|
|
|
|
|
fields map[string]interface{}
|
|
|
|
|
tags map[string]string
|
|
|
|
|
}{
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
name: value,
|
|
|
|
|
},
|
|
|
|
|
tags,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func prepareCPUInfoForSingleCPU(power *PowerStat, cpuID string, coreID string, packageID string) {
|
|
|
|
|
power.cpuInfo = make(map[string]*cpuInfo)
|
|
|
|
|
power.cpuInfo[cpuID] = &cpuInfo{
|
|
|
|
|
physicalID: packageID,
|
|
|
|
|
coreID: coreID,
|
|
|
|
|
cpuID: cpuID,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func prepareCPUInfo(power *PowerStat, coreIDs []string, packageIDs []string) {
|
|
|
|
|
power.cpuInfo = make(map[string]*cpuInfo)
|
|
|
|
|
currentCPU := 0
|
|
|
|
|
for _, packageID := range packageIDs {
|
|
|
|
|
for _, coreID := range coreIDs {
|
|
|
|
|
cpuID := strconv.Itoa(currentCPU)
|
|
|
|
|
power.cpuInfo[cpuID] = &cpuInfo{
|
|
|
|
|
physicalID: packageID,
|
|
|
|
|
cpuID: cpuID,
|
|
|
|
|
coreID: coreID,
|
|
|
|
|
}
|
|
|
|
|
currentCPU++
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func enableCoreMetrics(power *PowerStat) {
|
2022-05-24 03:02:32 +08:00
|
|
|
power.cpuC0StateResidency = true
|
2020-12-11 04:23:27 +08:00
|
|
|
power.cpuC1StateResidency = true
|
|
|
|
|
power.cpuC6StateResidency = true
|
|
|
|
|
power.cpuTemperature = true
|
|
|
|
|
power.cpuBusyFrequency = true
|
|
|
|
|
power.cpuFrequency = true
|
|
|
|
|
power.cpuBusyCycles = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func disableCoreMetrics(power *PowerStat) {
|
2022-05-24 03:02:32 +08:00
|
|
|
power.cpuC0StateResidency = false
|
2020-12-11 04:23:27 +08:00
|
|
|
power.cpuC1StateResidency = false
|
|
|
|
|
power.cpuC6StateResidency = false
|
2022-05-24 03:02:32 +08:00
|
|
|
power.cpuBusyCycles = false
|
2020-12-11 04:23:27 +08:00
|
|
|
power.cpuTemperature = false
|
|
|
|
|
power.cpuBusyFrequency = false
|
|
|
|
|
power.cpuFrequency = false
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func prepareRaplDataMap(socketIDs []string, socketCurrentEnergy float64, dramCurrentEnergy float64) map[string]*raplData {
|
|
|
|
|
raplDataMap := make(map[string]*raplData, len(socketIDs))
|
|
|
|
|
for _, socketID := range socketIDs {
|
|
|
|
|
raplDataMap[socketID] = &raplData{
|
|
|
|
|
socketCurrentEnergy: socketCurrentEnergy,
|
|
|
|
|
dramCurrentEnergy: dramCurrentEnergy,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return raplDataMap
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-24 03:02:32 +08:00
|
|
|
func getPowerWithMockedServices() (*PowerStat, *MockServices) {
|
|
|
|
|
var mockServices MockServices
|
|
|
|
|
mockServices.fs = &mockFileService{}
|
|
|
|
|
mockServices.msr = &mockMsrService{}
|
|
|
|
|
mockServices.rapl = &mockRaplService{}
|
|
|
|
|
p := newPowerStat(mockServices.fs)
|
|
|
|
|
p.Log = testutil.Logger{Name: "PowerPluginTest"}
|
|
|
|
|
p.rapl = mockServices.rapl
|
|
|
|
|
p.msr = mockServices.msr
|
|
|
|
|
p.packageCurrentPowerConsumption = true
|
|
|
|
|
p.packageCurrentDramPowerConsumption = true
|
|
|
|
|
p.packageThermalDesignPower = true
|
|
|
|
|
|
|
|
|
|
return p, &mockServices
|
2020-12-11 04:23:27 +08:00
|
|
|
}
|
2023-01-18 21:10:00 +08:00
|
|
|
|
|
|
|
|
func TestGetBusClock(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
modelCPU uint64
|
|
|
|
|
socketID string
|
|
|
|
|
msrFSBFreqValue uint64
|
|
|
|
|
readSingleMsrErrFSB error
|
|
|
|
|
cpuBusClockValue float64
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "Error_withUnknownCPUmodel",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0xFF,
|
|
|
|
|
cpuBusClockValue: 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBS100",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 106,
|
|
|
|
|
msrFSBFreqValue: 1,
|
|
|
|
|
cpuBusClockValue: 100.0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBS133",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x1F,
|
|
|
|
|
cpuBusClockValue: 133,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Error_withFBSCalculated",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 0,
|
|
|
|
|
readSingleMsrErrFSB: errors.New("something is wrong"),
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBSCalculated83.3",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 0,
|
|
|
|
|
cpuBusClockValue: 83.3,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBSCalculated100",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 1,
|
|
|
|
|
cpuBusClockValue: 100,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBSCalculated133.3",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 2,
|
|
|
|
|
cpuBusClockValue: 133.3,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBSCalculated116.7",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 3,
|
|
|
|
|
cpuBusClockValue: 116.7,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBSCalculated80",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 4,
|
|
|
|
|
cpuBusClockValue: 80,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_withFBSCalculatedUnknownFSBFreq",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
modelCPU: 0x37,
|
|
|
|
|
msrFSBFreqValue: 5,
|
|
|
|
|
cpuBusClockValue: 116.7,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
p, mockServices := getPowerWithMockedServices()
|
|
|
|
|
busClockCalculate := []uint64{0x37, 0x4D}
|
|
|
|
|
p.cpuInfo = map[string]*cpuInfo{
|
|
|
|
|
tt.socketID: {cpuID: tt.socketID, physicalID: tt.socketID, model: strconv.FormatUint(tt.modelCPU, 10)},
|
|
|
|
|
}
|
|
|
|
|
if contains(busClockCalculate, tt.modelCPU) {
|
|
|
|
|
mockServices.msr.On("readSingleMsr", mock.Anything, msrFSBFreqString).Return(tt.msrFSBFreqValue, tt.readSingleMsrErrFSB)
|
|
|
|
|
}
|
|
|
|
|
defer mockServices.msr.AssertExpectations(t)
|
|
|
|
|
|
|
|
|
|
value := p.getBusClock(tt.socketID)
|
|
|
|
|
require.Equal(t, tt.cpuBusClockValue, value)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestFillCPUBusClock(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
modelCPU uint64
|
|
|
|
|
busClockValue float64
|
|
|
|
|
packageCPUBaseFrequencySet bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "NotSet_0",
|
|
|
|
|
modelCPU: 0xFF,
|
|
|
|
|
busClockValue: 0,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "Set_100",
|
|
|
|
|
modelCPU: 0x2A,
|
|
|
|
|
busClockValue: 100,
|
|
|
|
|
packageCPUBaseFrequencySet: true,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
p, _ := getPowerWithMockedServices()
|
|
|
|
|
p.packageCPUBaseFrequency = true
|
|
|
|
|
p.cpuInfo = map[string]*cpuInfo{
|
|
|
|
|
"0": {cpuID: "0", physicalID: "0", model: strconv.FormatUint(tt.modelCPU, 10)},
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
p.fillCPUBusClock()
|
|
|
|
|
require.Equal(t, tt.busClockValue, p.cpuBusClockValue)
|
|
|
|
|
require.Equal(t, tt.packageCPUBaseFrequencySet, p.packageCPUBaseFrequency)
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func TestAddCPUBaseFreq(t *testing.T) {
|
|
|
|
|
tests := []struct {
|
|
|
|
|
name string
|
|
|
|
|
socketID string
|
|
|
|
|
readSingleMsrErrRatio error
|
|
|
|
|
msrPlatformInfoValue uint64
|
|
|
|
|
setupPowerstat func(t *testing.T)
|
|
|
|
|
clockBusValue float64
|
|
|
|
|
nonTurboRatio float64
|
|
|
|
|
metricExpected bool
|
|
|
|
|
}{
|
|
|
|
|
{
|
|
|
|
|
name: "Error_reading_msr",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
clockBusValue: 100,
|
|
|
|
|
readSingleMsrErrRatio: errors.New("can't read msr"),
|
|
|
|
|
metricExpected: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "NoMetric_Ratio_is_0",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
msrPlatformInfoValue: 0x8008082FF2810000,
|
|
|
|
|
clockBusValue: 100,
|
|
|
|
|
nonTurboRatio: 0,
|
|
|
|
|
metricExpected: false,
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
name: "OK_Ratio_is_24",
|
|
|
|
|
socketID: "0",
|
|
|
|
|
msrPlatformInfoValue: 0x8008082FF2811800,
|
|
|
|
|
clockBusValue: 100,
|
|
|
|
|
nonTurboRatio: 24,
|
|
|
|
|
metricExpected: true,
|
|
|
|
|
},
|
|
|
|
|
}
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
|
var acc testutil.Accumulator
|
|
|
|
|
p, mockServices := getPowerWithMockedServices()
|
|
|
|
|
|
|
|
|
|
p.cpuInfo = map[string]*cpuInfo{
|
|
|
|
|
tt.socketID: {cpuID: tt.socketID, physicalID: tt.socketID},
|
|
|
|
|
}
|
|
|
|
|
p.cpuBusClockValue = tt.clockBusValue
|
|
|
|
|
|
|
|
|
|
mockServices.msr.On("readSingleMsr", mock.Anything, msrPlatformInfoString).Return(tt.msrPlatformInfoValue, tt.readSingleMsrErrRatio)
|
|
|
|
|
defer mockServices.msr.AssertExpectations(t)
|
|
|
|
|
|
|
|
|
|
p.addCPUBaseFreq(tt.socketID, &acc)
|
|
|
|
|
actual := acc.GetTelegrafMetrics()
|
|
|
|
|
if !tt.metricExpected {
|
2023-10-26 05:09:13 +08:00
|
|
|
require.Empty(t, actual)
|
2023-01-18 21:10:00 +08:00
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
require.Len(t, actual, 1)
|
|
|
|
|
expected := []telegraf.Metric{
|
|
|
|
|
testutil.MustMetric(
|
|
|
|
|
"powerstat_package",
|
|
|
|
|
map[string]string{
|
|
|
|
|
"package_id": tt.socketID,
|
|
|
|
|
},
|
|
|
|
|
map[string]interface{}{
|
|
|
|
|
"cpu_base_frequency_mhz": uint64(tt.nonTurboRatio * tt.clockBusValue),
|
|
|
|
|
},
|
|
|
|
|
time.Unix(0, 0),
|
|
|
|
|
telegraf.Gauge,
|
|
|
|
|
),
|
|
|
|
|
}
|
|
|
|
|
testutil.RequireMetricsEqual(t, expected, actual, testutil.IgnoreTime())
|
|
|
|
|
})
|
|
|
|
|
}
|
|
|
|
|
}
|