Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 20 additions & 0 deletions cmd/kepler/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,26 @@ func createCPUMeter(logger *slog.Logger, cfg *config.Config) (device.CPUPowerMet
return device.NewFakeCPUMeter(fake.Zones, device.WithFakeLogger(logger))
}

// Launch hwmon if enabled (experimental feature)
if cfg.IsFeatureEnabled(config.ExperimentalHwmonFeature) {
hwmon := cfg.Experimental.Hwmon

if len(hwmon.Zones) > 0 {
logger.Info("hwmon zones are filtered", "zones-enabled", hwmon.Zones)
}

if len(hwmon.Chips) > 0 {
logger.Info("hwmon chips/sensors are filtered", "sensors-enabled", hwmon.Chips)
}

return device.NewHwmonPowerMeter(
cfg.Host.SysFS,
device.WithHwmonLogger(logger),
device.WithChipFilter(hwmon.Chips),
device.WithHwmonZoneFilter(hwmon.Zones),
)
}

if len(cfg.Rapl.Zones) > 0 {
logger.Info("rapl zones are filtered", "zones-enabled", cfg.Rapl.Zones)
}
Expand Down
97 changes: 97 additions & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ import (
type Feature string

const (
// ExperimentalHwmonFeature represents the hwmon power monitoring feature
ExperimentalHwmonFeature Feature = "hwmon"

// ExperimentalRedfishFeature represents the Redfish BMC power monitoring feature
ExperimentalRedfishFeature Feature = "redfish"

Expand Down Expand Up @@ -51,6 +54,13 @@ type (
Zones []string `yaml:"zones"`
}

// Hwmon configuration (Set in Experimental)
Hwmon struct {
Enabled *bool `yaml:"enabled"` // Development mode settings (sensor detection should be set based on architecture in future)
Zones []string `yaml:"zones"`
Chips []string `yaml:"chips"`
Comment on lines +60 to +61
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

add comments briefly explaining what are zones and chips in hwmon.
are these hwmon concepts or arm concepts?

}

// Development mode settings; disabled by default
Dev struct {
FakeCpuMeter struct {
Expand Down Expand Up @@ -127,6 +137,7 @@ type (
// Experimental contains experimental features (no stability guarantees)
Experimental struct {
Platform Platform `yaml:"platform"`
Hwmon Hwmon `yaml:"hwmon"`
}

Config struct {
Expand Down Expand Up @@ -231,6 +242,11 @@ const (
ExperimentalPlatformRedfishNodeNameFlag = "experimental.platform.redfish.node-name"
ExperimentalPlatformRedfishConfigFlag = "experimental.platform.redfish.config-file"

// Experimental Hwmon flags
ExperimentalHwmonEnabledFlag = "experimental.hwmon.enabled"
ExperimentalHwmonZonesFlag = "experimental.hwmon.zones"
ExperimentalHwmonChipsFlag = "experimental.hwmon.chips"

// WARN: dev settings shouldn't be exposed as flags as flags are intended for end users
)

Expand Down Expand Up @@ -381,6 +397,11 @@ func RegisterFlags(app *kingpin.Application) ConfigUpdaterFn {
redfishNodeName := app.Flag(ExperimentalPlatformRedfishNodeNameFlag, "Node name for experimental Redfish platform power monitoring").String()
redfishConfig := app.Flag(ExperimentalPlatformRedfishConfigFlag, "Path to experimental Redfish BMC configuration file").String()

// experimental hwmon
hwmonEnabled := app.Flag(ExperimentalHwmonEnabledFlag, "Enable experimental hwmon power monitoring").Default("false").Bool()
hwmonZones := app.Flag(ExperimentalHwmonZonesFlag, "Hwmon zone filter (power labels to monitor)").Strings()
hwmonChips := app.Flag(ExperimentalHwmonChipsFlag, "Hwmon chip filter (chip names to monitor)").Strings()

return func(cfg *Config) error {
// Logging settings
if flagsSet[LogLevelFlag] {
Expand Down Expand Up @@ -448,6 +469,11 @@ func RegisterFlags(app *kingpin.Application) ConfigUpdaterFn {
return err
}

// Apply experimental hwmon settings
if err := applyHwmonConfig(cfg, flagsSet, hwmonEnabled, hwmonZones, hwmonChips); err != nil {
return err
}

cfg.sanitize()
return cfg.Validate()
}
Expand Down Expand Up @@ -524,6 +550,59 @@ func resolveRedfishNodeName(redfish *Redfish, kubeNodeName string) error {
return nil
}

// applyHwmonConfig applies Hwmon configuration flags
func applyHwmonConfig(cfg *Config, flagsSet map[string]bool, enabled *bool, zones *[]string, chips *[]string) error {
// Early exit if no hwmon flags are set and config file does not have experimental section
if !hasHwmonFlags(flagsSet) && cfg.Experimental == nil {
return nil
}

// At this point, either hwmon flags are set or config file has experimental section
// so ensure experimental section exists
if cfg.Experimental == nil {
cfg.Experimental = &Experimental{
Hwmon: defaultHwmonConfig(),
}
}

hwmon := &cfg.Experimental.Hwmon

// Apply flag values
applyHwmonFlags(hwmon, flagsSet, enabled, zones, chips)

return nil
}

// hasHwmonFlags returns true if any hwmon experimental flags are set
func hasHwmonFlags(flagsSet map[string]bool) bool {
return flagsSet[ExperimentalHwmonEnabledFlag] ||
flagsSet[ExperimentalHwmonZonesFlag] ||
flagsSet[ExperimentalHwmonChipsFlag]
}

func defaultHwmonConfig() Hwmon {
return Hwmon{
Enabled: ptr.To(false),
Zones: []string{},
Chips: []string{},
}
}

// applyHwmonFlags applies flag values to hwmon config
func applyHwmonFlags(hwmon *Hwmon, flagsSet map[string]bool, enabled *bool, zones *[]string, chips *[]string) {
if flagsSet[ExperimentalHwmonEnabledFlag] {
hwmon.Enabled = enabled
}

if flagsSet[ExperimentalHwmonZonesFlag] {
hwmon.Zones = *zones
}

if flagsSet[ExperimentalHwmonChipsFlag] {
hwmon.Chips = *chips
}
}

// resolveNodeName resolves the node name using the following precedence:
// 1. CLI flag / config.yaml (--experimental.platform.redfish.node-name)
// 2. Kubernetes node name
Expand Down Expand Up @@ -556,6 +635,11 @@ func (c *Config) IsFeatureEnabled(feature Feature) bool {
return false
}
return ptr.Deref(c.Experimental.Platform.Redfish.Enabled, false)
case ExperimentalHwmonFeature:
if c.Experimental == nil {
return false
}
return ptr.Deref(c.Experimental.Hwmon.Enabled, false)
case PrometheusFeature:
return ptr.Deref(c.Exporter.Prometheus.Enabled, false)
case StdoutFeature:
Expand All @@ -578,6 +662,11 @@ func (c *Config) experimentalFeatureEnabled() bool {
return true
}

// Check if Hwmon is enabled
if ptr.Deref(c.Experimental.Hwmon.Enabled, false) {
return true
}

// Add checks for future experimental features here

return false
Expand Down Expand Up @@ -609,6 +698,14 @@ func (c *Config) sanitize() {
c.Experimental.Platform.Redfish.NodeName = strings.TrimSpace(c.Experimental.Platform.Redfish.NodeName)
c.Experimental.Platform.Redfish.ConfigFile = strings.TrimSpace(c.Experimental.Platform.Redfish.ConfigFile)

// Sanitize Hwmon fields
for i := range c.Experimental.Hwmon.Zones {
c.Experimental.Hwmon.Zones[i] = strings.TrimSpace(c.Experimental.Hwmon.Zones[i])
}
for i := range c.Experimental.Hwmon.Chips {
c.Experimental.Hwmon.Chips[i] = strings.TrimSpace(c.Experimental.Hwmon.Chips[i])
}

// If all experimental features are disabled, set experimental to nil to hide it
if !c.experimentalFeatureEnabled() {
c.Experimental = nil
Expand Down
Loading
Loading