Adding upstream version 1.34.4.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
e393c3af3f
commit
4978089aab
4963 changed files with 677545 additions and 0 deletions
320
plugins/inputs/intel_powerstat/metrics.go
Normal file
320
plugins/inputs/intel_powerstat/metrics.go
Normal file
|
@ -0,0 +1,320 @@
|
|||
//go:build linux && amd64
|
||||
|
||||
package intel_powerstat
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
|
||||
ptel "github.com/intel/powertelemetry"
|
||||
|
||||
"github.com/influxdata/telegraf"
|
||||
)
|
||||
|
||||
// cpuMetricType is an enum type to identify core metrics.
|
||||
type cpuMetricType int
|
||||
|
||||
// cpuMetricType enum defines supported core metrics.
|
||||
const (
|
||||
// metric relying on cpuFreq
|
||||
cpuFrequency cpuMetricType = iota
|
||||
|
||||
// metric relying on msr
|
||||
cpuTemperature
|
||||
|
||||
// metrics relying on msr with storage
|
||||
cpuC0StateResidency
|
||||
cpuC1StateResidency
|
||||
cpuC3StateResidency
|
||||
cpuC6StateResidency
|
||||
cpuC7StateResidency
|
||||
cpuBusyCycles // alias of cpuC0StateResidency
|
||||
cpuBusyFrequency
|
||||
|
||||
// metrics relying on perf
|
||||
cpuC0SubstateC01Percent
|
||||
cpuC0SubstateC02Percent
|
||||
cpuC0SubstateC0WaitPercent
|
||||
)
|
||||
|
||||
// Helper method to return a string representation of a core metric.
|
||||
func (m cpuMetricType) String() string {
|
||||
switch m {
|
||||
case cpuFrequency:
|
||||
return "cpu_frequency"
|
||||
case cpuTemperature:
|
||||
return "cpu_temperature"
|
||||
case cpuBusyFrequency:
|
||||
return "cpu_busy_frequency"
|
||||
case cpuC0StateResidency:
|
||||
return "cpu_c0_state_residency"
|
||||
case cpuC1StateResidency:
|
||||
return "cpu_c1_state_residency"
|
||||
case cpuC3StateResidency:
|
||||
return "cpu_c3_state_residency"
|
||||
case cpuC6StateResidency:
|
||||
return "cpu_c6_state_residency"
|
||||
case cpuC7StateResidency:
|
||||
return "cpu_c7_state_residency"
|
||||
case cpuBusyCycles:
|
||||
return "cpu_busy_cycles"
|
||||
case cpuC0SubstateC01Percent:
|
||||
return "cpu_c0_substate_c01"
|
||||
case cpuC0SubstateC02Percent:
|
||||
return "cpu_c0_substate_c02"
|
||||
case cpuC0SubstateC0WaitPercent:
|
||||
return "cpu_c0_substate_c0_wait"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// UnmarshalText parses the cpu metric from the TOML config file
|
||||
func (m *cpuMetricType) UnmarshalText(data []byte) (err error) {
|
||||
parsedMetric, err := cpuMetricTypeFromString(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = parsedMetric
|
||||
return nil
|
||||
}
|
||||
|
||||
func cpuMetricTypeFromString(metric string) (cpuMetricType, error) {
|
||||
switch metric {
|
||||
case "cpu_frequency":
|
||||
return cpuFrequency, nil
|
||||
case "cpu_temperature":
|
||||
return cpuTemperature, nil
|
||||
case "cpu_busy_frequency":
|
||||
return cpuBusyFrequency, nil
|
||||
case "cpu_c0_state_residency":
|
||||
return cpuC0StateResidency, nil
|
||||
case "cpu_c1_state_residency":
|
||||
return cpuC1StateResidency, nil
|
||||
case "cpu_c3_state_residency":
|
||||
return cpuC3StateResidency, nil
|
||||
case "cpu_c6_state_residency":
|
||||
return cpuC6StateResidency, nil
|
||||
case "cpu_c7_state_residency":
|
||||
return cpuC7StateResidency, nil
|
||||
case "cpu_busy_cycles":
|
||||
return cpuBusyCycles, nil
|
||||
case "cpu_c0_substate_c01":
|
||||
return cpuC0SubstateC01Percent, nil
|
||||
case "cpu_c0_substate_c02":
|
||||
return cpuC0SubstateC02Percent, nil
|
||||
case "cpu_c0_substate_c0_wait":
|
||||
return cpuC0SubstateC0WaitPercent, nil
|
||||
}
|
||||
|
||||
return -1, fmt.Errorf("invalid cpu metric specified: %q", metric)
|
||||
}
|
||||
|
||||
// packageMetricType is an enum type to identify package metrics.
|
||||
type packageMetricType int
|
||||
|
||||
// packageMetricType enum defines supported package metrics.
|
||||
const (
|
||||
// metrics relying on rapl
|
||||
packageCurrentPowerConsumption packageMetricType = iota
|
||||
packageCurrentDramPowerConsumption
|
||||
packageThermalDesignPower
|
||||
|
||||
// metrics relying on msr
|
||||
packageCPUBaseFrequency
|
||||
|
||||
// hybrid metric relying on uncoreFreq as a primary mechanism and on msr as fallback mechanism.
|
||||
packageUncoreFrequency
|
||||
|
||||
// metrics relying on msr
|
||||
packageTurboLimit
|
||||
)
|
||||
|
||||
// Helper method to return a string representation of a package metric.
|
||||
func (m packageMetricType) String() string {
|
||||
switch m {
|
||||
case packageCurrentPowerConsumption:
|
||||
return "current_power_consumption"
|
||||
case packageCurrentDramPowerConsumption:
|
||||
return "current_dram_power_consumption"
|
||||
case packageThermalDesignPower:
|
||||
return "thermal_design_power"
|
||||
case packageCPUBaseFrequency:
|
||||
return "cpu_base_frequency"
|
||||
case packageUncoreFrequency:
|
||||
return "uncore_frequency"
|
||||
case packageTurboLimit:
|
||||
return "max_turbo_frequency"
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// UnmarshalText parses the package metric from the TOML config file
|
||||
func (m *packageMetricType) UnmarshalText(data []byte) (err error) {
|
||||
parsedMetric, err := packageMetricTypeFromString(string(data))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*m = parsedMetric
|
||||
return nil
|
||||
}
|
||||
|
||||
func packageMetricTypeFromString(metric string) (packageMetricType, error) {
|
||||
switch metric {
|
||||
case "current_power_consumption":
|
||||
return packageCurrentPowerConsumption, nil
|
||||
case "current_dram_power_consumption":
|
||||
return packageCurrentDramPowerConsumption, nil
|
||||
case "thermal_design_power":
|
||||
return packageThermalDesignPower, nil
|
||||
case "cpu_base_frequency":
|
||||
return packageCPUBaseFrequency, nil
|
||||
case "uncore_frequency":
|
||||
return packageUncoreFrequency, nil
|
||||
case "max_turbo_frequency":
|
||||
return packageTurboLimit, nil
|
||||
}
|
||||
|
||||
return -1, fmt.Errorf("invalid package metric specified: %q", metric)
|
||||
}
|
||||
|
||||
// numeric is a type constraint definition.
|
||||
type numeric interface {
|
||||
float64 | uint64
|
||||
}
|
||||
|
||||
// metricInfoProvider provides measurement name, fields, and tags needed by the accumulator to add a metric.
|
||||
type metricInfoProvider interface {
|
||||
// measurement returns a string with the name of measurement.
|
||||
measurement() string
|
||||
|
||||
// fields returns a map of string keys with metric name and metric values.
|
||||
fields() (map[string]interface{}, error)
|
||||
|
||||
// tags returns a map of string key and string value to add additional metric-specific information.
|
||||
tags() map[string]string
|
||||
|
||||
// name returns the name of a metric.
|
||||
name() string
|
||||
}
|
||||
|
||||
// addMetric takes a metricInfoProvider interface and adds metric information to an accumulator.
|
||||
func addMetric(acc telegraf.Accumulator, m metricInfoProvider, logOnceMap map[string]struct{}) {
|
||||
fields, err := m.fields()
|
||||
if err == nil {
|
||||
acc.AddGauge(
|
||||
m.measurement(),
|
||||
fields,
|
||||
m.tags(),
|
||||
)
|
||||
return
|
||||
}
|
||||
|
||||
// Always add to the accumulator errors not related to module not initialized.
|
||||
var moduleErr *ptel.ModuleNotInitializedError
|
||||
if !errors.As(err, &moduleErr) {
|
||||
acc.AddError(err)
|
||||
return
|
||||
}
|
||||
|
||||
// Add only once module not initialized error related to module and metric name.
|
||||
logErrorOnce(
|
||||
acc,
|
||||
logOnceMap,
|
||||
fmt.Sprintf("%s_%s", moduleErr.Name, m.name()),
|
||||
fmt.Errorf("failed to get %q: %w", m.name(), moduleErr),
|
||||
)
|
||||
}
|
||||
|
||||
// metricCommon has metric information common to different types.
|
||||
type metricCommon struct {
|
||||
metric interface{}
|
||||
units string
|
||||
}
|
||||
|
||||
func (m *metricCommon) name() string {
|
||||
switch m.metric.(type) {
|
||||
case cpuMetricType:
|
||||
return m.metric.(cpuMetricType).String()
|
||||
case packageMetricType:
|
||||
return m.metric.(packageMetricType).String()
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func (m *metricCommon) measurement() string {
|
||||
switch m.metric.(type) {
|
||||
case cpuMetricType:
|
||||
return "powerstat_core"
|
||||
case packageMetricType:
|
||||
return "powerstat_package"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
// cpuMetric is a generic type that has the information to identify a CPU-related metric,
|
||||
// as well as function to retrieve its value at any time. Implements metricAdder interface.
|
||||
type cpuMetric[T numeric] struct {
|
||||
metricCommon
|
||||
|
||||
cpuID int
|
||||
coreID int
|
||||
packageID int
|
||||
fetchFn func(cpuID int) (T, error)
|
||||
}
|
||||
|
||||
func (m *cpuMetric[T]) fields() (map[string]interface{}, error) {
|
||||
val, err := m.fetchFn(m.cpuID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get %q for CPU ID %v: %w", m.metric, m.cpuID, err)
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
fmt.Sprintf("%s_%s", m.metric, m.units): round(val),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *cpuMetric[T]) tags() map[string]string {
|
||||
return map[string]string{
|
||||
"core_id": strconv.Itoa(m.coreID),
|
||||
"cpu_id": strconv.Itoa(m.cpuID),
|
||||
"package_id": strconv.Itoa(m.packageID),
|
||||
}
|
||||
}
|
||||
|
||||
// packageMetric is a generic type that has the information to identify a package-related metric,
|
||||
// as well as the function to retrieve its value at any time. Implements metricAdder interface.
|
||||
type packageMetric[T numeric] struct {
|
||||
metricCommon
|
||||
|
||||
packageID int
|
||||
fetchFn func(packageID int) (T, error)
|
||||
}
|
||||
|
||||
func (m *packageMetric[T]) fields() (map[string]interface{}, error) {
|
||||
val, err := m.fetchFn(m.packageID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get %q for package ID %v: %w", m.metric, m.packageID, err)
|
||||
}
|
||||
|
||||
return map[string]interface{}{
|
||||
fmt.Sprintf("%s_%s", m.metric, m.units): round(val),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (m *packageMetric[T]) tags() map[string]string {
|
||||
return map[string]string{
|
||||
"package_id": strconv.Itoa(m.packageID),
|
||||
}
|
||||
}
|
||||
|
||||
// round returns the result of rounding the argument, only if it's a 64 bit floating-point type.
|
||||
func round[T numeric](val T) T {
|
||||
if v, ok := any(val).(float64); ok {
|
||||
val = T(math.Round(v*100) / 100)
|
||||
}
|
||||
return val
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue