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

@@ -1,6 +0,0 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="GoLinter" enabled="true" level="WARNING" enabled_by_default="true" />
</profile>
</component>

View File

@@ -20,6 +20,7 @@ package ad
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err) return fmt.Errorf("failed to collect DirectoryServices (AD) metrics: %w", err)

View File

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

View File

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

View File

@@ -20,6 +20,7 @@ package cache
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect Cache metrics: %w", err) return fmt.Errorf("failed to collect Cache metrics: %w", err)

View File

@@ -26,6 +26,7 @@ import (
"os" "os"
"slices" "slices"
"strings" "strings"
"time"
"unsafe" "unsafe"
"github.com/alecthomas/kingpin/v2" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorHCS) { if slices.Contains(c.config.CollectorsEnabled, subCollectorHCS) {

View File

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

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 c.miSession = miSession
var dst []miProcessor 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) return fmt.Errorf("WMI query failed: %w", err)
} }
@@ -176,9 +177,9 @@ type miProcessor struct {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"slices" "slices"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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. // Collect implements the Collector interface.
// Sends metric values for each metric to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, "connection") { if slices.Contains(c.config.CollectorsEnabled, "connection") {

View File

@@ -24,6 +24,7 @@ import (
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/dhcpsapi" "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 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 var errs []error
if slices.Contains(c.config.CollectorsEnabled, subCollectorServerMetrics) { if slices.Contains(c.config.CollectorsEnabled, subCollectorServerMetrics) {

View File

@@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 c.miSession = miSession
var dst []diskDrive 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) 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. // 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"slices" "slices"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
@@ -320,12 +321,17 @@ func (c *Collector) buildErrorStatsCollector(miSession *mi.Session) error {
c.miSession = miSession c.miSession = miSession
c.miQuery = query 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 return nil
} }
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) { 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 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)) 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 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 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) return fmt.Errorf("failed to query DNS statistics: %w", err)
} }

View File

@@ -24,6 +24,7 @@ import (
"os" "os"
"strings" "strings"
"sync" "sync"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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. // 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)) errCh := make(chan error, len(c.collectorFns))
errs := make([]error, 0, len(c.collectorFns)) errs := make([]error, 0, len(c.collectorFns))

View File

@@ -25,6 +25,7 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"sync" "sync"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/bmatcuk/doublestar/v4" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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{} wg := sync.WaitGroup{}
for _, filePattern := range c.config.FilePatterns { for _, filePattern := range c.config.FilePatterns {

View File

@@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 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) return fmt.Errorf("WMI query failed: %w", err)
} }
@@ -169,9 +170,9 @@ type msftFSRMQuota struct {
// Collect sends the metric values for each metric // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/cfgmgr32" "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...) 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) errs := make([]error, 0)
c.collectGpuInfo(ch) c.collectGpuInfo(ch)

View File

@@ -24,6 +24,7 @@ import (
"sort" "sort"
"strings" "strings"
"sync" "sync"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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)) errCh := make(chan error, len(c.collectorFns))
errs := make([]error, 0, len(c.collectorFns)) errs := make([]error, 0, len(c.collectorFns))

View File

@@ -24,6 +24,7 @@ import (
"regexp" "regexp"
"slices" "slices"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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( ch <- prometheus.MustNewConstMetric(
c.info, c.info,
prometheus.GaugeValue, prometheus.GaugeValue,

View File

@@ -19,6 +19,7 @@ package license
import ( import (
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/slc" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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() status, err := slc.SLIsWindowsGenuineLocal()
if err != nil { if err != nil {
return err return err

View File

@@ -29,6 +29,7 @@ import (
"slices" "slices"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/go-ole/go-ole" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 var info volumeInfo
err := c.perfDataCollector.Collect(&c.perfDataObject) err := c.perfDataCollector.Collect(&c.perfDataObject)

View File

@@ -24,6 +24,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if err := c.collectPDH(ch); err != nil { if err := c.collectPDH(ch); err != nil {

View File

@@ -24,6 +24,7 @@ import (
"slices" "slices"
"strings" "strings"
"sync" "sync"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 { if len(c.config.CollectorsEnabled) == 0 {
return nil return nil
} }
errCh := make(chan error, 6) errCh := make(chan error, 7)
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
wg.Add(6) wg.Add(7)
go func() { go func() {
defer wg.Done() defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorCluster) { 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) 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() defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorNetwork) { 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) 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) { if slices.Contains(c.config.CollectorsEnabled, subCollectorNode) {
var err error var err error
nodeNames, err = c.collectNode(ch) nodeNames, err = c.collectNode(ch, maxScrapeDuration)
if err != nil { if err != nil {
errCh <- fmt.Errorf("failed to collect node metrics: %w", err) 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() defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorResource) { 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) 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() defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorResourceGroup) { 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) 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() defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorSharedVolumes) { 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) errCh <- fmt.Errorf("failed to collect shared_volumes metrics: %w", err)
} }
} }
}()
go func() {
defer wg.Done()
if slices.Contains(c.config.CollectorsEnabled, subCollectorVirtualDisk) { 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) errCh <- fmt.Errorf("failed to collect virtualdisk metrics: %w", err)
} }
} }

View File

@@ -19,6 +19,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion" "github.com/prometheus-community/windows_exporter/internal/osversion"
@@ -673,16 +674,16 @@ func (c *Collector) buildCluster() error {
) )
var dst []msClusterCluster 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 fmt.Errorf("WMI query failed: %w", err)
} }
return nil 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -90,7 +91,7 @@ func (c *Collector) buildNetwork() error {
var dst []msClusterNetwork 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) 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 // Collect sends the metric values for each metric
// to the provided prometheus metric channel. // 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/osversion" "github.com/prometheus-community/windows_exporter/internal/osversion"
@@ -170,7 +171,7 @@ func (c *Collector) buildNode() error {
var dst []msClusterNode 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) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 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) return nil, fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -194,7 +195,7 @@ func (c *Collector) buildResource() error {
var dst []msClusterResource 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) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -168,7 +169,7 @@ func (c *Collector) buildResourceGroup() error {
var dst []msClusterResourceGroup 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) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -20,6 +20,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"strings" "strings"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -76,16 +77,16 @@ func (c *Collector) buildSharedVolumes() error {
) )
var dst []msClusterDiskPartition 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 fmt.Errorf("WMI query failed: %w", err)
} }
return nil 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package mscluster
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -92,13 +93,19 @@ func (c *Collector) buildVirtualDisk() error {
nil, 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 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -20,6 +20,7 @@ package msmq
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect MSMQ Queue metrics: %w", err) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 { if len(c.mssqlInstances) == 0 {
return fmt.Errorf("no SQL instances found: %w", pdh.ErrNoData) return fmt.Errorf("no SQL instances found: %w", pdh.ErrNoData)
} }

View File

@@ -25,6 +25,7 @@ import (
"regexp" "regexp"
"slices" "slices"
"strings" "strings"
"time"
"unsafe" "unsafe"
"github.com/alecthomas/kingpin/v2" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) { if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {

View File

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

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -63,9 +64,9 @@ type Win32_PerfRawData_NETFramework_NETCLRExceptions struct {
ThrowToCatchDepthPersec uint32 `mi:"ThrowToCatchDepthPersec"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -57,9 +58,9 @@ type Win32_PerfRawData_NETFramework_NETCLRInterop struct {
NumberofTLBimportsPersec uint32 `mi:"NumberofTLBimportsPersec"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -65,9 +66,9 @@ type Win32_PerfRawData_NETFramework_NETCLRJit struct {
TotalNumberofILBytesJitted uint32 `mi:"TotalNumberofILBytesJitted"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -104,9 +105,9 @@ type Win32_PerfRawData_NETFramework_NETCLRLoading struct {
TotalNumberofLoadFailures uint32 `mi:"TotalNumberofLoadFailures"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -86,9 +87,9 @@ type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct {
TotalNumberofContentions uint32 `mi:"TotalNumberofContentions"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -20,6 +20,7 @@ package netframework
import ( import (
"fmt" "fmt"
"strconv" "strconv"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -136,9 +137,9 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct {
PromotedMemoryfromGen1 uint64 `mi:"PromotedMemoryfromGen1"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -77,9 +78,9 @@ type Win32_PerfRawData_NETFramework_NETCLRRemoting struct {
TotalRemoteCalls uint32 `mi:"TotalRemoteCalls"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -19,6 +19,7 @@ package netframework
import ( import (
"fmt" "fmt"
"time"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
"github.com/prometheus-community/windows_exporter/internal/types" "github.com/prometheus-community/windows_exporter/internal/types"
@@ -64,9 +65,9 @@ type Win32_PerfRawData_NETFramework_NETCLRSecurity struct {
TotalRuntimeChecks uint32 `mi:"TotalRuntimeChecks"` 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

@@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if err := c.collectAccept(ch); err != nil { if err := c.collectAccept(ch); err != nil {

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/sysinfoapi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
ch <- prometheus.MustNewConstMetric( ch <- prometheus.MustNewConstMetric(

View File

@@ -22,6 +22,7 @@ import (
"log/slog" "log/slog"
"os" "os"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/psapi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect Paging File metrics: %w", err) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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 var errs []error
for _, perfDataObject := range c.objects { for _, perfDataObject := range c.objects {

View File

@@ -42,7 +42,7 @@ func (a collectorAdapter) Describe(_ chan<- *prometheus.Desc) {}
// Collect implements the prometheus.Collector interface. // Collect implements the prometheus.Collector interface.
func (a collectorAdapter) Collect(ch chan<- prometheus.Metric) { 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)) panic(fmt.Sprintf("failed to update collector: %v", err))
} }
} }

View File

@@ -22,6 +22,7 @@ import (
"log/slog" "log/slog"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect PhysicalDisk metrics: %w", err) return fmt.Errorf("failed to collect PhysicalDisk metrics: %w", err)

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"regexp" "regexp"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "github.com/prometheus-community/windows_exporter/internal/mi"
@@ -183,14 +184,14 @@ type wmiPrintJob struct {
Status string `mi:"Status"` 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 var errs []error
if err := c.collectPrinterStatus(ch); err != nil { if err := c.collectPrinterStatus(ch); err != nil {
errs = append(errs, fmt.Errorf("failed to collect printer status metrics: %w", err)) 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)) 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 { func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
var printers []wmiPrinter 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) return fmt.Errorf("WMI query failed: %w", err)
} }
@@ -235,9 +236,9 @@ func (c *Collector) collectPrinterStatus(ch chan<- prometheus.Metric) error {
return nil 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 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) return fmt.Errorf("WMI query failed: %w", err)
} }

View File

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

View File

@@ -39,7 +39,7 @@ type processWorkerRequest struct {
workerProcesses []WorkerProcess 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect metrics: %w", err) 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 var workerProcesses []WorkerProcess
if c.config.EnableWorkerProcess { 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) err = fmt.Errorf("WMI query for collector.process.iis failed: %w", err)
} }
} }

View File

@@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if err := c.collectRemoteFXNetworkCount(ch); err != nil { if err := c.collectRemoteFXNetworkCount(ch); err != nil {

View File

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

View File

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

View File

@@ -20,6 +20,7 @@ package smb
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect SMB Server Shares metrics: %w", err) return fmt.Errorf("failed to collect SMB Server Shares metrics: %w", err)

View File

@@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect SMB Client Shares metrics: %w", err) return fmt.Errorf("failed to collect SMB Client Shares metrics: %w", err)

View File

@@ -21,6 +21,7 @@ import (
"fmt" "fmt"
"log/slog" "log/slog"
"regexp" "regexp"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect SMTP Server metrics: %w", err) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect System metrics: %w", err) return fmt.Errorf("failed to collect System metrics: %w", err)

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"slices" "slices"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/iphlpapi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) { if slices.Contains(c.config.CollectorsEnabled, subCollectorMetrics) {

View File

@@ -23,6 +23,7 @@ import (
"log/slog" "log/slog"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/headers/wtsapi32" "github.com/prometheus-community/windows_exporter/internal/headers/wtsapi32"
@@ -50,7 +51,7 @@ type Win32_ServerFeature struct {
func isConnectionBrokerServer(miSession *mi.Session) bool { func isConnectionBrokerServer(miSession *mi.Session) bool {
var dst []Win32_ServerFeature 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 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if err := c.collectWTSSessions(ch); err != nil { 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. // 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{} mTimes := map[string]time.Time{}
// Create empty metricFamily slice here and append parsedFamilies to it inside the loop. // 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) errCh := make(chan error, 1)
go func() { go func() {
errCh <- textFileCollector.Collect(metrics) errCh <- textFileCollector.Collect(metrics, 0)
close(metrics) close(metrics)
}() }()
@@ -91,7 +91,7 @@ func TestDuplicateFileName(t *testing.T) {
errCh := make(chan error, 1) errCh := make(chan error, 1)
go func() { go func() {
errCh <- textFileCollector.Collect(metrics) errCh <- textFileCollector.Collect(metrics, 0)
close(metrics) close(metrics)
}() }()

View File

@@ -20,6 +20,7 @@ package thermalzone
import ( import (
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) err := c.perfDataCollector.Collect(&c.perfDataObject)
if err != nil { if err != nil {
return fmt.Errorf("failed to collect Thermal Zone Information metrics: %w", err) 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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if slices.Contains(c.config.CollectorsEnabled, collectorSystemTime) { 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) return fmt.Errorf("failed to open registry key: %w", err)
} }
defer key.Close()
val, _, err := key.GetStringValue("Type") val, _, err := key.GetStringValue("Type")
if err != nil { if err != nil {
return fmt.Errorf("failed to read 'Type' value: %w", err) 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 return nil
} }

View File

@@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) 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) 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() c.mu.RLock()
defer c.mu.RUnlock() defer c.mu.RUnlock()

View File

@@ -21,6 +21,7 @@ import (
"errors" "errors"
"fmt" "fmt"
"log/slog" "log/slog"
"time"
"github.com/alecthomas/kingpin/v2" "github.com/alecthomas/kingpin/v2"
"github.com/prometheus-community/windows_exporter/internal/mi" "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 // Collect sends the metric values for each metric
// to the provided prometheus Metric channel. // 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) errs := make([]error, 0)
if err := c.collectCpu(ch); err != nil { if err := c.collectCpu(ch); err != nil {

View File

@@ -205,6 +205,16 @@ func (application *Application) NewOperationOptions() (*OperationOptions, error)
return operationOptions, nil 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. // 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 // 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 { for range 300 {
var processes []win32Process var processes []win32Process
err := session.Query(&processes, mi.NamespaceRootCIMv2, queryPrinter) err := session.Query(&processes, mi.NamespaceRootCIMv2, queryPrinter, -1)
require.NoError(t, err) require.NoError(t, err)
currentFileHandle, err = testutils.GetProcessHandleCount(windows.CurrentProcess()) 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) 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" "errors"
"fmt" "fmt"
"reflect" "reflect"
"strings"
"syscall" "syscall"
"time" "time"
"unsafe" "unsafe"
@@ -150,8 +151,35 @@ func (o *Operation) GetInstance() (*Instance, bool, error) {
uintptr(unsafe.Pointer(&errorMessageUTF16)), uintptr(unsafe.Pointer(&errorMessageUTF16)),
uintptr(unsafe.Pointer(&errorDetails)), uintptr(unsafe.Pointer(&errorDetails)),
) )
//nolint:nestif
if !errors.Is(instanceResult, MI_RESULT_OK) { 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) { if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
@@ -273,6 +301,20 @@ func (o *OperationOptions) SetTimeout(timeout time.Duration) error {
return nil 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 { func (o *OperationOptions) Delete() error {
if o == nil || o.ft == nil { if o == nil || o.ft == nil {
return ErrNotInitialized return ErrNotInitialized

View File

@@ -22,6 +22,7 @@ import (
"fmt" "fmt"
"reflect" "reflect"
"syscall" "syscall"
"time"
"unsafe" "unsafe"
"golang.org/x/sys/windows" "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) { if result := ResultError(r0); !errors.Is(result, MI_RESULT_OK) {
return result return fmt.Errorf("failed to query instances: %w", result)
} }
defer func() { defer func() {
@@ -308,11 +309,28 @@ func (s *Session) QueryUnmarshal(dst any,
} }
// Query queries for a set of instances based on a query expression. // 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) //nolint:nestif
if err != nil { func (s *Session) Query(dst any, namespaceName Namespace, queryExpression Query, queryTimeout time.Duration) error {
return fmt.Errorf("WMI query failed: %w", err) 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 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))) errs = append(errs, fmt.Errorf("GetCounterTimeBase: %w", NewPdhError(ret)))
continue continue

View File

@@ -60,8 +60,10 @@ func FuncBenchmarkCollector[C collector.Collector](b *testing.B, name string, co
}() }()
for b.Loop() { 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) { 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) time.Sleep(1 * time.Second)
err = c.Collect(ch) err = c.Collect(ch, 0)
switch { switch {
// container collector // container collector

View File

@@ -136,7 +136,7 @@ func (c *Collection) collectCollector(ch chan<- prometheus.Metric, logger *slog.
close(bufCh) close(bufCh)
}() }()
errCh <- collector.Collect(bufCh) errCh <- collector.Collect(bufCh, maxScrapeDuration)
}() }()
wg := sync.WaitGroup{} wg := sync.WaitGroup{}

View File

@@ -244,6 +244,7 @@ func (c *Collection) Build(ctx context.Context, logger *slog.Logger) error {
errors.Is(err, registry.ErrNotExist) || errors.Is(err, registry.ErrNotExist) ||
errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) || errors.Is(err, pdh.NewPdhError(pdh.CstatusNoObject)) ||
errors.Is(err, pdh.NewPdhError(pdh.CstatusNoCounter)) || errors.Is(err, pdh.NewPdhError(pdh.CstatusNoCounter)) ||
errors.Is(err, mi.MI_RESULT_INVALID_OPERATION_TIMEOUT) ||
errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) { errors.Is(err, mi.MI_RESULT_INVALID_NAMESPACE) {
logger.LogAttrs(ctx, slog.LevelWarn, "couldn't initialize collector", slog.Any("err", err)) logger.LogAttrs(ctx, slog.LevelWarn, "couldn't initialize collector", slog.Any("err", err))

View File

@@ -52,7 +52,7 @@ type Collector interface {
// Build build the collector // Build build the collector
Build(logger *slog.Logger, miSession *mi.Session) error Build(logger *slog.Logger, miSession *mi.Session) error
// Collect Get new metrics and expose them via prometheus registry. // Collect Get new metrics and expose them via prometheus registry.
Collect(ch chan<- prometheus.Metric) (err error) Collect(ch chan<- prometheus.Metric, maxScrapeDuration time.Duration) (err error)
// Close closes the collector // Close closes the collector
Close() error Close() error
} }