mi: make timeout configurable for build functions (#2377)

This commit is contained in:
Jan-Otto Kröpke
2026-03-30 18:32:58 +02:00
committed by GitHub
parent 792ef67c4e
commit 43f83573ef
75 changed files with 322 additions and 143 deletions

View File

@@ -20,6 +20,7 @@ package ad
import (
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -518,7 +519,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err)

View File

@@ -20,6 +20,7 @@ package adcs
import (
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -173,7 +174,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect Certification Authority (ADCS) metrics: %w", err)

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"log/slog"
"math"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -383,7 +384,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect ADFS metrics: %w", err)

View File

@@ -20,6 +20,7 @@ package cache
import (
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -286,7 +287,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
}
// Collect implements the Collector interface.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect Cache metrics: %w", err)

View File

@@ -26,6 +26,7 @@ import (
"os"
"slices"
"strings"
"time"
"unsafe"
"github.com/alecthomas/kingpin/v2"
@@ -291,7 +292,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorHCS) {

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"log/slog"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -191,7 +192,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
c.mu.Lock() // Lock is needed to prevent concurrent map access to c.processorRTCValues
defer c.mu.Unlock()

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"strconv"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -151,7 +152,7 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
c.miSession = miSession
var dst []miProcessor
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -176,9 +177,9 @@ type miProcessor struct {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []miProcessor
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"slices"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -480,7 +481,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect implements the Collector interface.
// Sends metric values for each metric to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, "connection") {

View File

@@ -24,6 +24,7 @@ import (
"slices"
"strconv"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/dhcpsapi"
@@ -387,7 +388,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
var errs []error
if slices.Contains(c.config.CollectorsEnabled, subCollectorServerMetrics) {

View File

@@ -22,6 +22,7 @@ import (
"fmt"
"log/slog"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -127,7 +128,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
c.miSession = miSession
var dst []diskDrive
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -188,9 +189,9 @@ var (
)
// Collect sends the metric values for each metric to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []diskDrive
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, c.miQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"slices"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -320,12 +321,17 @@ func (c *Collector) buildErrorStatsCollector(miSession *mi.Session) error {
c.miSession = miSession
c.miQuery = query
var stats []Statistic
if err := c.miSession.Query(&stats, mi.NamespaceRootMicrosoftDNS, c.miQuery, 0); err != nil {
return fmt.Errorf("failed to query DNS statistics: %w", err)
}
return nil
}
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {
@@ -335,7 +341,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
}
if slices.Contains(c.config.CollectorsEnabled, subCollectorWMIStats) {
if err := c.collectErrorStats(ch); err != nil {
if err := c.collectErrorStats(ch, maxScrapeDuration); err != nil {
errs = append(errs, fmt.Errorf("failed collecting WMI statistics: %w", err))
}
}
@@ -627,9 +633,9 @@ func (c *Collector) collectMetrics(ch chan<- prometheus.Metric) error {
return nil
}
func (c *Collector) collectErrorStats(ch chan<- prometheus.Metric) error {
func (c *Collector) collectErrorStats(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var stats []Statistic
if err := c.miSession.Query(&stats, mi.NamespaceRootMicrosoftDNS, c.miQuery); err != nil {
if err := c.miSession.Query(&stats, mi.NamespaceRootMicrosoftDNS, c.miQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("failed to query DNS statistics: %w", err)
}

View File

@@ -24,6 +24,7 @@ import (
"os"
"strings"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -252,7 +253,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
}
// Collect collects exchange metrics and sends them to prometheus.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errCh := make(chan error, len(c.collectorFns))
errs := make([]error, 0, len(c.collectorFns))

View File

@@ -25,6 +25,7 @@ import (
"path/filepath"
"strings"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/bmatcuk/doublestar/v4"
@@ -124,7 +125,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
wg := sync.WaitGroup{}
for _, filePattern := range c.config.FilePatterns {

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -146,7 +147,7 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
)
var dst []msftFSRMQuota
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -169,9 +170,9 @@ type msftFSRMQuota struct {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []msftFSRMQuota
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootWindowsFSRM, c.miQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/cfgmgr32"
@@ -314,7 +315,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
return errors.Join(errs...)
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
c.collectGpuInfo(ch)

View File

@@ -24,6 +24,7 @@ import (
"sort"
"strings"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -281,7 +282,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errCh := make(chan error, len(c.collectorFns))
errs := make([]error, 0, len(c.collectorFns))

View File

@@ -24,6 +24,7 @@ import (
"regexp"
"slices"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -251,7 +252,7 @@ func (c *Collector) getIISVersion() simpleVersion {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
ch <- prometheus.MustNewConstMetric(
c.info,
prometheus.GaugeValue,

View File

@@ -19,6 +19,7 @@ package license
import (
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/slc"
@@ -87,7 +88,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
status, err := slc.SLIsWindowsGenuineLocal()
if err != nil {
return err

View File

@@ -29,6 +29,7 @@ import (
"slices"
"strconv"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/go-ole/go-ole"
@@ -361,7 +362,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
var info volumeInfo
err := c.perfDataCollector.Collect(&c.perfDataObject)

View File

@@ -24,6 +24,7 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
@@ -347,7 +348,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if err := c.collectPDH(ch); err != nil {

View File

@@ -24,6 +24,7 @@ import (
"slices"
"strings"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -179,21 +180,21 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
if len(c.config.CollectorsEnabled) == 0 {
return nil
}
errCh := make(chan error, 6)
errCh := make(chan error, 7)
wg := sync.WaitGroup{}
wg.Add(6)
wg.Add(7)
go func() {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorCluster) {
if err := c.collectCluster(ch); err != nil {
if err := c.collectCluster(ch, maxScrapeDuration); err != nil {
errCh <- fmt.Errorf("failed to collect cluster metrics: %w", err)
}
}
@@ -203,7 +204,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorNetwork) {
if err := c.collectNetwork(ch); err != nil {
if err := c.collectNetwork(ch, maxScrapeDuration); err != nil {
errCh <- fmt.Errorf("failed to collect network metrics: %w", err)
}
}
@@ -217,7 +218,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
if slices.Contains(c.config.CollectorsEnabled, subCollectorNode) {
var err error
nodeNames, err = c.collectNode(ch)
nodeNames, err = c.collectNode(ch, maxScrapeDuration)
if err != nil {
errCh <- fmt.Errorf("failed to collect node metrics: %w", err)
}
@@ -227,7 +228,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorResource) {
if err := c.collectResource(ch, nodeNames); err != nil {
if err := c.collectResource(ch, maxScrapeDuration, nodeNames); err != nil {
errCh <- fmt.Errorf("failed to collect resource metrics: %w", err)
}
}
@@ -237,7 +238,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorResourceGroup) {
if err := c.collectResourceGroup(ch, nodeNames); err != nil {
if err := c.collectResourceGroup(ch, maxScrapeDuration, nodeNames); err != nil {
errCh <- fmt.Errorf("failed to collect resource group metrics: %w", err)
}
}
@@ -248,13 +249,17 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorSharedVolumes) {
if err := c.collectSharedVolumes(ch); err != nil {
if err := c.collectSharedVolumes(ch, maxScrapeDuration); err != nil {
errCh <- fmt.Errorf("failed to collect shared_volumes metrics: %w", err)
}
}
}()
go func() {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorVirtualDisk) {
if err := c.collectVirtualDisk(ch); err != nil {
if err := c.collectVirtualDisk(ch, maxScrapeDuration); err != nil {
errCh <- fmt.Errorf("failed to collect virtualdisk metrics: %w", err)
}
}

View File

@@ -19,6 +19,7 @@ package mscluster
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
@@ -673,16 +674,16 @@ func (c *Collector) buildCluster() error {
)
var dst []msClusterCluster
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.clusterMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.clusterMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil
}
func (c *Collector) collectCluster(ch chan<- prometheus.Metric) error {
func (c *Collector) collectCluster(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []msClusterCluster
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.clusterMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.clusterMIQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package mscluster
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -90,7 +91,7 @@ func (c *Collector) buildNetwork() error {
var dst []msClusterNetwork
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.networkMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.networkMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -99,10 +100,10 @@ func (c *Collector) buildNetwork() error {
// Collect sends the metric values for each metric
// to the provided prometheus metric channel.
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric) error {
func (c *Collector) collectNetwork(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []msClusterNetwork
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.networkMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.networkMIQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package mscluster
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion"
@@ -170,7 +171,7 @@ func (c *Collector) buildNode() error {
var dst []msClusterNode
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.nodeMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.nodeMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -179,10 +180,10 @@ func (c *Collector) buildNode() error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) collectNode(ch chan<- prometheus.Metric) ([]string, error) {
func (c *Collector) collectNode(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) ([]string, error) {
var dst []msClusterNode
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.nodeMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.nodeMIQuery, maxScrapeDuration); err != nil {
return nil, fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package mscluster
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -194,7 +195,7 @@ func (c *Collector) buildResource() error {
var dst []msClusterResource
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -203,10 +204,10 @@ func (c *Collector) buildResource() error {
// 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 {
func (c *Collector) collectResource(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration, nodeNames []string) error {
var dst []msClusterResource
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceMIQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package mscluster
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -168,7 +169,7 @@ func (c *Collector) buildResourceGroup() error {
var dst []msClusterResourceGroup
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceGroupMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceGroupMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -177,10 +178,10 @@ func (c *Collector) buildResourceGroup() error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, nodeNames []string) error {
func (c *Collector) collectResourceGroup(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration, nodeNames []string) error {
var dst []msClusterResourceGroup
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceGroupMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.resourceGroupMIQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -20,6 +20,7 @@ package mscluster
import (
"fmt"
"strings"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -76,16 +77,16 @@ func (c *Collector) buildSharedVolumes() error {
)
var dst []msClusterDiskPartition
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.sharedVolumesMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.sharedVolumesMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil
}
func (c *Collector) collectSharedVolumes(ch chan<- prometheus.Metric) error {
func (c *Collector) collectSharedVolumes(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []msClusterDiskPartition
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.sharedVolumesMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootMSCluster, c.sharedVolumesMIQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package mscluster
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -92,13 +93,19 @@ func (c *Collector) buildVirtualDisk() error {
nil,
)
var dst []msftVirtualDisk
if err := c.miSession.Query(&dst, mi.NamespaceRootStorage, c.virtualDiskMIQuery, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
return nil
}
func (c *Collector) collectVirtualDisk(ch chan<- prometheus.Metric) error {
func (c *Collector) collectVirtualDisk(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []msftVirtualDisk
if err := c.miSession.Query(&dst, mi.NamespaceRootStorage, c.virtualDiskMIQuery); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootStorage, c.virtualDiskMIQuery, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -20,6 +20,7 @@ package msmq
import (
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -113,7 +114,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect MSMQ Queue metrics: %w", err)

View File

@@ -274,7 +274,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
if len(c.mssqlInstances) == 0 {
return fmt.Errorf("no SQL instances found: %w", pdh.ErrNoData)
}

View File

@@ -25,6 +25,7 @@ import (
"regexp"
"slices"
"strings"
"time"
"unsafe"
"github.com/alecthomas/kingpin/v2"
@@ -295,7 +296,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {

View File

@@ -24,6 +24,7 @@ import (
"sort"
"strings"
"sync"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -66,7 +67,7 @@ type Collector struct {
config Config
miSession *mi.Session
collectorFns []func(ch chan<- prometheus.Metric) error
collectorFns []func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error
// clrexceptions
numberOfExceptionsThrown *prometheus.Desc
@@ -187,11 +188,11 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
c.miSession = miSession
c.collectorFns = make([]func(ch chan<- prometheus.Metric) error, 0, len(c.config.CollectorsEnabled))
c.collectorFns = make([]func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error, 0, len(c.config.CollectorsEnabled))
subCollectors := map[string]struct {
build func()
collect func(ch chan<- prometheus.Metric) error
collect func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error
close func()
}{
collectorClrExceptions: {
@@ -246,7 +247,7 @@ func (c *Collector) Build(_ *slog.Logger, miSession *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
errCh := make(chan error, len(c.collectorFns))
errs := make([]error, 0, len(c.collectorFns))
@@ -255,10 +256,10 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
for _, fn := range c.collectorFns {
wg.Add(1)
go func(fn func(ch chan<- prometheus.Metric) error) {
go func(fn func(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error) {
defer wg.Done()
if err := fn(ch); err != nil {
if err := fn(ch, maxScrapeDuration); err != nil {
errCh <- err
}
}(fn)

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -63,9 +64,9 @@ type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
ThrowToCatchDepthPersec uint32 `mi:"ThrowToCatchDepthPersec"`
}
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrExceptions(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRExceptions"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRExceptions")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -57,9 +58,9 @@ type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
NumberofTLBimportsPersec uint32 `mi:"NumberofTLBimportsPersec"`
}
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrInterop(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRInterop
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRInterop"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRInterop")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -65,9 +66,9 @@ type Win32_PerfRawData_NETFramework_NETCLRJit struct {
TotalNumberofILBytesJitted uint32 `mi:"TotalNumberofILBytesJitted"`
}
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrJIT(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRJit
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRJit"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRJit")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -104,9 +105,9 @@ type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
TotalNumberofLoadFailures uint32 `mi:"TotalNumberofLoadFailures"`
}
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrLoading(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRLoading
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLoading"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLoading")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -86,9 +87,9 @@ type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
TotalNumberofContentions uint32 `mi:"TotalNumberofContentions"`
}
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrLocksAndThreads(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -20,6 +20,7 @@ package netframework
import (
"fmt"
"strconv"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -136,9 +137,9 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
PromotedMemoryfromGen1 uint64 `mi:"PromotedMemoryfromGen1"`
}
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrMemory(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRMemory
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRMemory"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRMemory")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -77,9 +78,9 @@ type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
TotalRemoteCalls uint32 `mi:"TotalRemoteCalls"`
}
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrRemoting(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRRemoting"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRRemoting")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -19,6 +19,7 @@ package netframework
import (
"fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types"
@@ -64,9 +65,9 @@ type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
TotalRuntimeChecks uint32 `mi:"TotalRuntimeChecks"`
}
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric) error {
func (c *Collector) collectClrSecurity(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRSecurity"))); err != nil {
if err := c.miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_PerfRawData_NETFramework_NETCLRSecurity")), maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -267,7 +268,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if err := c.collectAccept(ch); err != nil {

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"strconv"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi"
@@ -133,7 +134,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
ch <- prometheus.MustNewConstMetric(

View File

@@ -22,6 +22,7 @@ import (
"log/slog"
"os"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/psapi"
@@ -102,7 +103,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect Paging File metrics: %w", err)

View File

@@ -249,7 +249,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
var errs []error
for _, perfDataObject := range c.objects {

View File

@@ -42,7 +42,7 @@ func (a collectorAdapter) Describe(_ chan<- *prometheus.Desc) {}
// Collect implements the prometheus.Collector interface.
func (a collectorAdapter) Collect(ch chan<- prometheus.Metric) {
if err := a.Collector.Collect(ch); err != nil {
if err := a.Collector.Collect(ch, 0); err != nil {
panic(fmt.Sprintf("failed to update collector: %v", err))
}
}

View File

@@ -22,6 +22,7 @@ import (
"log/slog"
"regexp"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -225,7 +226,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect PhysicalDisk metrics: %w", err)

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"regexp"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -183,14 +184,14 @@ type wmiPrintJob struct {
Status string `mi:"Status"`
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var errs []error
if err := c.collectPrinterStatus(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect printer status metrics: %w", err))
}
if err := c.collectPrinterJobStatus(ch); err != nil {
if err := c.collectPrinterJobStatus(ch, maxScrapeDuration); err != nil {
errs = append(errs, fmt.Errorf("failed to collect printer job status metrics: %w", err))
}
@@ -199,7 +200,7 @@ func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
var printers []wmiPrinter
if err := c.miSession.Query(&printers, mi.NamespaceRootCIMv2, c.miQueryPrinter); err != nil {
if err := c.miSession.Query(&printers, mi.NamespaceRootCIMv2, c.miQueryPrinter, 0); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}
@@ -235,9 +236,9 @@ func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
return nil
}
func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric) error {
func (c *Collector) collectPrinterJobStatus(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
var printJobs []wmiPrintJob
if err := c.miSession.Query(&printJobs, mi.NamespaceRootCIMv2, c.miQueryPrinterJobs); err != nil {
if err := c.miSession.Query(&printJobs, mi.NamespaceRootCIMv2, c.miQueryPrinterJobs, maxScrapeDuration); err != nil {
return fmt.Errorf("WMI query failed: %w", err)
}

View File

@@ -26,6 +26,7 @@ import (
"strconv"
"strings"
"sync"
"time"
"unsafe"
"github.com/alecthomas/kingpin/v2"
@@ -332,7 +333,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
var workerProcesses []WorkerProcess
if err = c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
if err = c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery, 0); err != nil {
c.config.EnableWorkerProcess = false
return fmt.Errorf("WMI query for collector.process.iis failed: %w", err)
@@ -342,8 +343,8 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
return nil
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
return c.collect(ch)
func (c *Collector) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
return c.collect(ch, maxScrapeDuration)
}
// ref: https://github.com/microsoft/hcsshim/blob/8beabacfc2d21767a07c20f8dd5f9f3932dbf305/internal/uvm/stats.go#L25

View File

@@ -39,7 +39,7 @@ type processWorkerRequest struct {
workerProcesses []WorkerProcess
}
func (c *Collector) collect(ch chan<- prometheus.Metric) error {
func (c *Collector) collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect metrics: %w", err)
@@ -49,7 +49,7 @@ func (c *Collector) collect(ch chan<- prometheus.Metric) error {
var workerProcesses []WorkerProcess
if c.config.EnableWorkerProcess {
if err = c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery); err != nil {
if err = c.miSession.Query(&workerProcesses, mi.NamespaceRootWebAdministration, c.workerProcessMIQueryQuery, maxScrapeDuration); err != nil {
err = fmt.Errorf("WMI query for collector.process.iis failed: %w", err)
}
}

View File

@@ -22,6 +22,7 @@ import (
"fmt"
"log/slog"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -247,7 +248,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if err := c.collectRemoteFXNetworkCount(ch); err != nil {

View File

@@ -24,6 +24,7 @@ import (
"regexp"
"runtime"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/go-ole/go-ole"
@@ -173,7 +174,7 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error {
return nil
}
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
return c.collect(ch)
}

View File

@@ -25,6 +25,7 @@ import (
"regexp"
"strconv"
"sync"
"time"
"unsafe"
"github.com/alecthomas/kingpin/v2"
@@ -211,7 +212,7 @@ func (c *Collector) Close() error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
services, err := c.queryAllServices()
if err != nil {
return fmt.Errorf("failed to query all services: %w", err)

View File

@@ -20,6 +20,7 @@ package smb
import (
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -138,7 +139,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
}
// Collect collects smb metrics and sends them to prometheus.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect SMB Server Shares metrics: %w", err)

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"log/slog"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -199,7 +200,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
}
// Collect collects smb client metrics and sends them to prometheus.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect SMB Client Shares metrics: %w", err)

View File

@@ -21,6 +21,7 @@ import (
"fmt"
"log/slog"
"regexp"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -428,7 +429,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect SMTP Server metrics: %w", err)

View File

@@ -147,7 +147,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect System metrics: %w", err)

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"slices"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi"
@@ -212,7 +213,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {

View File

@@ -23,6 +23,7 @@ import (
"log/slog"
"strconv"
"strings"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/wtsapi32"
@@ -50,7 +51,7 @@ type Win32_ServerFeature struct {
func isConnectionBrokerServer(miSession *mi.Session) bool {
var dst []Win32_ServerFeature
if err := miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_ServerFeature"))); err != nil {
if err := miSession.Query(&dst, mi.NamespaceRootCIMv2, utils.Must(mi.NewQuery("SELECT * FROM Win32_ServerFeature")), 0); err != nil {
return false
}
@@ -260,7 +261,7 @@ func (c *Collector) Build(logger *slog.Logger, miSession *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if err := c.collectWTSSessions(ch); err != nil {

View File

@@ -303,7 +303,7 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) {
}
// Collect implements the Collector interface.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
mTimes := map[string]time.Time{}
// Create empty metricFamily slice here and append parsedFamilies to it inside the loop.

View File

@@ -53,7 +53,7 @@ func TestMultipleDirectories(t *testing.T) {
errCh := make(chan error, 1)
go func() {
errCh <- textFileCollector.Collect(metrics)
errCh <- textFileCollector.Collect(metrics, 0)
close(metrics)
}()
@@ -91,7 +91,7 @@ func TestDuplicateFileName(t *testing.T) {
errCh := make(chan error, 1)
go func() {
errCh <- textFileCollector.Collect(metrics)
errCh <- textFileCollector.Collect(metrics, 0)
close(metrics)
}()

View File

@@ -20,6 +20,7 @@ package thermalzone
import (
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -113,7 +114,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil {
return fmt.Errorf("failed to collect Thermal Zone Information metrics: %w", err)

View File

@@ -217,7 +217,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, collectorSystemTime) {
@@ -274,6 +274,8 @@ func (c *Collector) collectClockSource(ch chan<- prometheus.Metric) error {
return fmt.Errorf("failed to open registry key: %w", err)
}
defer key.Close()
val, _, err := key.GetStringValue("Type")
if err != nil {
return fmt.Errorf("failed to read 'Type' value: %w", err)
@@ -293,12 +295,6 @@ func (c *Collector) collectClockSource(ch chan<- prometheus.Metric) error {
)
}
if err := key.Close(); err != nil {
c.logger.Debug("failed to close registry key",
slog.Any("err", err),
)
}
return nil
}

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -127,7 +128,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
return c.collect(ch)
}

View File

@@ -155,7 +155,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
func (c *Collector) GetName() string { return Name }
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
c.mu.RLock()
defer c.mu.RUnlock()

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"log/slog"
"time"
"github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi"
@@ -231,7 +232,7 @@ func (c *Collector) Build(logger *slog.Logger, _ *mi.Session) error {
// Collect sends the metric values for each metric
// to the provided prometheus Metric channel.
func (c *Collector) Collect(ch chan<- prometheus.Metric) error {
func (c *Collector) Collect(ch chan<- prometheus.Metric, _ time.Duration) error {
errs := make([]error, 0)
if err := c.collectCpu(ch); err != nil {

View File

@@ -205,6 +205,16 @@ func (application *Application) NewOperationOptions() (*OperationOptions, error)
return operationOptions, nil
}
// MustNewOperationOptions is the panicking version of NewOperationOptions.
func (application *Application) MustNewOperationOptions() *OperationOptions {
operationOptions, err := application.NewOperationOptions()
if err != nil {
panic(fmt.Sprintf("failed to create operation options: %v", err))
}
return operationOptions
}
// NewDestinationOptions creates an DestinationOptions object that can be used with the Application.NewSession function.
//
// https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_newdestinationoptions

View File

@@ -257,7 +257,7 @@ func Test_MI_FD_Leak(t *testing.T) {
for range 300 {
var processes []win32Process
err := session.Query(&processes, mi.NamespaceRootCIMv2, queryPrinter)
err := session.Query(&processes, mi.NamespaceRootCIMv2, queryPrinter, -1)
require.NoError(t, err)
currentFileHandle, err = testutils.GetProcessHandleCount(windows.CurrentProcess())
@@ -287,3 +287,48 @@ func Test_MI_FD_Leak(t *testing.T) {
t.Log("Current File Handle Count: ", currentFileHandle)
}
func Test_MI_QueryTimeout(t *testing.T) {
application, err := mi.ApplicationInitialize()
require.NoError(t, err)
require.NotEmpty(t, application)
destinationOptions, err := application.NewDestinationOptions()
require.NoError(t, err)
require.NotEmpty(t, destinationOptions)
err = destinationOptions.SetTimeout(1 * time.Second)
require.NoError(t, err)
err = destinationOptions.SetLocale(mi.LocaleEnglish)
require.NoError(t, err)
session, err := application.NewSession(destinationOptions)
require.NoError(t, err)
require.NotEmpty(t, session)
operationOptions, err := application.NewOperationOptions()
require.NoError(t, err)
require.NotEmpty(t, operationOptions)
err = operationOptions.SetTimeout(1 * time.Millisecond)
require.NoError(t, err)
operation, err := session.QueryInstances(mi.OperationFlagsStandardRTTI, operationOptions, mi.NamespaceRootCIMv2, mi.QueryDialectWQL, "select Name from win32_process where handle = 0")
require.NoError(t, err)
require.NotEmpty(t, operation)
instance, moreResults, err := operation.GetInstance()
require.ErrorIs(t, err, mi.MI_RESULT_INVALID_OPERATION_TIMEOUT)
require.False(t, moreResults)
require.Empty(t, instance)
err = operation.Close()
require.NoError(t, err)
err = session.Close()
require.NoError(t, err)
err = application.Close()
require.NoError(t, err)
}

View File

@@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"reflect"
"strings"
"syscall"
"time"
"unsafe"
@@ -150,8 +151,35 @@ func (o *Operation) GetInstance() (*Instance, bool, error) {
uintptr(unsafe.Pointer(&errorMessageUTF16)),
uintptr(unsafe.Pointer(&errorDetails)),
)
//nolint:nestif
if !errors.Is(instanceResult, MI_RESULT_OK) {
return nil, false, fmt.Errorf("instance result: %w (%s)", instanceResult, windows.UTF16PtrToString(errorMessageUTF16))
errorMessage := strings.TrimSpace(windows.UTF16PtrToString(errorMessageUTF16))
// We need a language neutral way to detect an operation timeout, because MI_RESULT_OPERATION_TIMED_OUT
// is not returned by the API, but instead we get MI_RESULT_INVALID_OPERATION_TIMEOUT with a specific error code
// in the error details.
if errorDetails != nil {
count, _ := errorDetails.GetElementCount()
if count != 0 {
errorCodeRaw, err := errorDetails.GetElement("error_Code")
if err == nil {
errorCodeValue, _ := errorCodeRaw.GetValue()
errorCode, ok := errorCodeValue.(uint32)
if ok && errorCode == 262148 {
instanceResult = MI_RESULT_INVALID_OPERATION_TIMEOUT
errorMessage = ""
}
}
}
}
if errorMessage != "" {
errorMessage = fmt.Sprintf(" (%s)", errorMessage)
}
return nil, false, fmt.Errorf("instance result: %w%s", instanceResult, errorMessage)
}
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
@@ -273,6 +301,20 @@ func (o *OperationOptions) SetTimeout(timeout time.Duration) error {
return nil
}
func (o *OperationOptions) Close() error {
if o == nil || o.ft == nil {
return ErrNotInitialized
}
r0, _, _ := syscall.SyscallN(o.ft.Clone, uintptr(unsafe.Pointer(o)))
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
return result
}
return nil
}
func (o *OperationOptions) Delete() error {
if o == nil || o.ft == nil {
return ErrNotInitialized

View File

@@ -22,6 +22,7 @@ import (
"fmt"
"reflect"
"syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
@@ -229,7 +230,7 @@ func (s *Session) QueryUnmarshal(dst any,
)
if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
return result
return fmt.Errorf("failed to query instances: %w", result)
}
defer func() {
@@ -308,11 +309,28 @@ func (s *Session) QueryUnmarshal(dst any,
}
// Query queries for a set of instances based on a query expression.
func (s *Session) Query(dst any, namespaceName Namespace, queryExpression Query) error {
err := s.QueryUnmarshal(dst, OperationFlagsStandardRTTI, nil, namespaceName, QueryDialectWQL, queryExpression)
if err != nil {
return fmt.Errorf("WMI query failed: %w", err)
//
//nolint:nestif
func (s *Session) Query(dst any, namespaceName Namespace, queryExpression Query, queryTimeout time.Duration) error {
var operationOptions *OperationOptions
if queryTimeout >= 0 {
app, err := s.GetApplication()
if err != nil {
return fmt.Errorf("failed to get application: %w", err)
}
operationOptions, err = app.NewOperationOptions()
if err != nil {
return fmt.Errorf("failed to create operation options: %w", err)
}
if queryTimeout > 0 {
if err = operationOptions.SetTimeout(queryTimeout); err != nil {
return fmt.Errorf("failed to set timeout: %w", err)
}
}
}
return nil
return s.QueryUnmarshal(dst, OperationFlagsStandardRTTI, operationOptions, namespaceName, QueryDialectWQL, queryExpression)
}

View File

@@ -221,7 +221,7 @@ func NewCollectorWithReflection(logger *slog.Logger, resultType CounterType, obj
}
if counter.Type == PERF_ELAPSED_TIME {
if ret := GetCounterTimeBase(counterHandle, &counter.Frequency); ret != ErrorSuccess {
if ret := GetCounterTimeBase(counterHandle, &counter.Frequency); ret != ErrorSuccess && ret != NoData {
errs = append(errs, fmt.Errorf("GetCounterTimeBase: %w", NewPdhError(ret)))
continue

View File

@@ -60,8 +60,10 @@ func FuncBenchmarkCollector[C collector.Collector](b *testing.B, name string, co
}()
for b.Loop() {
require.NoError(b, c.Collect(metrics))
require.NoError(b, c.Collect(metrics, 0))
}
require.NoError(b, collectors.Close())
}
func TestCollector[C collector.Collector, V any](t *testing.T, fn func(*V) C, conf *V) {
@@ -110,7 +112,7 @@ func TestCollector[C collector.Collector, V any](t *testing.T, fn func(*V) C, co
time.Sleep(1 * time.Second)
err = c.Collect(ch)
err = c.Collect(ch, 0)
switch {
// container collector