diff --git a/collector/chassis/collector.go b/collector/chassis/collector.go index 5da4dac7..fc0da3ae 100755 --- a/collector/chassis/collector.go +++ b/collector/chassis/collector.go @@ -10,6 +10,7 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/stmcginnis/gofish/schemas" + "github.com/stackhpc/redfish_exporter/collector/chassis/environment_metrics" "github.com/stackhpc/redfish_exporter/collector/chassis/network_adapters" "github.com/stackhpc/redfish_exporter/collector/chassis/power" "github.com/stackhpc/redfish_exporter/collector/chassis/power_subsystem" @@ -123,6 +124,10 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) { power_subsystem := power_subsystem.NewCollector(c.Ctx, chassisLogContext, chassis) wg.Go(func() { power_subsystem.Collect(ch) }) + // Some metrics were also moved to EnvironmentMetrics + environment_metrics := environment_metrics.NewCollector(c.Ctx, chassisLogContext, chassis) + wg.Go(func() { environment_metrics.Collect(ch) }) + network_adapters := network_adapters.NewCollector(c.Ctx, chassisLogContext, chassis) wg.Go(func() { network_adapters.Collect(ch) }) diff --git a/collector/chassis/environment_metrics/collector.go b/collector/chassis/environment_metrics/collector.go new file mode 100644 index 00000000..934ad3f8 --- /dev/null +++ b/collector/chassis/environment_metrics/collector.go @@ -0,0 +1,74 @@ +package environment_metrics + +import ( + "log/slog" + + "github.com/prometheus/client_golang/prometheus" + "github.com/stackhpc/redfish_exporter/collector/chassis/power_common" + "github.com/stackhpc/redfish_exporter/common" + "github.com/stmcginnis/gofish/schemas" +) + +var ( + Subsystem = "chassis" + + metricMap = createMetricMap() +) + +func createMetricMap() map[string]common.Metric { + metrics := make(map[string]common.Metric) + + return metrics +} + +// Implements the prometheus.Collector. +type Collector struct { + Ctx *common.CollectionContext + Log *slog.Logger + chassis *schemas.Chassis +} + +// NewCollector returns a collector that collects chassis environment metrics +func NewCollector(ctx *common.CollectionContext, logger *slog.Logger, chassis *schemas.Chassis) *Collector { + return &Collector{ + Ctx: ctx, + Log: logger.With( + "collector", "chassis.environment_metrics", + ), + chassis: chassis, + } +} + +// Describe implemented prometheus.Collector +func Describe(ch chan<- *prometheus.Desc) { + for _, metric := range metricMap { + ch <- metric.Desc + } + power_common.Describe(ch) +} + +// Describe implemented prometheus.Collector +func (c *Collector) Describe(ch chan<- *prometheus.Desc) { + Describe(ch) +} + +func (c *Collector) Collect(ch chan<- prometheus.Metric) { + environmentMetrics, err := c.chassis.EnvironmentMetrics() + if err != nil { + c.Log.Error("error getting environment metrics from chassis", "operation", "chassis.EnvironmentMetrics()", "err", err) + return + } + if environmentMetrics == nil { + return + } + + if environmentMetrics.PowerWatts.Reading != nil { + labelValues := []string{"power_wattage", c.chassis.ID, environmentMetrics.Name, environmentMetrics.ID} + ch <- prometheus.MustNewConstMetric(power_common.MetricMap["chassis_power_average_consumed_watts"].Desc, prometheus.GaugeValue, *environmentMetrics.PowerWatts.Reading, labelValues...) + } + + if environmentMetrics.Voltage.Reading != nil { + labelValues := []string{"power_voltage", c.chassis.ID, environmentMetrics.Name, environmentMetrics.ID} + ch <- prometheus.MustNewConstMetric(power_common.MetricMap["chassis_power_voltage_volts"].Desc, prometheus.GaugeValue, *environmentMetrics.Voltage.Reading, labelValues...) + } +} diff --git a/collector/chassis/environment_metrics/collector_test.go b/collector/chassis/environment_metrics/collector_test.go new file mode 100644 index 00000000..8a76e593 --- /dev/null +++ b/collector/chassis/environment_metrics/collector_test.go @@ -0,0 +1,35 @@ +package environment_metrics_test + +import ( + "testing" + + "github.com/prometheus/common/promslog" + "github.com/stackhpc/redfish_exporter/collector/chassis/environment_metrics" + "github.com/stackhpc/redfish_exporter/common" + redfish_test "github.com/stackhpc/redfish_exporter/common/test" + "github.com/stretchr/testify/require" +) + +func TestPublicTower_2026_2(t *testing.T) { + redfishClient := redfish_test.CreateRedfishClient(t, "DSP2043_2026.2/public-tower") + + chassis, err := redfishClient.Service.Chassis() + require.NoError(t, err) + + ctx := common.CollectionContext{ + RedfishClient: redfishClient, + } + + promslogConfig := promslog.Config{} + logger := promslog.New(&promslogConfig) + + collector := environment_metrics.NewCollector(&ctx, logger, chassis[0]) + expected := ` + redfish_chassis_power_average_consumed_watts{chassis_id="Tower",resource="power_wattage",sensor_id="EnvironmentMetrics",sensor_name="Chassis Environment Metrics"} 974 + ` + redfish_test.CollectAndCompare(t, collector, expected, + // No mockups include voltage on chassis environment metrics + // "redfish_chassis_power_voltage_volts", + "redfish_chassis_power_average_consumed_watts", + ) +} diff --git a/collector/chassis/power/collector.go b/collector/chassis/power/collector.go index b264a24d..a0795f18 100644 --- a/collector/chassis/power/collector.go +++ b/collector/chassis/power/collector.go @@ -13,8 +13,7 @@ import ( ) var ( - Subsystem = "chassis" - ChassisPowerVoltageLabelNames = []string{"resource", "chassis_id", "power_voltage", "power_voltage_id"} + Subsystem = "chassis" metricMap = createMetricMap() ) @@ -22,9 +21,7 @@ var ( func createMetricMap() map[string]common.Metric { metrics := make(map[string]common.Metric) - common.AddToMetricMap(metrics, Subsystem, "power_voltage_state", fmt.Sprintf("power voltage state of chassis component,%s", common.StateHelp), ChassisPowerVoltageLabelNames) - common.AddToMetricMap(metrics, Subsystem, "power_voltage_volts", "power voltage volts number of chassis component", ChassisPowerVoltageLabelNames) - common.AddToMetricMap(metrics, Subsystem, "power_average_consumed_watts", "power wattage watts number of chassis component", ChassisPowerVoltageLabelNames) + common.AddToMetricMap(metrics, Subsystem, "power_voltage_state", fmt.Sprintf("power voltage state of chassis component,%s", common.StateHelp), power_common.ChassisPowerLabelNames) return metrics } @@ -95,11 +92,13 @@ func parseVoltage(ch chan<- prometheus.Metric, chassisID string, voltageInfo sch ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_voltage_state"].Desc, prometheus.GaugeValue, chassisPowerInfoVoltageStateValue, labelValues...) } if voltageInfo.ReadingVolts != nil { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_voltage_volts"].Desc, prometheus.GaugeValue, float64(*voltageInfo.ReadingVolts), labelValues...) + ch <- prometheus.MustNewConstMetric(power_common.MetricMap["chassis_power_voltage_volts"].Desc, prometheus.GaugeValue, float64(*voltageInfo.ReadingVolts), labelValues...) } } func parsePowerControl(ch chan<- prometheus.Metric, chassisID string, powerControl schemas.PowerControl) { labelValues := []string{"power_wattage", chassisID, powerControl.Name, powerControl.MemberID} - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_average_consumed_watts"].Desc, prometheus.GaugeValue, float64(*powerControl.PowerMetrics.AverageConsumedWatts), labelValues...) + if powerControl.PowerMetrics.AverageConsumedWatts != nil { + ch <- prometheus.MustNewConstMetric(power_common.MetricMap["chassis_power_average_consumed_watts"].Desc, prometheus.GaugeValue, float64(*powerControl.PowerMetrics.AverageConsumedWatts), labelValues...) + } } diff --git a/collector/chassis/power/collector_test.go b/collector/chassis/power/collector_test.go index 1507f36f..d8e3cd63 100644 --- a/collector/chassis/power/collector_test.go +++ b/collector/chassis/power/collector_test.go @@ -25,16 +25,15 @@ func TestDSP2043_1_0_0(t *testing.T) { collector := power.NewCollector(&ctx, logger, chassis[0]) expected := ` - redfish_chassis_power_average_consumed_watts{chassis_id="1U",power_voltage="Server Power Control",power_voltage_id="0",resource="power_wattage"} 319 + redfish_chassis_power_average_consumed_watts{chassis_id="1U",resource="power_wattage",sensor_id="0",sensor_name="Server Power Control"} 319 redfish_chassis_power_powersupply_health{chassis_id="1U",power_supply="Power Supply Bay",power_supply_id="0",resource="power_supply"} 2 redfish_chassis_power_powersupply_last_power_output_watts{chassis_id="1U",power_supply="Power Supply Bay",power_supply_id="0",resource="power_supply"} 325 redfish_chassis_power_powersupply_power_capacity_watts{chassis_id="1U",power_supply="Power Supply Bay",power_supply_id="0",resource="power_supply"} 800 redfish_chassis_power_powersupply_state{chassis_id="1U",power_supply="Power Supply Bay",power_supply_id="0",resource="power_supply"} 1 - redfish_chassis_power_voltage_state{chassis_id="1U",power_voltage="VRM1 Voltage",power_voltage_id="0",resource="power_voltage"} 1 - redfish_chassis_power_voltage_state{chassis_id="1U",power_voltage="VRM2 Voltage",power_voltage_id="1",resource="power_voltage"} 1 - redfish_chassis_power_voltage_volts{chassis_id="1U",power_voltage="VRM1 Voltage",power_voltage_id="0",resource="power_voltage"} 12 - redfish_chassis_power_voltage_volts{chassis_id="1U",power_voltage="VRM2 Voltage",power_voltage_id="1",resource="power_voltage"} 5 - + redfish_chassis_power_voltage_state{chassis_id="1U",resource="power_voltage",sensor_id="0",sensor_name="VRM1 Voltage"} 1 + redfish_chassis_power_voltage_state{chassis_id="1U",resource="power_voltage",sensor_id="1",sensor_name="VRM2 Voltage"} 1 + redfish_chassis_power_voltage_volts{chassis_id="1U",resource="power_voltage",sensor_id="0",sensor_name="VRM1 Voltage"} 12 + redfish_chassis_power_voltage_volts{chassis_id="1U",resource="power_voltage",sensor_id="1",sensor_name="VRM2 Voltage"} 5 ` redfish_test.CollectAndCompare(t, collector, expected, "redfish_chassis_power_voltage_state", diff --git a/collector/chassis/power_common/common.go b/collector/chassis/power_common/common.go index 7af719f9..be7de0ca 100644 --- a/collector/chassis/power_common/common.go +++ b/collector/chassis/power_common/common.go @@ -11,8 +11,9 @@ import ( var ( Subsystem = "chassis" ChassisPowerSupplyLabelNames = []string{"resource", "chassis_id", "power_supply", "power_supply_id"} + ChassisPowerLabelNames = []string{"resource", "chassis_id", "sensor_name", "sensor_id"} - metricMap = createMetricMap() + MetricMap = createMetricMap() ) func createMetricMap() map[string]common.Metric { @@ -26,11 +27,14 @@ func createMetricMap() map[string]common.Metric { common.AddToMetricMap(metrics, Subsystem, "power_powersupply_power_output_watts", "measured output power, in Watts, of powersupply on this chassis", ChassisPowerSupplyLabelNames) common.AddToMetricMap(metrics, Subsystem, "power_powersupply_power_capacity_watts", "power_capacity_watts of powersupply on this chassis", ChassisPowerSupplyLabelNames) + common.AddToMetricMap(metrics, Subsystem, "power_voltage_volts", "power voltage volts number of chassis component", ChassisPowerLabelNames) + common.AddToMetricMap(metrics, Subsystem, "power_average_consumed_watts", "power wattage watts number of chassis component", ChassisPowerLabelNames) + return metrics } func Describe(ch chan<- *prometheus.Desc) { - for _, metric := range metricMap { + for _, metric := range MetricMap { ch <- metric.Desc } } @@ -38,24 +42,24 @@ func Describe(ch chan<- *prometheus.Desc) { func ParsePowerSupply(ch chan<- prometheus.Metric, chassisID string, powerSupply schemas.PowerSupply) { labelValues := []string{"power_supply", chassisID, powerSupply.Name, powerSupply.MemberID} if chassisPowerInfoPowerSupplyStateValue, ok := common.ParseCommonStatusState(powerSupply.Status.State); ok { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_state"].Desc, prometheus.GaugeValue, chassisPowerInfoPowerSupplyStateValue, labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_state"].Desc, prometheus.GaugeValue, chassisPowerInfoPowerSupplyStateValue, labelValues...) } if chassisPowerInfoPowerSupplyHealthValue, ok := common.ParseCommonStatusHealth(powerSupply.Status.Health); ok { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_health"].Desc, prometheus.GaugeValue, chassisPowerInfoPowerSupplyHealthValue, labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_health"].Desc, prometheus.GaugeValue, chassisPowerInfoPowerSupplyHealthValue, labelValues...) } if powerSupply.EfficiencyPercent != nil { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_power_efficiency_percentage"].Desc, prometheus.GaugeValue, float64(*powerSupply.EfficiencyPercent), labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_power_efficiency_percentage"].Desc, prometheus.GaugeValue, float64(*powerSupply.EfficiencyPercent), labelValues...) } if powerSupply.LastPowerOutputWatts != nil { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_last_power_output_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.LastPowerOutputWatts), labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_last_power_output_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.LastPowerOutputWatts), labelValues...) } if powerSupply.PowerCapacityWatts != nil { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_power_capacity_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.PowerCapacityWatts), labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_power_capacity_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.PowerCapacityWatts), labelValues...) } if powerSupply.PowerInputWatts != nil { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_power_input_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.PowerInputWatts), labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_power_input_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.PowerInputWatts), labelValues...) } if powerSupply.PowerOutputWatts != nil { - ch <- prometheus.MustNewConstMetric(metricMap["chassis_power_powersupply_power_output_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.PowerOutputWatts), labelValues...) + ch <- prometheus.MustNewConstMetric(MetricMap["chassis_power_powersupply_power_output_watts"].Desc, prometheus.GaugeValue, float64(*powerSupply.PowerOutputWatts), labelValues...) } }