Skip to content

Commit

Permalink
mscluster: fix cluster and network sub collectors (#1759)
Browse files Browse the repository at this point in the history
Signed-off-by: Jan-Otto Kröpke <[email protected]>
  • Loading branch information
jkroepke authored Nov 24, 2024
1 parent 86ace68 commit f9e4129
Show file tree
Hide file tree
Showing 6 changed files with 162 additions and 58 deletions.
140 changes: 97 additions & 43 deletions internal/collector/mscluster/mscluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,25 +8,34 @@ import (
"log/slog"
"slices"
"strings"
"sync"

"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus/client_golang/prometheus"
)

const Name = "mscluster"
const (
Name = "mscluster"

subCollectorCluster = "cluster"
subCollectorNetwork = "network"
subCollectorNode = "node"
subCollectorResource = "resource"
subCollectorResourceGroup = "resourcegroup"
)

type Config struct {
CollectorsEnabled []string `yaml:"collectors_enabled"`
}

var ConfigDefaults = Config{
CollectorsEnabled: []string{
"cluster",
"network",
"node",
"resource",
"resourcegroup",
subCollectorCluster,
subCollectorNetwork,
subCollectorNode,
subCollectorResource,
subCollectorResourceGroup,
},
}

Expand Down Expand Up @@ -99,27 +108,39 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {

c.miSession = miSession

if slices.Contains(c.config.CollectorsEnabled, "cluster") {
c.buildCluster()
errs := make([]error, 0, 5)

if slices.Contains(c.config.CollectorsEnabled, subCollectorCluster) {
if err := c.buildCluster(); err != nil {
errs = append(errs, fmt.Errorf("failed to build cluster collector: %w", err))
}
}

if slices.Contains(c.config.CollectorsEnabled, "network") {
c.buildNetwork()
if slices.Contains(c.config.CollectorsEnabled, subCollectorNetwork) {
if err := c.buildNetwork(); err != nil {
errs = append(errs, fmt.Errorf("failed to build network collector: %w", err))
}
}

if slices.Contains(c.config.CollectorsEnabled, "node") {
c.buildNode()
if slices.Contains(c.config.CollectorsEnabled, subCollectorNode) {
if err := c.buildNode(); err != nil {
errs = append(errs, fmt.Errorf("failed to build node collector: %w", err))
}
}

if slices.Contains(c.config.CollectorsEnabled, "resource") {
c.buildResource()
if slices.Contains(c.config.CollectorsEnabled, subCollectorResource) {
if err := c.buildResource(); err != nil {
errs = append(errs, fmt.Errorf("failed to build resource collector: %w", err))
}
}

if slices.Contains(c.config.CollectorsEnabled, "resourcegroup") {
c.buildResourceGroup()
if slices.Contains(c.config.CollectorsEnabled, subCollectorResourceGroup) {
if err := c.buildResourceGroup(); err != nil {
errs = append(errs, fmt.Errorf("failed to build resource group collector: %w", err))
}
}

return nil
return errors.Join(errs...)
}

// Collect sends the metric values for each metric
Expand All @@ -129,40 +150,73 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
return nil
}

var (
err error
errs []error
nodeNames []string
)
errCh := make(chan error, 5)

if slices.Contains(c.config.CollectorsEnabled, "cluster") {
if err = c.collectCluster(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect cluster metrics: %w", err))
}
}
wg := sync.WaitGroup{}
wg.Add(5)

if slices.Contains(c.config.CollectorsEnabled, "network") {
if err = c.collectNetwork(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect network metrics: %w", err))
}
}
go func() {
defer wg.Done()

if slices.Contains(c.config.CollectorsEnabled, "node") {
if nodeNames, err = c.collectNode(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect node metrics: %w", err))
if slices.Contains(c.config.CollectorsEnabled, subCollectorCluster) {
if err := c.collectCluster(ch); err != nil {
errCh <- fmt.Errorf("failed to collect cluster metrics: %w", err)
}
}
}
}()

go func() {
defer wg.Done()

if slices.Contains(c.config.CollectorsEnabled, "resource") {
if err = c.collectResource(ch, nodeNames); err != nil {
errs = append(errs, fmt.Errorf("failed to collect resource metrics: %w", err))
if slices.Contains(c.config.CollectorsEnabled, subCollectorNetwork) {
if err := c.collectNetwork(ch); err != nil {
errCh <- fmt.Errorf("failed to collect network metrics: %w", err)
}
}
}
}()

go func() {
defer wg.Done()

if slices.Contains(c.config.CollectorsEnabled, "resourcegroup") {
if err = c.collectResourceGroup(ch, nodeNames); err != nil {
errs = append(errs, fmt.Errorf("failed to collect resource group metrics: %w", err))
nodeNames := make([]string, 0)

if slices.Contains(c.config.CollectorsEnabled, subCollectorNode) {
var err error

nodeNames, err = c.collectNode(ch)
if err != nil {
errCh <- fmt.Errorf("failed to collect node metrics: %w", err)
}
}

go func() {
defer wg.Done()

if slices.Contains(c.config.CollectorsEnabled, subCollectorResource) {
if err := c.collectResource(ch, nodeNames); err != nil {
errCh <- fmt.Errorf("failed to collect resource metrics: %w", err)
}
}
}()

go func() {
defer wg.Done()

if slices.Contains(c.config.CollectorsEnabled, subCollectorResourceGroup) {
if err := c.collectResourceGroup(ch, nodeNames); err != nil {
errCh <- fmt.Errorf("failed to collect resource group metrics: %w", err)
}
}
}()
}()

wg.Wait()
close(errCh)

errs := make([]error, 0, 5)

for err := range errCh {
errs = append(errs, err)
}

return errors.Join(errs...)
Expand Down
16 changes: 13 additions & 3 deletions internal/collector/mscluster/mscluster_cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (

"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
)

const nameCluster = Name + "_cluster"

type collectorCluster struct {
clusterMIQuery mi.Query

clusterAddEvictDelay *prometheus.Desc
clusterAdminAccessPoint *prometheus.Desc
clusterAutoAssignNodeSite *prometheus.Desc
Expand Down Expand Up @@ -177,7 +178,14 @@ type msClusterCluster struct {
WitnessRestartInterval uint `mi:"WitnessRestartInterval"`
}

func (c *Collector) buildCluster() {
func (c *Collector) buildCluster() error {
clusterMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Cluster")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}

c.clusterMIQuery = clusterMIQuery

c.clusterAddEvictDelay = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameCluster, "add_evict_delay"),
"Provides access to the cluster's AddEvictDelay property, which is the number a seconds that a new node is delayed after an eviction of another node.",
Expand Down Expand Up @@ -640,11 +648,13 @@ func (c *Collector) buildCluster() {
[]string{"name"},
nil,
)

return nil
}

func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error {
var dst []msClusterCluster
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * MSCluster_Cluster"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.clusterMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

Expand Down
16 changes: 13 additions & 3 deletions internal/collector/mscluster/mscluster_network.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (

"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
)

const nameNetwork = Name + "_network"

type collectorNetwork struct {
networkMIQuery mi.Query

networkCharacteristics *prometheus.Desc
networkFlags *prometheus.Desc
networkMetric *prometheus.Desc
Expand All @@ -33,7 +34,14 @@ type msClusterNetwork struct {
State uint `mi:"State"`
}

func (c *Collector) buildNetwork() {
func (c *Collector) buildNetwork() error {
networkMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Network")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}

c.networkMIQuery = networkMIQuery

c.networkCharacteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNetwork, "characteristics"),
"Provides the characteristics of the network.",
Expand Down Expand Up @@ -64,14 +72,16 @@ func (c *Collector) buildNetwork() {
[]string{"name"},
nil,
)

return nil
}

// Collect sends the metric values for each metric
// to the provided prometheus metric channel.
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric) error {
var dst []msClusterNetwork

if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * MSCluster_Node"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.networkMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

Expand Down
16 changes: 13 additions & 3 deletions internal/collector/mscluster/mscluster_node.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (

"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
)

const nameNode = Name + "_node"

type collectorNode struct {
nodeMIQuery mi.Query

nodeBuildNumber *prometheus.Desc
nodeCharacteristics *prometheus.Desc
nodeDetectedCloudPlatform *prometheus.Desc
Expand Down Expand Up @@ -51,7 +52,14 @@ type msClusterNode struct {
StatusInformation uint `mi:"StatusInformation"`
}

func (c *Collector) buildNode() {
func (c *Collector) buildNode() error {
nodeMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Node")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}

c.nodeMIQuery = nodeMIQuery

c.nodeBuildNumber = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameNode, "build_number"),
"Provides access to the node's BuildNumber property.",
Expand Down Expand Up @@ -136,14 +144,16 @@ func (c *Collector) buildNode() {
[]string{"name"},
nil,
)

return nil
}

// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) collectNode(ch chan<- prometheus.Metric) ([]string, error) {
var dst []msClusterNode

if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_Node"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.nodeMIQuery); err != nil {
return nil, fmt.Errorf("WMI query failed: %w", err)
}

Expand Down
16 changes: 13 additions & 3 deletions internal/collector/mscluster/mscluster_resource.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,14 @@ import (

"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
"github.com/prometheus-community/windows_exporter/internal/utils"
"github.com/prometheus/client_golang/prometheus"
)

const nameResource = Name + "_resource"

type collectorResource struct {
resourceMIQuery mi.Query

resourceCharacteristics *prometheus.Desc
resourceDeadlockTimeout *prometheus.Desc
resourceEmbeddedFailureAction *prometheus.Desc
Expand Down Expand Up @@ -59,7 +60,14 @@ type msClusterResource struct {
Subclass uint `mi:"Subclass"`
}

func (c *Collector) buildResource() {
func (c *Collector) buildResource() error {
resourceMIQuery, err := mi.NewQuery("SELECT * FROM MSCluster_Resource")
if err != nil {
return fmt.Errorf("failed to create WMI query: %w", err)
}

c.resourceMIQuery = resourceMIQuery

c.resourceCharacteristics = prometheus.NewDesc(
prometheus.BuildFQName(types.Namespace, nameResource, "characteristics"),
"Provides the characteristics of the object.",
Expand Down Expand Up @@ -168,14 +176,16 @@ func (c *Collector) buildResource() {
[]string{"type", "owner_group", "name"},
nil,
)

return nil
}

// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) collectResource(ch chan<- prometheus.Metric, nodeNames []string) error {
var dst []msClusterResource

if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, utils.Must(mi.NewQuery("SELECT * FROM MSCluster_Resource"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceMIQuery); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

Expand Down
Loading

0 comments on commit f9e4129

Please sign in to comment.