Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mscluster: fix cluster and network sub collectors #1759

Merged
merged 6 commits into from
Nov 24, 2024
Merged
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
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