diff --git a/Makefile b/Makefile index c15045a4ec..ad6d0d7e59 100644 --- a/Makefile +++ b/Makefile @@ -20,7 +20,7 @@ test: go test -v ./... bench: - go test -v -bench='benchmark(cpu|logicaldisk|physicaldisk|logon|memory|net|process|service|system|tcp|time)collector' ./... + go test -v -bench='benchmarkcollector' ./pkg/collector/{cpu,logical_disk,physical_disk,logon,memory,net,process,service,system,tcp,time} lint: golangci-lint -c .golangci.yaml run diff --git a/collector/ad_test.go b/collector/ad_test.go deleted file mode 100644 index b2d1b69654..0000000000 --- a/collector/ad_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkADCollector(b *testing.B) { - benchmarkCollector(b, "ad", newADCollector) -} diff --git a/collector/adcs_test.go b/collector/adcs_test.go deleted file mode 100644 index 5ef71052f8..0000000000 --- a/collector/adcs_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkADCSCollector(b *testing.B) { - benchmarkCollector(b, "adcs", adcsCollectorMethod) -} diff --git a/collector/adfs_test.go b/collector/adfs_test.go deleted file mode 100644 index 35db4d74de..0000000000 --- a/collector/adfs_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkADFSCollector(b *testing.B) { - benchmarkCollector(b, "adfs", newADFSCollector) -} diff --git a/collector/collector.go b/collector/collector.go deleted file mode 100644 index 90d3376587..0000000000 --- a/collector/collector.go +++ /dev/null @@ -1,159 +0,0 @@ -package collector - -import ( - "fmt" - "sort" - "strconv" - "strings" - - "github.com/prometheus-community/windows_exporter/perflib" - - "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "golang.org/x/sys/windows/registry" -) - -// ... -const ( - // TODO: Make package-local - Namespace = "windows" - - // Conversion factors - ticksToSecondsScaleFactor = 1 / 1e7 - windowsEpoch = 116444736000000000 -) - -// getWindowsVersion reads the version number of the OS from the Registry -// See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version -func getWindowsVersion(logger log.Logger) float64 { - k, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) - if err != nil { - _ = level.Warn(logger).Log("msg", "Couldn't open registry", "err", err) - return 0 - } - defer func() { - err = k.Close() - if err != nil { - _ = level.Warn(logger).Log("msg", "Failed to close registry key", "err", err) - } - }() - - currentv, _, err := k.GetStringValue("CurrentVersion") - if err != nil { - _ = level.Warn(logger).Log("msg", "Couldn't open registry to determine current Windows version", "err", err) - return 0 - } - - currentv_flt, err := strconv.ParseFloat(currentv, 64) - - _ = level.Debug(logger).Log("msg", fmt.Sprintf("Detected Windows version %f\n", currentv_flt)) - - return currentv_flt -} - -type collectorBuilder func(log.Logger) (Collector, error) -type flagsBuilder func(*kingpin.Application) -type perfCounterNamesBuilder func(log.Logger) []string - -var ( - builders = make(map[string]collectorBuilder) - perfCounterDependencies = make(map[string]string) -) - -func registerCollector(name string, builder collectorBuilder, perfCounterNames ...string) { - builders[name] = builder - addPerfCounterDependencies(name, perfCounterNames) -} - -func addPerfCounterDependencies(name string, perfCounterNames []string) { - perfIndicies := make([]string, 0, len(perfCounterNames)) - for _, cn := range perfCounterNames { - perfIndicies = append(perfIndicies, MapCounterToIndex(cn)) - } - perfCounterDependencies[name] = strings.Join(perfIndicies, " ") -} - -func Available() []string { - cs := make([]string, 0, len(builders)) - for c := range builders { - cs = append(cs, c) - } - return cs -} -func Build(collector string, logger log.Logger) (Collector, error) { - builder, exists := builders[collector] - if !exists { - return nil, fmt.Errorf("Unknown collector %q", collector) - } - return builder(logger) -} -func getPerfQuery(collectors []string) string { - parts := make([]string, 0, len(collectors)) - for _, c := range collectors { - if p := perfCounterDependencies[c]; p != "" { - parts = append(parts, p) - } - } - return strings.Join(parts, " ") -} - -// Collector is the interface a collector has to implement. -type Collector interface { - // Get new metrics and expose them via prometheus registry. - Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (err error) -} - -type ScrapeContext struct { - perfObjects map[string]*perflib.PerfObject -} - -// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape -func PrepareScrapeContext(collectors []string) (*ScrapeContext, error) { - q := getPerfQuery(collectors) // TODO: Memoize - objs, err := getPerflibSnapshot(q) - if err != nil { - return nil, err - } - - return &ScrapeContext{objs}, nil -} -func boolToFloat(b bool) float64 { - if b { - return 1.0 - } - return 0.0 -} - -func find(slice []string, val string) bool { - for _, item := range slice { - if item == val { - return true - } - } - return false -} - -// Used by more complex collectors where user input specifies enabled child collectors. -// Splits provided child collectors and deduplicate. -func expandEnabledChildCollectors(enabled string) []string { - separated := strings.Split(enabled, ",") - unique := map[string]bool{} - for _, s := range separated { - if s != "" { - unique[s] = true - } - } - result := make([]string, 0, len(unique)) - for s := range unique { - result = append(result, s) - } - // Ensure result is ordered, to prevent test failure - sort.Strings(result) - return result -} - -func milliSecToSec(t float64) float64 { - return t / 1000 -} diff --git a/collector/collector_test.go b/collector/collector_test.go deleted file mode 100644 index c69a493dd3..0000000000 --- a/collector/collector_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package collector - -import ( - "reflect" - "testing" - - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" -) - -func TestExpandChildCollectors(t *testing.T) { - cases := []struct { - name string - input string - expectedOutput []string - }{ - { - name: "simple", - input: "testing1,testing2,testing3", - expectedOutput: []string{"testing1", "testing2", "testing3"}, - }, - { - name: "duplicate", - input: "testing1,testing2,testing2,testing3", - expectedOutput: []string{"testing1", "testing2", "testing3"}, - }, - } - - for _, c := range cases { - t.Run(c.name, func(t *testing.T) { - output := expandEnabledChildCollectors(c.input) - if !reflect.DeepEqual(output, c.expectedOutput) { - t.Errorf("Output mismatch, expected %+v, got %+v", c.expectedOutput, output) - } - }) - } -} - -func benchmarkCollector(b *testing.B, name string, collectFunc func(logger log.Logger) (Collector, error)) { - // Create perflib scrape context. Some perflib collectors required a correct context, - // or will fail during benchmark. - scrapeContext, err := PrepareScrapeContext([]string{name}) - if err != nil { - b.Error(err) - } - c, err := collectFunc(log.NewNopLogger()) - if err != nil { - b.Error(err) - } - - metrics := make(chan prometheus.Metric) - go func() { - for { - <-metrics - } - }() - - for i := 0; i < b.N; i++ { - c.Collect(scrapeContext, metrics) //nolint:errcheck - } -} diff --git a/collector/container.go b/collector/container.go deleted file mode 100644 index 5f559ea5ca..0000000000 --- a/collector/container.go +++ /dev/null @@ -1,372 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "fmt" - "strings" - - "github.com/Microsoft/hcsshim" - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -// A ContainerMetricsCollector is a Prometheus collector for containers metrics -type ContainerMetricsCollector struct { - logger log.Logger - - // Presence - ContainerAvailable *prometheus.Desc - - // Number of containers - ContainersCount *prometheus.Desc - // memory - UsageCommitBytes *prometheus.Desc - UsageCommitPeakBytes *prometheus.Desc - UsagePrivateWorkingSetBytes *prometheus.Desc - - // CPU - RuntimeTotal *prometheus.Desc - RuntimeUser *prometheus.Desc - RuntimeKernel *prometheus.Desc - - // Network - BytesReceived *prometheus.Desc - BytesSent *prometheus.Desc - PacketsReceived *prometheus.Desc - PacketsSent *prometheus.Desc - DroppedPacketsIncoming *prometheus.Desc - DroppedPacketsOutgoing *prometheus.Desc - - // Storage - ReadCountNormalized *prometheus.Desc - ReadSizeBytes *prometheus.Desc - WriteCountNormalized *prometheus.Desc - WriteSizeBytes *prometheus.Desc -} - -// newContainerMetricsCollector constructs a new ContainerMetricsCollector -func newContainerMetricsCollector(logger log.Logger) (Collector, error) { - const subsystem = "container" - return &ContainerMetricsCollector{ - logger: log.With(logger, "collector", subsystem), - - ContainerAvailable: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "available"), - "Available", - []string{"container_id"}, - nil, - ), - ContainersCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "count"), - "Number of containers", - nil, - nil, - ), - UsageCommitBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memory_usage_commit_bytes"), - "Memory Usage Commit Bytes", - []string{"container_id"}, - nil, - ), - UsageCommitPeakBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memory_usage_commit_peak_bytes"), - "Memory Usage Commit Peak Bytes", - []string{"container_id"}, - nil, - ), - UsagePrivateWorkingSetBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memory_usage_private_working_set_bytes"), - "Memory Usage Private Working Set Bytes", - []string{"container_id"}, - nil, - ), - RuntimeTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_total"), - "Total Run time in Seconds", - []string{"container_id"}, - nil, - ), - RuntimeUser: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_usermode"), - "Run Time in User mode in Seconds", - []string{"container_id"}, - nil, - ), - RuntimeKernel: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_usage_seconds_kernelmode"), - "Run time in Kernel mode in Seconds", - []string{"container_id"}, - nil, - ), - BytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "network_receive_bytes_total"), - "Bytes Received on Interface", - []string{"container_id", "interface"}, - nil, - ), - BytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "network_transmit_bytes_total"), - "Bytes Sent on Interface", - []string{"container_id", "interface"}, - nil, - ), - PacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "network_receive_packets_total"), - "Packets Received on Interface", - []string{"container_id", "interface"}, - nil, - ), - PacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "network_transmit_packets_total"), - "Packets Sent on Interface", - []string{"container_id", "interface"}, - nil, - ), - DroppedPacketsIncoming: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "network_receive_packets_dropped_total"), - "Dropped Incoming Packets on Interface", - []string{"container_id", "interface"}, - nil, - ), - DroppedPacketsOutgoing: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "network_transmit_packets_dropped_total"), - "Dropped Outgoing Packets on Interface", - []string{"container_id", "interface"}, - nil, - ), - ReadCountNormalized: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "storage_read_count_normalized_total"), - "Read Count Normalized", - []string{"container_id"}, - nil, - ), - ReadSizeBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "storage_read_size_bytes_total"), - "Read Size Bytes", - []string{"container_id"}, - nil, - ), - WriteCountNormalized: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "storage_write_count_normalized_total"), - "Write Count Normalized", - []string{"container_id"}, - nil, - ), - WriteSizeBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "storage_write_size_bytes_total"), - "Write Size Bytes", - []string{"container_id"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *ContainerMetricsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("msg", "failed collecting ContainerMetricsCollector metrics", "desc", desc, "err", err) - return err - } - return nil -} - -// containerClose closes the container resource -func (c *ContainerMetricsCollector) containerClose(container hcsshim.Container) { - err := container.Close() - if err != nil { - _ = level.Error(c.logger).Log("err", err) - } -} - -func (c *ContainerMetricsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - - // Types Container is passed to get the containers compute systems only - containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}}) - if err != nil { - _ = level.Error(c.logger).Log("msg", "Err in Getting containers", "err", err) - return nil, err - } - - count := len(containers) - - ch <- prometheus.MustNewConstMetric( - c.ContainersCount, - prometheus.GaugeValue, - float64(count), - ) - if count == 0 { - return nil, nil - } - - containerPrefixes := make(map[string]string) - - for _, containerDetails := range containers { - container, err := hcsshim.OpenContainer(containerDetails.ID) - if container != nil { - defer c.containerClose(container) - } - if err != nil { - _ = level.Error(c.logger).Log("msg", "err in opening container", "containerId", containerDetails.ID, "err", err) - continue - } - - cstats, err := container.Statistics() - if err != nil { - _ = level.Error(c.logger).Log("msg", "err in fetching container Statistics", "containerId", containerDetails.ID, "err", err) - continue - } - - containerIdWithPrefix := getContainerIdWithPrefix(containerDetails) - containerPrefixes[containerDetails.ID] = containerIdWithPrefix - - ch <- prometheus.MustNewConstMetric( - c.ContainerAvailable, - prometheus.CounterValue, - 1, - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.UsageCommitBytes, - prometheus.GaugeValue, - float64(cstats.Memory.UsageCommitBytes), - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.UsageCommitPeakBytes, - prometheus.GaugeValue, - float64(cstats.Memory.UsageCommitPeakBytes), - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.UsagePrivateWorkingSetBytes, - prometheus.GaugeValue, - float64(cstats.Memory.UsagePrivateWorkingSetBytes), - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.RuntimeTotal, - prometheus.CounterValue, - float64(cstats.Processor.TotalRuntime100ns)*ticksToSecondsScaleFactor, - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.RuntimeUser, - prometheus.CounterValue, - float64(cstats.Processor.RuntimeUser100ns)*ticksToSecondsScaleFactor, - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.RuntimeKernel, - prometheus.CounterValue, - float64(cstats.Processor.RuntimeKernel100ns)*ticksToSecondsScaleFactor, - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.ReadCountNormalized, - prometheus.CounterValue, - float64(cstats.Storage.ReadCountNormalized), - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.ReadSizeBytes, - prometheus.CounterValue, - float64(cstats.Storage.ReadSizeBytes), - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.WriteCountNormalized, - prometheus.CounterValue, - float64(cstats.Storage.WriteCountNormalized), - containerIdWithPrefix, - ) - ch <- prometheus.MustNewConstMetric( - c.WriteSizeBytes, - prometheus.CounterValue, - float64(cstats.Storage.WriteSizeBytes), - containerIdWithPrefix, - ) - } - - hnsEndpoints, err := hcsshim.HNSListEndpointRequest() - if err != nil { - _ = level.Warn(c.logger).Log("msg", "Failed to collect network stats for containers") - return nil, nil - } - - if len(hnsEndpoints) == 0 { - _ = level.Info(c.logger).Log("msg", fmt.Sprintf("No network stats for containers to collect")) - return nil, nil - } - - for _, endpoint := range hnsEndpoints { - endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id) - if err != nil { - _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for interface %s", endpoint.Id), "err", err) - continue - } - - for _, containerId := range endpoint.SharedContainers { - containerIdWithPrefix, ok := containerPrefixes[containerId] - endpointId := strings.ToUpper(endpoint.Id) - - if !ok { - _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for container %s", containerId)) - continue - } - - ch <- prometheus.MustNewConstMetric( - c.BytesReceived, - prometheus.CounterValue, - float64(endpointStats.BytesReceived), - containerIdWithPrefix, endpointId, - ) - - ch <- prometheus.MustNewConstMetric( - c.BytesSent, - prometheus.CounterValue, - float64(endpointStats.BytesSent), - containerIdWithPrefix, endpointId, - ) - ch <- prometheus.MustNewConstMetric( - c.PacketsReceived, - prometheus.CounterValue, - float64(endpointStats.PacketsReceived), - containerIdWithPrefix, endpointId, - ) - ch <- prometheus.MustNewConstMetric( - c.PacketsSent, - prometheus.CounterValue, - float64(endpointStats.PacketsSent), - containerIdWithPrefix, endpointId, - ) - ch <- prometheus.MustNewConstMetric( - c.DroppedPacketsIncoming, - prometheus.CounterValue, - float64(endpointStats.DroppedPacketsIncoming), - containerIdWithPrefix, endpointId, - ) - ch <- prometheus.MustNewConstMetric( - c.DroppedPacketsOutgoing, - prometheus.CounterValue, - float64(endpointStats.DroppedPacketsOutgoing), - containerIdWithPrefix, endpointId, - ) - } - } - - return nil, nil -} - -func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string { - switch containerDetails.Owner { - case "containerd-shim-runhcs-v1.exe": - return "containerd://" + containerDetails.ID - default: - // default to docker or if owner is not set - return "docker://" + containerDetails.ID - } -} diff --git a/collector/container_test.go b/collector/container_test.go deleted file mode 100644 index 002f38ad10..0000000000 --- a/collector/container_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkContainerCollector(b *testing.B) { - benchmarkCollector(b, "container", newContainerMetricsCollector) -} diff --git a/collector/cpu_test.go b/collector/cpu_test.go deleted file mode 100644 index 4788e5983e..0000000000 --- a/collector/cpu_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkCPUCollector(b *testing.B) { - benchmarkCollector(b, "cpu", newCPUCollector) -} diff --git a/collector/cs.go b/collector/cs.go deleted file mode 100644 index 0a089f7945..0000000000 --- a/collector/cs.go +++ /dev/null @@ -1,108 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus-community/windows_exporter/headers/sysinfoapi" - "github.com/prometheus/client_golang/prometheus" -) - -// A CSCollector is a Prometheus collector for WMI metrics -type CSCollector struct { - logger log.Logger - - PhysicalMemoryBytes *prometheus.Desc - LogicalProcessors *prometheus.Desc - Hostname *prometheus.Desc -} - -// newCSCollector ... -func newCSCollector(logger log.Logger) (Collector, error) { - const subsystem = "cs" - - return &CSCollector{ - logger: log.With(logger, "collector", subsystem), - - LogicalProcessors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "logical_processors"), - "ComputerSystem.NumberOfLogicalProcessors", - nil, - nil, - ), - PhysicalMemoryBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "physical_memory_bytes"), - "ComputerSystem.TotalPhysicalMemory", - nil, - nil, - ), - Hostname: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "hostname"), - "Labeled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain", - []string{ - "hostname", - "domain", - "fqdn"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *CSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("msg", "failed collecting cs metrics", "desc", desc, "err", err) - return err - } - return nil -} - -func (c *CSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - // Get systeminfo for number of processors - systemInfo := sysinfoapi.GetSystemInfo() - - // Get memory status for physical memory - mem, err := sysinfoapi.GlobalMemoryStatusEx() - if err != nil { - return nil, err - } - - ch <- prometheus.MustNewConstMetric( - c.LogicalProcessors, - prometheus.GaugeValue, - float64(systemInfo.NumberOfProcessors), - ) - - ch <- prometheus.MustNewConstMetric( - c.PhysicalMemoryBytes, - prometheus.GaugeValue, - float64(mem.TotalPhys), - ) - - hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname) - if err != nil { - return nil, err - } - domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain) - if err != nil { - return nil, err - } - fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified) - if err != nil { - return nil, err - } - - ch <- prometheus.MustNewConstMetric( - c.Hostname, - prometheus.GaugeValue, - 1.0, - hostname, - domain, - fqdn, - ) - - return nil, nil -} diff --git a/collector/cs_test.go b/collector/cs_test.go deleted file mode 100644 index 0816029008..0000000000 --- a/collector/cs_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkCsCollector(b *testing.B) { - benchmarkCollector(b, "cs", newCSCollector) -} diff --git a/collector/dfsr_test.go b/collector/dfsr_test.go deleted file mode 100644 index fd24a63b52..0000000000 --- a/collector/dfsr_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkDFSRCollector(b *testing.B) { - benchmarkCollector(b, "dfsr", newDFSRCollector) -} diff --git a/collector/dhcp_test.go b/collector/dhcp_test.go deleted file mode 100644 index 1c8b717b77..0000000000 --- a/collector/dhcp_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkDHCPCollector(b *testing.B) { - benchmarkCollector(b, "dhcp", newDhcpCollector) -} diff --git a/collector/diskdrive_test.go b/collector/diskdrive_test.go deleted file mode 100644 index 933e4e372e..0000000000 --- a/collector/diskdrive_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkDiskDriveCollector(b *testing.B) { - benchmarkCollector(b, "disk_drive", newDiskDriveInfoCollector) -} diff --git a/collector/dns_test.go b/collector/dns_test.go deleted file mode 100644 index 9f42945f38..0000000000 --- a/collector/dns_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkDNSCollector(b *testing.B) { - benchmarkCollector(b, "dns", newDNSCollector) -} diff --git a/collector/exchange_test.go b/collector/exchange_test.go deleted file mode 100644 index 465f245a7a..0000000000 --- a/collector/exchange_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkExchangeCollector(b *testing.B) { - benchmarkCollector(b, "exchange", newExchangeCollector) -} diff --git a/collector/fsrmquota.go b/collector/fsrmquota.go deleted file mode 100644 index 1ed582734d..0000000000 --- a/collector/fsrmquota.go +++ /dev/null @@ -1,188 +0,0 @@ -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -type FSRMQuotaCollector struct { - logger log.Logger - - QuotasCount *prometheus.Desc - Path *prometheus.Desc - PeakUsage *prometheus.Desc - Size *prometheus.Desc - Usage *prometheus.Desc - - Description *prometheus.Desc - Disabled *prometheus.Desc - MatchesTemplate *prometheus.Desc - SoftLimit *prometheus.Desc - Template *prometheus.Desc -} - -func newFSRMQuotaCollector(logger log.Logger) (Collector, error) { - const subsystem = "fsrmquota" - return &FSRMQuotaCollector{ - logger: log.With(logger, "collector", subsystem), - - QuotasCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "count"), - "Number of Quotas", - nil, - nil, - ), - PeakUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "peak_usage_bytes"), - "The highest amount of disk space usage charged to this quota. (PeakUsage)", - []string{"path", "template"}, - nil, - ), - Size: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "size_bytes"), - "The size of the quota. (Size)", - []string{"path", "template"}, - nil, - ), - Usage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usage_bytes"), - "The current amount of disk space usage charged to this quota. (Usage)", - []string{"path", "template"}, - nil, - ), - Description: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "description"), - "Description of the quota (Description)", - []string{"path", "template", "description"}, - nil, - ), - Disabled: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "disabled"), - "If 1, the quota is disabled. The default value is 0. (Disabled)", - []string{"path", "template"}, - nil, - ), - SoftLimit: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "softlimit"), - "If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)", - []string{"path", "template"}, - nil, - ), - Template: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "template"), - "Quota template name. (Template)", - []string{"path", "template"}, - nil, - ), - MatchesTemplate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "matchestemplate"), - "If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)", - []string{"path", "template"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *FSRMQuotaCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("msg", "failed collecting fsrmquota metrics", "desc", desc, "err", err) - return err - } - return nil -} - -// MSFT_FSRMQuota docs: -// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota -type MSFT_FSRMQuota struct { - Name string - - Path string - PeakUsage uint64 - Size uint64 - Usage uint64 - Description string - Template string - //Threshold string - Disabled bool - MatchesTemplate bool - SoftLimit bool -} - -func (c *FSRMQuotaCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []MSFT_FSRMQuota - q := queryAll(&dst, c.logger) - - var count int - - if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil { - return nil, err - } - - for _, quota := range dst { - - count++ - path := quota.Path - template := quota.Template - Description := quota.Description - - ch <- prometheus.MustNewConstMetric( - c.PeakUsage, - prometheus.GaugeValue, - float64(quota.PeakUsage), - path, - template, - ) - ch <- prometheus.MustNewConstMetric( - c.Size, - prometheus.GaugeValue, - float64(quota.Size), - path, - template, - ) - ch <- prometheus.MustNewConstMetric( - c.Usage, - prometheus.GaugeValue, - float64(quota.Usage), - path, - template, - ) - ch <- prometheus.MustNewConstMetric( - c.Description, - prometheus.GaugeValue, - 1.0, - path, template, Description, - ) - ch <- prometheus.MustNewConstMetric( - c.Disabled, - prometheus.GaugeValue, - boolToFloat(quota.Disabled), - path, - template, - ) - ch <- prometheus.MustNewConstMetric( - c.MatchesTemplate, - prometheus.GaugeValue, - boolToFloat(quota.MatchesTemplate), - path, - template, - ) - ch <- prometheus.MustNewConstMetric( - c.SoftLimit, - prometheus.GaugeValue, - boolToFloat(quota.SoftLimit), - path, - template, - ) - } - - ch <- prometheus.MustNewConstMetric( - c.QuotasCount, - prometheus.GaugeValue, - float64(count), - ) - return nil, nil -} diff --git a/collector/fsrmquota_test.go b/collector/fsrmquota_test.go deleted file mode 100644 index 03f42cee74..0000000000 --- a/collector/fsrmquota_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkFsrmQuotaCollector(b *testing.B) { - benchmarkCollector(b, "fsrmquota", newFSRMQuotaCollector) -} diff --git a/collector/hyperv_test.go b/collector/hyperv_test.go deleted file mode 100644 index 1898965e06..0000000000 --- a/collector/hyperv_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkHypervCollector(b *testing.B) { - benchmarkCollector(b, "hyperv", newHyperVCollector) -} diff --git a/collector/init.go b/collector/init.go deleted file mode 100644 index 7fb07df983..0000000000 --- a/collector/init.go +++ /dev/null @@ -1,423 +0,0 @@ -package collector - -import ( - "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" -) - -// collectorInit represents the required initialisation config for a collector. -type collectorInit struct { - // Name of collector to be initialised - name string - // Builder function for the collector - flags flagsBuilder - // Builder function for the collector - builder collectorBuilder - // Perflib counter names for the collector. - // These will be included in the Perflib scrape scope by the exporter. - perfCounterFunc perfCounterNamesBuilder -} - -func getDFSRCollectorDeps(_ log.Logger) []string { - // Perflib sources are dynamic, depending on the enabled child collectors - var perflibDependencies []string - for _, source := range expandEnabledChildCollectors(*dfsrEnabledCollectors) { - perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source)) - } - - return perflibDependencies -} - -var collectors = []collectorInit{ - { - name: "ad", - flags: nil, - builder: newADCollector, - perfCounterFunc: nil, - }, - { - name: "adcs", - flags: nil, - builder: adcsCollectorMethod, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Certification Authority"} - }, - }, - { - name: "adfs", - flags: nil, - builder: newADFSCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"AD FS"} - }, - }, - { - name: "cache", - flags: nil, - builder: newCacheCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Cache"} - }, - }, - { - name: "container", - flags: nil, - builder: newContainerMetricsCollector, - perfCounterFunc: nil, - }, - { - name: "cpu", - flags: nil, - builder: newCPUCollector, - perfCounterFunc: func(logger log.Logger) []string { - if getWindowsVersion(logger) > 6.05 { - return []string{"Processor Information"} - } - return []string{"Processor"} - }, - }, - { - name: "cpu_info", - flags: nil, - builder: newCpuInfoCollector, - perfCounterFunc: nil, - }, - { - name: "cs", - flags: nil, - builder: newCSCollector, - perfCounterFunc: nil, - }, - { - name: "dfsr", - flags: newDFSRCollectorFlags, - builder: newDFSRCollector, - perfCounterFunc: getDFSRCollectorDeps, - }, - { - name: "dhcp", - flags: nil, - builder: newDhcpCollector, - perfCounterFunc: nil, - }, - { - name: "diskdrive", - flags: nil, - builder: newDiskDriveInfoCollector, - perfCounterFunc: nil, - }, - { - name: "dns", - flags: nil, - builder: newDNSCollector, - perfCounterFunc: nil, - }, - { - name: "exchange", - flags: newExchangeCollectorFlags, - builder: newExchangeCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{ - "MSExchange ADAccess Processes", - "MSExchangeTransport Queues", - "MSExchange HttpProxy", - "MSExchange ActiveSync", - "MSExchange Availability Service", - "MSExchange OWA", - "MSExchangeAutodiscover", - "MSExchange WorkloadManagement Workloads", - "MSExchange RpcClientAccess", - } - }, - }, - { - name: "fsrmquota", - flags: nil, - builder: newFSRMQuotaCollector, - perfCounterFunc: nil, - }, - { - name: "hyperv", - flags: nil, - builder: newHyperVCollector, - perfCounterFunc: nil, - }, - { - name: "iis", - flags: newIISCollectorFlags, - builder: newIISCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{ - "Web Service", - "APP_POOL_WAS", - "Web Service Cache", - "W3SVC_W3WP", - } - }, - }, - { - name: "logical_disk", - flags: newLogicalDiskCollectorFlags, - builder: newLogicalDiskCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"LogicalDisk"} - }, - }, - { - name: "logon", - flags: nil, - builder: newLogonCollector, - perfCounterFunc: nil, - }, - { - name: "memory", - flags: nil, - builder: newMemoryCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Memory"} - }, - }, - { - name: "mscluster_cluster", - flags: nil, - builder: newMSCluster_ClusterCollector, - perfCounterFunc: nil, - }, - { - name: "mscluster_network", - flags: nil, - builder: newMSCluster_NetworkCollector, - perfCounterFunc: nil, - }, - { - name: "mscluster_node", - flags: nil, - builder: newMSCluster_NodeCollector, - perfCounterFunc: nil, - }, - { - name: "mscluster_resource", - flags: nil, - builder: newMSCluster_ResourceCollector, - perfCounterFunc: nil, - }, - { - name: "mscluster_resourcegroup", - flags: nil, - builder: newMSCluster_ResourceGroupCollector, - perfCounterFunc: nil, - }, - { - name: "msmq", - flags: newMSMQCollectorFlags, - builder: newMSMQCollector, - perfCounterFunc: nil, - }, - { - name: "mssql", - flags: newMSSQLCollectorFlags, - builder: newMSSQLCollector, - perfCounterFunc: nil, - }, - { - name: "net", - flags: newNetworkCollectorFlags, - builder: newNetworkCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Network Interface"} - }, - }, - { - name: "netframework_clrexceptions", - flags: nil, - builder: newNETFramework_NETCLRExceptionsCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrinterop", - flags: nil, - builder: newNETFramework_NETCLRInteropCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrjit", - flags: nil, - builder: newNETFramework_NETCLRJitCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrloading", - flags: nil, - builder: newNETFramework_NETCLRLoadingCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrlocksandthreads", - flags: nil, - builder: newNETFramework_NETCLRLocksAndThreadsCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrmemory", - flags: nil, - builder: newNETFramework_NETCLRMemoryCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrremoting", - flags: nil, - builder: newNETFramework_NETCLRRemotingCollector, - perfCounterFunc: nil, - }, - { - name: "netframework_clrsecurity", - flags: nil, - builder: newNETFramework_NETCLRSecurityCollector, - perfCounterFunc: nil, - }, - { - name: "nps", - builder: newNPSCollector, - perfCounterFunc: nil, - }, - { - name: "os", - flags: nil, - builder: newOSCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Paging File"} - }, - }, - { - name: "physical_disk", - flags: newPhysicalDiskCollectorFlags, - builder: NewPhysicalDiskCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"PhysicalDisk"} - }, - }, - { - name: "process", - flags: newProcessCollectorFlags, - builder: newProcessCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Process"} - }, - }, - { - name: "remote_fx", - flags: nil, - builder: newRemoteFx, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"RemoteFX Network"} - }, - }, - { - name: "scheduled_task", - flags: newScheduledTaskFlags, - builder: newScheduledTask, - perfCounterFunc: nil, - }, - { - name: "service", - flags: newServiceCollectorFlags, - builder: newserviceCollector, - perfCounterFunc: nil, - }, - { - name: "smtp", - flags: newSMTPCollectorFlags, - builder: newSMTPCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"SMTP Server"} - }, - }, - { - name: "system", - flags: nil, - builder: newSystemCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"System"} - }, - }, - { - name: "teradici_pcoip", - flags: nil, - builder: newTeradiciPcoipCollector, - perfCounterFunc: nil, - }, - { - name: "tcp", - flags: nil, - builder: newTCPCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"TCPv4"} - }, - }, - { - name: "terminal_services", - flags: nil, - builder: newTerminalServicesCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{ - "Terminal Services", - "Terminal Services Session", - "Remote Desktop Connection Broker Counterset", - } - }, - }, - { - name: "textfile", - flags: newTextFileCollectorFlags, - builder: newTextFileCollector, - perfCounterFunc: nil, - }, - { - name: "thermalzone", - flags: nil, - builder: newThermalZoneCollector, - perfCounterFunc: nil, - }, - { - name: "time", - flags: nil, - builder: newTimeCollector, - perfCounterFunc: func(_ log.Logger) []string { - return []string{"Windows Time Service"} - }, - }, - { - name: "vmware", - flags: nil, - builder: newVmwareCollector, - perfCounterFunc: nil, - }, - { - name: "vmware_blast", - flags: nil, - builder: newVmwareBlastCollector, - perfCounterFunc: nil, - }, -} - -// RegisterCollectorsFlags To be called by the exporter for collector initialisation before running app.Parse -func RegisterCollectorsFlags(app *kingpin.Application) { - for _, v := range collectors { - if v.flags != nil { - v.flags(app) - } - } -} - -// RegisterCollectors To be called by the exporter for collector initialisation -func RegisterCollectors(logger log.Logger) { - for _, v := range collectors { - var perfCounterNames []string - - if v.perfCounterFunc != nil { - perfCounterNames = v.perfCounterFunc(logger) - } - - registerCollector(v.name, v.builder, perfCounterNames...) - } -} diff --git a/collector/logical_disk.go b/collector/logical_disk.go deleted file mode 100644 index ef7398a1da..0000000000 --- a/collector/logical_disk.go +++ /dev/null @@ -1,391 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "errors" - "fmt" - "regexp" - - "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -const ( - FlagLogicalDiskVolumeOldExclude = "collector.logical_disk.volume-blacklist" - FlagLogicalDiskVolumeOldInclude = "collector.logical_disk.volume-whitelist" - - FlagLogicalDiskVolumeExclude = "collector.logical_disk.volume-exclude" - FlagLogicalDiskVolumeInclude = "collector.logical_disk.volume-include" -) - -var ( - volumeOldInclude *string - volumeOldExclude *string - - volumeInclude *string - volumeExclude *string - - volumeIncludeSet bool - volumeExcludeSet bool -) - -// A LogicalDiskCollector is a Prometheus collector for perflib logicalDisk metrics -type LogicalDiskCollector struct { - logger log.Logger - - RequestsQueued *prometheus.Desc - AvgReadQueue *prometheus.Desc - AvgWriteQueue *prometheus.Desc - ReadBytesTotal *prometheus.Desc - ReadsTotal *prometheus.Desc - WriteBytesTotal *prometheus.Desc - WritesTotal *prometheus.Desc - ReadTime *prometheus.Desc - WriteTime *prometheus.Desc - TotalSpace *prometheus.Desc - FreeSpace *prometheus.Desc - IdleTime *prometheus.Desc - SplitIOs *prometheus.Desc - ReadLatency *prometheus.Desc - WriteLatency *prometheus.Desc - ReadWriteLatency *prometheus.Desc - - volumeIncludePattern *regexp.Regexp - volumeExcludePattern *regexp.Regexp -} - -// newLogicalDiskCollectorFlags ... -func newLogicalDiskCollectorFlags(app *kingpin.Application) { - volumeInclude = app.Flag( - FlagLogicalDiskVolumeInclude, - "Regexp of volumes to include. Volume name must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - volumeIncludeSet = true - return nil - }).String() - - volumeExclude = app.Flag( - FlagLogicalDiskVolumeExclude, - "Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - volumeExcludeSet = true - return nil - }).String() - - volumeOldInclude = app.Flag( - FlagLogicalDiskVolumeOldInclude, - "DEPRECATED: Use --collector.logical_disk.volume-include", - ).Hidden().String() - volumeOldExclude = app.Flag( - FlagLogicalDiskVolumeOldExclude, - "DEPRECATED: Use --collector.logical_disk.volume-exclude", - ).Hidden().String() -} - -// newLogicalDiskCollector ... -func newLogicalDiskCollector(logger log.Logger) (Collector, error) { - const subsystem = "logical_disk" - logger = log.With(logger, "collector", subsystem) - - if *volumeOldExclude != "" { - if !volumeExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.logical_disk.volume-blacklist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-exclude") - *volumeExclude = *volumeOldExclude - } else { - return nil, errors.New("--collector.logical_disk.volume-blacklist and --collector.logical_disk.volume-exclude are mutually exclusive") - } - } - if *volumeOldInclude != "" { - if !volumeIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.logical_disk.volume-whitelist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-include") - *volumeInclude = *volumeOldInclude - } else { - return nil, errors.New("--collector.logical_disk.volume-whitelist and --collector.logical_disk.volume-include are mutually exclusive") - } - } - - return &LogicalDiskCollector{ - logger: logger, - - RequestsQueued: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "requests_queued"), - "The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)", - []string{"volume"}, - nil, - ), - - AvgReadQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "avg_read_requests_queued"), - "Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)", - []string{"volume"}, - nil, - ), - - AvgWriteQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "avg_write_requests_queued"), - "Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)", - []string{"volume"}, - nil, - ), - - ReadBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"), - "The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)", - []string{"volume"}, - nil, - ), - - ReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "reads_total"), - "The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)", - []string{"volume"}, - nil, - ), - - WriteBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"), - "The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)", - []string{"volume"}, - nil, - ), - - WritesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "writes_total"), - "The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)", - []string{"volume"}, - nil, - ), - - ReadTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_seconds_total"), - "Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)", - []string{"volume"}, - nil, - ), - - WriteTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_seconds_total"), - "Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)", - []string{"volume"}, - nil, - ), - - FreeSpace: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "free_bytes"), - "Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)", - []string{"volume"}, - nil, - ), - - TotalSpace: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "size_bytes"), - "Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)", - []string{"volume"}, - nil, - ), - - IdleTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "idle_seconds_total"), - "Seconds that the disk was idle (LogicalDisk.PercentIdleTime)", - []string{"volume"}, - nil, - ), - - SplitIOs: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "split_ios_total"), - "The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)", - []string{"volume"}, - nil, - ), - - ReadLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_latency_seconds_total"), - "Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)", - []string{"volume"}, - nil, - ), - - WriteLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_latency_seconds_total"), - "Shows the average time, in seconds, of a write operation to the disk (LogicalDisk.AvgDiskSecPerWrite)", - []string{"volume"}, - nil, - ), - - ReadWriteLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_write_latency_seconds_total"), - "Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)", - []string{"volume"}, - nil, - ), - - volumeIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeInclude)), - volumeExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *volumeExclude)), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *LogicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting logical_disk metrics", "desc", desc, "err", err) - return err - } - return nil -} - -// Win32_PerfRawData_PerfDisk_LogicalDisk docs: -// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class -// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference -type logicalDisk struct { - Name string - CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` - AvgDiskReadQueueLength float64 `perflib:"Avg. Disk Read Queue Length"` - AvgDiskWriteQueueLength float64 `perflib:"Avg. Disk Write Queue Length"` - DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"` - DiskReadsPerSec float64 `perflib:"Disk Reads/sec"` - DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"` - DiskWritesPerSec float64 `perflib:"Disk Writes/sec"` - PercentDiskReadTime float64 `perflib:"% Disk Read Time"` - PercentDiskWriteTime float64 `perflib:"% Disk Write Time"` - PercentFreeSpace float64 `perflib:"% Free Space_Base"` - PercentFreeSpace_Base float64 `perflib:"Free Megabytes"` - PercentIdleTime float64 `perflib:"% Idle Time"` - SplitIOPerSec float64 `perflib:"Split IO/Sec"` - AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"` - AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"` - AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"` -} - -func (c *LogicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []logicalDisk - if err := unmarshalObject(ctx.perfObjects["LogicalDisk"], &dst, c.logger); err != nil { - return nil, err - } - - for _, volume := range dst { - if volume.Name == "_Total" || - c.volumeExcludePattern.MatchString(volume.Name) || - !c.volumeIncludePattern.MatchString(volume.Name) { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.RequestsQueued, - prometheus.GaugeValue, - volume.CurrentDiskQueueLength, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.AvgReadQueue, - prometheus.GaugeValue, - volume.AvgDiskReadQueueLength*ticksToSecondsScaleFactor, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.AvgWriteQueue, - prometheus.GaugeValue, - volume.AvgDiskWriteQueueLength*ticksToSecondsScaleFactor, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadBytesTotal, - prometheus.CounterValue, - volume.DiskReadBytesPerSec, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadsTotal, - prometheus.CounterValue, - volume.DiskReadsPerSec, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteBytesTotal, - prometheus.CounterValue, - volume.DiskWriteBytesPerSec, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.WritesTotal, - prometheus.CounterValue, - volume.DiskWritesPerSec, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadTime, - prometheus.CounterValue, - volume.PercentDiskReadTime, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteTime, - prometheus.CounterValue, - volume.PercentDiskWriteTime, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.FreeSpace, - prometheus.GaugeValue, - volume.PercentFreeSpace_Base*1024*1024, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalSpace, - prometheus.GaugeValue, - volume.PercentFreeSpace*1024*1024, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.IdleTime, - prometheus.CounterValue, - volume.PercentIdleTime, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.SplitIOs, - prometheus.CounterValue, - volume.SplitIOPerSec, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadLatency, - prometheus.CounterValue, - volume.AvgDiskSecPerRead*ticksToSecondsScaleFactor, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteLatency, - prometheus.CounterValue, - volume.AvgDiskSecPerWrite*ticksToSecondsScaleFactor, - volume.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadWriteLatency, - prometheus.CounterValue, - volume.AvgDiskSecPerTransfer*ticksToSecondsScaleFactor, - volume.Name, - ) - } - - return nil, nil -} diff --git a/collector/logical_disk_test.go b/collector/logical_disk_test.go deleted file mode 100644 index 51120df30c..0000000000 --- a/collector/logical_disk_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkLogicalDiskCollector(b *testing.B) { - // Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all disks. - localVolumeInclude := ".+" - volumeInclude = &localVolumeInclude - - benchmarkCollector(b, "logical_disk", newLogicalDiskCollector) -} diff --git a/collector/logon_test.go b/collector/logon_test.go deleted file mode 100644 index 423d083cd5..0000000000 --- a/collector/logon_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkLogonCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newLogonCollector) -} diff --git a/collector/memory.go b/collector/memory.go deleted file mode 100644 index 5239476ff2..0000000000 --- a/collector/memory.go +++ /dev/null @@ -1,513 +0,0 @@ -// returns data points from Win32_PerfRawData_PerfOS_Memory -// - Win32_PerfRawData_PerfOS_Memory class - -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -// A MemoryCollector is a Prometheus collector for perflib Memory metrics -type MemoryCollector struct { - logger log.Logger - - AvailableBytes *prometheus.Desc - CacheBytes *prometheus.Desc - CacheBytesPeak *prometheus.Desc - CacheFaultsTotal *prometheus.Desc - CommitLimit *prometheus.Desc - CommittedBytes *prometheus.Desc - DemandZeroFaultsTotal *prometheus.Desc - FreeAndZeroPageListBytes *prometheus.Desc - FreeSystemPageTableEntries *prometheus.Desc - ModifiedPageListBytes *prometheus.Desc - PageFaultsTotal *prometheus.Desc - SwapPageReadsTotal *prometheus.Desc - SwapPagesReadTotal *prometheus.Desc - SwapPagesWrittenTotal *prometheus.Desc - SwapPageOperationsTotal *prometheus.Desc - SwapPageWritesTotal *prometheus.Desc - PoolNonpagedAllocsTotal *prometheus.Desc - PoolNonpagedBytes *prometheus.Desc - PoolPagedAllocsTotal *prometheus.Desc - PoolPagedBytes *prometheus.Desc - PoolPagedResidentBytes *prometheus.Desc - StandbyCacheCoreBytes *prometheus.Desc - StandbyCacheNormalPriorityBytes *prometheus.Desc - StandbyCacheReserveBytes *prometheus.Desc - SystemCacheResidentBytes *prometheus.Desc - SystemCodeResidentBytes *prometheus.Desc - SystemCodeTotalBytes *prometheus.Desc - SystemDriverResidentBytes *prometheus.Desc - SystemDriverTotalBytes *prometheus.Desc - TransitionFaultsTotal *prometheus.Desc - TransitionPagesRepurposedTotal *prometheus.Desc - WriteCopiesTotal *prometheus.Desc -} - -// newMemoryCollector ... -func newMemoryCollector(logger log.Logger) (Collector, error) { - const subsystem = "memory" - - return &MemoryCollector{ - logger: log.With(logger, "collector", subsystem), - - AvailableBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "available_bytes"), - "The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+ - " the standby (cached), free and zero page lists (AvailableBytes)", - nil, - nil, - ), - CacheBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cache_bytes"), - "(CacheBytes)", - nil, - nil, - ), - CacheBytesPeak: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cache_bytes_peak"), - "(CacheBytesPeak)", - nil, - nil, - ), - CacheFaultsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cache_faults_total"), - "Number of faults which occur when a page sought in the file system cache is not found there and must be retrieved from elsewhere in memory (soft fault) "+ - "or from disk (hard fault) (Cache Faults/sec)", - nil, - nil, - ), - CommitLimit: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "commit_limit"), - "(CommitLimit)", - nil, - nil, - ), - CommittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "committed_bytes"), - "(CommittedBytes)", - nil, - nil, - ), - DemandZeroFaultsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "demand_zero_faults_total"), - "The number of zeroed pages required to satisfy faults. Zeroed pages, pages emptied of previously stored data and filled with zeros, are a security"+ - " feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (Demand Zero Faults/sec)", - nil, - nil, - ), - FreeAndZeroPageListBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "free_and_zero_page_list_bytes"), - "The amount of physical memory, in bytes, that is assigned to the free and zero page lists. This memory does not contain cached data. It is immediately"+ - " available for allocation to a process or for system use (FreeAndZeroPageListBytes)", - nil, - nil, - ), - FreeSystemPageTableEntries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "free_system_page_table_entries"), - "(FreeSystemPageTableEntries)", - nil, - nil, - ), - ModifiedPageListBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "modified_page_list_bytes"), - "The amount of physical memory, in bytes, that is assigned to the modified page list. This memory contains cached data and code that is not actively in "+ - "use by processes, the system and the system cache (ModifiedPageListBytes)", - nil, - nil, - ), - PageFaultsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"), - "Overall rate at which faulted pages are handled by the processor (Page Faults/sec)", - nil, - nil, - ), - SwapPageReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "swap_page_reads_total"), - "Number of disk page reads (a single read operation reading several pages is still only counted once) (PageReadsPersec)", - nil, - nil, - ), - SwapPagesReadTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "swap_pages_read_total"), - "Number of pages read across all page reads (ie counting all pages read even if they are read in a single operation) (PagesInputPersec)", - nil, - nil, - ), - SwapPagesWrittenTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "swap_pages_written_total"), - "Number of pages written across all page writes (ie counting all pages written even if they are written in a single operation) (PagesOutputPersec)", - nil, - nil, - ), - SwapPageOperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "swap_page_operations_total"), - "Total number of swap page read and writes (PagesPersec)", - nil, - nil, - ), - SwapPageWritesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "swap_page_writes_total"), - "Number of disk page writes (a single write operation writing several pages is still only counted once) (PageWritesPersec)", - nil, - nil, - ), - PoolNonpagedAllocsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_allocs_total"), - "The number of calls to allocate space in the nonpaged pool. The nonpaged pool is an area of system memory area for objects that cannot be written"+ - " to disk, and must remain in physical memory as long as they are allocated (PoolNonpagedAllocs)", - nil, - nil, - ), - PoolNonpagedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_nonpaged_bytes"), - "Number of bytes in the non-paged pool, an area of the system virtual memory that is used for objects that cannot be written to disk, but must "+ - "remain in physical memory as long as they are allocated (PoolNonpagedBytes)", - nil, - nil, - ), - PoolPagedAllocsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_paged_allocs_total"), - "Number of calls to allocate space in the paged pool, regardless of the amount of space allocated in each call (PoolPagedAllocs)", - nil, - nil, - ), - PoolPagedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_paged_bytes"), - "(PoolPagedBytes)", - nil, - nil, - ), - PoolPagedResidentBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_paged_resident_bytes"), - "The size, in bytes, of the portion of the paged pool that is currently resident and active in physical memory. The paged pool is an area of the "+ - "system virtual memory that is used for objects that can be written to disk when they are not being used (PoolPagedResidentBytes)", - nil, - nil, - ), - StandbyCacheCoreBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "standby_cache_core_bytes"), - "The amount of physical memory, in bytes, that is assigned to the core standby cache page lists. This memory contains cached data and code that is "+ - "not actively in use by processes, the system and the system cache (StandbyCacheCoreBytes)", - nil, - nil, - ), - StandbyCacheNormalPriorityBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "standby_cache_normal_priority_bytes"), - "The amount of physical memory, in bytes, that is assigned to the normal priority standby cache page lists. This memory contains cached data and "+ - "code that is not actively in use by processes, the system and the system cache (StandbyCacheNormalPriorityBytes)", - nil, - nil, - ), - StandbyCacheReserveBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "standby_cache_reserve_bytes"), - "The amount of physical memory, in bytes, that is assigned to the reserve standby cache page lists. This memory contains cached data and code "+ - "that is not actively in use by processes, the system and the system cache (StandbyCacheReserveBytes)", - nil, - nil, - ), - SystemCacheResidentBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_cache_resident_bytes"), - "The size, in bytes, of the portion of the system file cache which is currently resident and active in physical memory (SystemCacheResidentBytes)", - nil, - nil, - ), - SystemCodeResidentBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_code_resident_bytes"), - "The size, in bytes, of the pageable operating system code that is currently resident and active in physical memory (SystemCodeResidentBytes)", - nil, - nil, - ), - SystemCodeTotalBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_code_total_bytes"), - "The size, in bytes, of the pageable operating system code currently mapped into the system virtual address space (SystemCodeTotalBytes)", - nil, - nil, - ), - SystemDriverResidentBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_driver_resident_bytes"), - "The size, in bytes, of the pageable physical memory being used by device drivers. It is the working set (physical memory area) of the drivers (SystemDriverResidentBytes)", - nil, - nil, - ), - SystemDriverTotalBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_driver_total_bytes"), - "The size, in bytes, of the pageable virtual memory currently being used by device drivers. Pageable memory can be written to disk when it is not being used (SystemDriverTotalBytes)", - nil, - nil, - ), - TransitionFaultsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transition_faults_total"), - "Number of faults rate at which page faults are resolved by recovering pages that were being used by another process sharing the page, or were on the "+ - "modified page list or the standby list, or were being written to disk at the time of the page fault (TransitionFaultsPersec)", - nil, - nil, - ), - TransitionPagesRepurposedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transition_pages_repurposed_total"), - "Transition Pages RePurposed is the rate at which the number of transition cache pages were reused for a different purpose (TransitionPagesRePurposedPersec)", - nil, - nil, - ), - WriteCopiesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_copies_total"), - "The number of page faults caused by attempting to write that were satisfied by copying the page from elsewhere in physical memory (WriteCopiesPersec)", - nil, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *MemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting memory metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type memory struct { - AvailableBytes float64 `perflib:"Available Bytes"` - AvailableKBytes float64 `perflib:"Available KBytes"` - AvailableMBytes float64 `perflib:"Available MBytes"` - CacheBytes float64 `perflib:"Cache Bytes"` - CacheBytesPeak float64 `perflib:"Cache Bytes Peak"` - CacheFaultsPersec float64 `perflib:"Cache Faults/sec"` - CommitLimit float64 `perflib:"Commit Limit"` - CommittedBytes float64 `perflib:"Committed Bytes"` - DemandZeroFaultsPersec float64 `perflib:"Demand Zero Faults/sec"` - FreeAndZeroPageListBytes float64 `perflib:"Free & Zero Page List Bytes"` - FreeSystemPageTableEntries float64 `perflib:"Free System Page Table Entries"` - ModifiedPageListBytes float64 `perflib:"Modified Page List Bytes"` - PageFaultsPersec float64 `perflib:"Page Faults/sec"` - PageReadsPersec float64 `perflib:"Page Reads/sec"` - PagesInputPersec float64 `perflib:"Pages Input/sec"` - PagesOutputPersec float64 `perflib:"Pages Output/sec"` - PagesPersec float64 `perflib:"Pages/sec"` - PageWritesPersec float64 `perflib:"Page Writes/sec"` - PoolNonpagedAllocs float64 `perflib:"Pool Nonpaged Allocs"` - PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` - PoolPagedAllocs float64 `perflib:"Pool Paged Allocs"` - PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` - PoolPagedResidentBytes float64 `perflib:"Pool Paged Resident Bytes"` - StandbyCacheCoreBytes float64 `perflib:"Standby Cache Core Bytes"` - StandbyCacheNormalPriorityBytes float64 `perflib:"Standby Cache Normal Priority Bytes"` - StandbyCacheReserveBytes float64 `perflib:"Standby Cache Reserve Bytes"` - SystemCacheResidentBytes float64 `perflib:"System Cache Resident Bytes"` - SystemCodeResidentBytes float64 `perflib:"System Code Resident Bytes"` - SystemCodeTotalBytes float64 `perflib:"System Code Total Bytes"` - SystemDriverResidentBytes float64 `perflib:"System Driver Resident Bytes"` - SystemDriverTotalBytes float64 `perflib:"System Driver Total Bytes"` - TransitionFaultsPersec float64 `perflib:"Transition Faults/sec"` - TransitionPagesRePurposedPersec float64 `perflib:"Transition Pages RePurposed/sec"` - WriteCopiesPersec float64 `perflib:"Write Copies/sec"` -} - -func (c *MemoryCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []memory - if err := unmarshalObject(ctx.perfObjects["Memory"], &dst, c.logger); err != nil { - return nil, err - } - - ch <- prometheus.MustNewConstMetric( - c.AvailableBytes, - prometheus.GaugeValue, - dst[0].AvailableBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.CacheBytes, - prometheus.GaugeValue, - dst[0].CacheBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.CacheBytesPeak, - prometheus.GaugeValue, - dst[0].CacheBytesPeak, - ) - - ch <- prometheus.MustNewConstMetric( - c.CacheFaultsTotal, - prometheus.CounterValue, - dst[0].CacheFaultsPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.CommitLimit, - prometheus.GaugeValue, - dst[0].CommitLimit, - ) - - ch <- prometheus.MustNewConstMetric( - c.CommittedBytes, - prometheus.GaugeValue, - dst[0].CommittedBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.DemandZeroFaultsTotal, - prometheus.CounterValue, - dst[0].DemandZeroFaultsPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.FreeAndZeroPageListBytes, - prometheus.GaugeValue, - dst[0].FreeAndZeroPageListBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.FreeSystemPageTableEntries, - prometheus.GaugeValue, - dst[0].FreeSystemPageTableEntries, - ) - - ch <- prometheus.MustNewConstMetric( - c.ModifiedPageListBytes, - prometheus.GaugeValue, - dst[0].ModifiedPageListBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.PageFaultsTotal, - prometheus.CounterValue, - dst[0].PageFaultsPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.SwapPageReadsTotal, - prometheus.CounterValue, - dst[0].PageReadsPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.SwapPagesReadTotal, - prometheus.CounterValue, - dst[0].PagesInputPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.SwapPagesWrittenTotal, - prometheus.CounterValue, - dst[0].PagesOutputPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.SwapPageOperationsTotal, - prometheus.CounterValue, - dst[0].PagesPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.SwapPageWritesTotal, - prometheus.CounterValue, - dst[0].PageWritesPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.PoolNonpagedAllocsTotal, - prometheus.GaugeValue, - dst[0].PoolNonpagedAllocs, - ) - - ch <- prometheus.MustNewConstMetric( - c.PoolNonpagedBytes, - prometheus.GaugeValue, - dst[0].PoolNonpagedBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.PoolPagedAllocsTotal, - prometheus.CounterValue, - dst[0].PoolPagedAllocs, - ) - - ch <- prometheus.MustNewConstMetric( - c.PoolPagedBytes, - prometheus.GaugeValue, - dst[0].PoolPagedBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.PoolPagedResidentBytes, - prometheus.GaugeValue, - dst[0].PoolPagedResidentBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.StandbyCacheCoreBytes, - prometheus.GaugeValue, - dst[0].StandbyCacheCoreBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.StandbyCacheNormalPriorityBytes, - prometheus.GaugeValue, - dst[0].StandbyCacheNormalPriorityBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.StandbyCacheReserveBytes, - prometheus.GaugeValue, - dst[0].StandbyCacheReserveBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.SystemCacheResidentBytes, - prometheus.GaugeValue, - dst[0].SystemCacheResidentBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.SystemCodeResidentBytes, - prometheus.GaugeValue, - dst[0].SystemCodeResidentBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.SystemCodeTotalBytes, - prometheus.GaugeValue, - dst[0].SystemCodeTotalBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.SystemDriverResidentBytes, - prometheus.GaugeValue, - dst[0].SystemDriverResidentBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.SystemDriverTotalBytes, - prometheus.GaugeValue, - dst[0].SystemDriverTotalBytes, - ) - - ch <- prometheus.MustNewConstMetric( - c.TransitionFaultsTotal, - prometheus.CounterValue, - dst[0].TransitionFaultsPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.TransitionPagesRepurposedTotal, - prometheus.CounterValue, - dst[0].TransitionPagesRePurposedPersec, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteCopiesTotal, - prometheus.CounterValue, - dst[0].WriteCopiesPersec, - ) - - return nil, nil -} diff --git a/collector/memory_test.go b/collector/memory_test.go deleted file mode 100644 index 8dd5e9246d..0000000000 --- a/collector/memory_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkMemoryCollector(b *testing.B) { - benchmarkCollector(b, "memory", newMemoryCollector) -} diff --git a/collector/mscluster_network.go b/collector/mscluster_network.go deleted file mode 100644 index 6a4fb5d4d4..0000000000 --- a/collector/mscluster_network.go +++ /dev/null @@ -1,117 +0,0 @@ -package collector - -import ( - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A MSCluster_NetworkCollector is a Prometheus collector for WMI MSCluster_Network metrics -type MSCluster_NetworkCollector struct { - logger log.Logger - - Characteristics *prometheus.Desc - Flags *prometheus.Desc - Metric *prometheus.Desc - Role *prometheus.Desc - State *prometheus.Desc -} - -func newMSCluster_NetworkCollector(logger log.Logger) (Collector, error) { - const subsystem = "mscluster_network" - return &MSCluster_NetworkCollector{ - logger: log.With(logger, "collector", subsystem), - - Characteristics: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "characteristics"), - "Provides the characteristics of the network.", - []string{"name"}, - nil, - ), - Flags: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "flags"), - "Provides access to the flags set for the node. ", - []string{"name"}, - nil, - ), - Metric: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "metric"), - "The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false.", - []string{"name"}, - nil, - ), - Role: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "role"), - "Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both ", - []string{"name"}, - nil, - ), - State: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "state"), - "Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up", - []string{"name"}, - nil, - ), - }, nil -} - -// MSCluster_Network docs: -// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network -type MSCluster_Network struct { - Name string - - Characteristics uint - Flags uint - Metric uint - Role uint - State uint -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *MSCluster_NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - var dst []MSCluster_Network - q := queryAll(&dst, c.logger) - if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { - return err - } - - for _, v := range dst { - ch <- prometheus.MustNewConstMetric( - c.Characteristics, - prometheus.GaugeValue, - float64(v.Characteristics), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Flags, - prometheus.GaugeValue, - float64(v.Flags), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Metric, - prometheus.GaugeValue, - float64(v.Metric), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Role, - prometheus.GaugeValue, - float64(v.Role), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.State, - prometheus.GaugeValue, - float64(v.State), - v.Name, - ) - } - - return nil -} diff --git a/collector/mscluster_node.go b/collector/mscluster_node.go deleted file mode 100644 index e6ce25b244..0000000000 --- a/collector/mscluster_node.go +++ /dev/null @@ -1,252 +0,0 @@ -package collector - -import ( - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A MSCluster_NodeCollector is a Prometheus collector for WMI MSCluster_Node metrics -type MSCluster_NodeCollector struct { - logger log.Logger - - BuildNumber *prometheus.Desc - Characteristics *prometheus.Desc - DetectedCloudPlatform *prometheus.Desc - DynamicWeight *prometheus.Desc - Flags *prometheus.Desc - MajorVersion *prometheus.Desc - MinorVersion *prometheus.Desc - NeedsPreventQuorum *prometheus.Desc - NodeDrainStatus *prometheus.Desc - NodeHighestVersion *prometheus.Desc - NodeLowestVersion *prometheus.Desc - NodeWeight *prometheus.Desc - State *prometheus.Desc - StatusInformation *prometheus.Desc -} - -func newMSCluster_NodeCollector(logger log.Logger) (Collector, error) { - const subsystem = "mscluster_node" - return &MSCluster_NodeCollector{ - logger: log.With(logger, "collector", subsystem), - BuildNumber: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "build_number"), - "Provides access to the node's BuildNumber property.", - []string{"name"}, - nil, - ), - Characteristics: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "characteristics"), - "Provides access to the characteristics set for the node.", - []string{"name"}, - nil, - ), - DetectedCloudPlatform: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "detected_cloud_platform"), - "(DetectedCloudPlatform)", - []string{"name"}, - nil, - ), - DynamicWeight: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dynamic_weight"), - "The dynamic vote weight of the node adjusted by dynamic quorum feature.", - []string{"name"}, - nil, - ), - Flags: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "flags"), - "Provides access to the flags set for the node.", - []string{"name"}, - nil, - ), - MajorVersion: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "major_version"), - "Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed.", - []string{"name"}, - nil, - ), - MinorVersion: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "minor_version"), - "Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed.", - []string{"name"}, - nil, - ), - NeedsPreventQuorum: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "needs_prevent_quorum"), - "Whether the cluster service on that node should be started with prevent quorum flag.", - []string{"name"}, - nil, - ), - NodeDrainStatus: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "node_drain_status"), - "The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed", - []string{"name"}, - nil, - ), - NodeHighestVersion: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "node_highest_version"), - "Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate.", - []string{"name"}, - nil, - ), - NodeLowestVersion: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "node_lowest_version"), - "Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate.", - []string{"name"}, - nil, - ), - NodeWeight: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "node_weight"), - "The vote weight of the node.", - []string{"name"}, - nil, - ), - State: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "state"), - "Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining", - []string{"name"}, - nil, - ), - StatusInformation: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "status_information"), - "The isolation or quarantine status of the node.", - []string{"name"}, - nil, - ), - }, nil -} - -// MSCluster_Node docs: -// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node -type MSCluster_Node struct { - Name string - - BuildNumber uint - Characteristics uint - DetectedCloudPlatform uint - DynamicWeight uint - Flags uint - MajorVersion uint - MinorVersion uint - NeedsPreventQuorum uint - NodeDrainStatus uint - NodeHighestVersion uint - NodeLowestVersion uint - NodeWeight uint - State uint - StatusInformation uint -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *MSCluster_NodeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - var dst []MSCluster_Node - q := queryAll(&dst, c.logger) - if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { - return err - } - - for _, v := range dst { - - ch <- prometheus.MustNewConstMetric( - c.BuildNumber, - prometheus.GaugeValue, - float64(v.BuildNumber), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Characteristics, - prometheus.GaugeValue, - float64(v.Characteristics), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.DetectedCloudPlatform, - prometheus.GaugeValue, - float64(v.DetectedCloudPlatform), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.DynamicWeight, - prometheus.GaugeValue, - float64(v.DynamicWeight), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Flags, - prometheus.GaugeValue, - float64(v.Flags), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.MajorVersion, - prometheus.GaugeValue, - float64(v.MajorVersion), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.MinorVersion, - prometheus.GaugeValue, - float64(v.MinorVersion), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NeedsPreventQuorum, - prometheus.GaugeValue, - float64(v.NeedsPreventQuorum), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NodeDrainStatus, - prometheus.GaugeValue, - float64(v.NodeDrainStatus), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NodeHighestVersion, - prometheus.GaugeValue, - float64(v.NodeHighestVersion), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NodeLowestVersion, - prometheus.GaugeValue, - float64(v.NodeLowestVersion), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NodeWeight, - prometheus.GaugeValue, - float64(v.NodeWeight), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.State, - prometheus.GaugeValue, - float64(v.State), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.StatusInformation, - prometheus.GaugeValue, - float64(v.StatusInformation), - v.Name, - ) - } - - return nil -} diff --git a/collector/mscluster_resource.go b/collector/mscluster_resource.go deleted file mode 100644 index 2cddc90f32..0000000000 --- a/collector/mscluster_resource.go +++ /dev/null @@ -1,284 +0,0 @@ -package collector - -import ( - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A MSCluster_ResourceCollector is a Prometheus collector for WMI MSCluster_Resource metrics -type MSCluster_ResourceCollector struct { - logger log.Logger - - Characteristics *prometheus.Desc - DeadlockTimeout *prometheus.Desc - EmbeddedFailureAction *prometheus.Desc - Flags *prometheus.Desc - IsAlivePollInterval *prometheus.Desc - LooksAlivePollInterval *prometheus.Desc - MonitorProcessId *prometheus.Desc - PendingTimeout *prometheus.Desc - ResourceClass *prometheus.Desc - RestartAction *prometheus.Desc - RestartDelay *prometheus.Desc - RestartPeriod *prometheus.Desc - RestartThreshold *prometheus.Desc - RetryPeriodOnFailure *prometheus.Desc - State *prometheus.Desc - Subclass *prometheus.Desc -} - -func newMSCluster_ResourceCollector(logger log.Logger) (Collector, error) { - const subsystem = "mscluster_resource" - return &MSCluster_ResourceCollector{ - logger: log.With(logger, "collector", subsystem), - Characteristics: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "characteristics"), - "Provides the characteristics of the object.", - []string{"type", "owner_group", "name"}, - nil, - ), - DeadlockTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "deadlock_timeout"), - "Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource.", - []string{"type", "owner_group", "name"}, - nil, - ), - EmbeddedFailureAction: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "embedded_failure_action"), - "The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it.", - []string{"type", "owner_group", "name"}, - nil, - ), - Flags: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "flags"), - "Provides access to the flags set for the object.", - []string{"type", "owner_group", "name"}, - nil, - ), - IsAlivePollInterval: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "is_alive_poll_interval"), - "Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource.", - []string{"type", "owner_group", "name"}, - nil, - ), - LooksAlivePollInterval: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "looks_alive_poll_interval"), - "Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource.", - []string{"type", "owner_group", "name"}, - nil, - ), - MonitorProcessId: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "monitor_process_id"), - "Provides the process ID of the resource host service that is currently hosting the resource.", - []string{"type", "owner_group", "name"}, - nil, - ), - PendingTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pending_timeout"), - "Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated.", - []string{"type", "owner_group", "name"}, - nil, - ), - ResourceClass: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "resource_class"), - "Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown ", - []string{"type", "owner_group", "name"}, - nil, - ), - RestartAction: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "restart_action"), - "Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails.", - []string{"type", "owner_group", "name"}, - nil, - ), - RestartDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "restart_delay"), - "Indicates the time delay before a failed resource is restarted.", - []string{"type", "owner_group", "name"}, - nil, - ), - RestartPeriod: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "restart_period"), - "Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource.", - []string{"type", "owner_group", "name"}, - nil, - ), - RestartThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "restart_threshold"), - "Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property.", - []string{"type", "owner_group", "name"}, - nil, - ), - RetryPeriodOnFailure: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "retry_period_on_failure"), - "Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it.", - []string{"type", "owner_group", "name"}, - nil, - ), - State: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "state"), - "The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending ", - []string{"type", "owner_group", "name"}, - nil, - ), - Subclass: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "subclass"), - "Provides the list of references to nodes that can be the owner of this resource.", - []string{"type", "owner_group", "name"}, - nil, - ), - }, nil -} - -// MSCluster_Resource docs: -// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource -type MSCluster_Resource struct { - Name string - Type string - OwnerGroup string - - Characteristics uint - DeadlockTimeout uint - EmbeddedFailureAction uint - Flags uint - IsAlivePollInterval uint - LooksAlivePollInterval uint - MonitorProcessId uint - PendingTimeout uint - ResourceClass uint - RestartAction uint - RestartDelay uint - RestartPeriod uint - RestartThreshold uint - RetryPeriodOnFailure uint - State uint - Subclass uint -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *MSCluster_ResourceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - var dst []MSCluster_Resource - q := queryAll(&dst, c.logger) - if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { - return err - } - - for _, v := range dst { - - ch <- prometheus.MustNewConstMetric( - c.Characteristics, - prometheus.GaugeValue, - float64(v.Characteristics), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.DeadlockTimeout, - prometheus.GaugeValue, - float64(v.DeadlockTimeout), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.EmbeddedFailureAction, - prometheus.GaugeValue, - float64(v.EmbeddedFailureAction), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Flags, - prometheus.GaugeValue, - float64(v.Flags), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.IsAlivePollInterval, - prometheus.GaugeValue, - float64(v.IsAlivePollInterval), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.LooksAlivePollInterval, - prometheus.GaugeValue, - float64(v.LooksAlivePollInterval), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.MonitorProcessId, - prometheus.GaugeValue, - float64(v.MonitorProcessId), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.PendingTimeout, - prometheus.GaugeValue, - float64(v.PendingTimeout), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ResourceClass, - prometheus.GaugeValue, - float64(v.ResourceClass), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.RestartAction, - prometheus.GaugeValue, - float64(v.RestartAction), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.RestartDelay, - prometheus.GaugeValue, - float64(v.RestartDelay), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.RestartPeriod, - prometheus.GaugeValue, - float64(v.RestartPeriod), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.RestartThreshold, - prometheus.GaugeValue, - float64(v.RestartThreshold), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.RetryPeriodOnFailure, - prometheus.GaugeValue, - float64(v.RetryPeriodOnFailure), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.State, - prometheus.GaugeValue, - float64(v.State), - v.Type, v.OwnerGroup, v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Subclass, - prometheus.GaugeValue, - float64(v.Subclass), - v.Type, v.OwnerGroup, v.Name, - ) - } - - return nil -} diff --git a/collector/mscluster_resourcegroup.go b/collector/mscluster_resourcegroup.go deleted file mode 100644 index 6f6e05d01e..0000000000 --- a/collector/mscluster_resourcegroup.go +++ /dev/null @@ -1,240 +0,0 @@ -package collector - -import ( - "github.com/go-kit/log" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A MSCluster_ResourceGroupCollector is a Prometheus collector for WMI MSCluster_ResourceGroup metrics -type MSCluster_ResourceGroupCollector struct { - logger log.Logger - - AutoFailbackType *prometheus.Desc - Characteristics *prometheus.Desc - ColdStartSetting *prometheus.Desc - DefaultOwner *prometheus.Desc - FailbackWindowEnd *prometheus.Desc - FailbackWindowStart *prometheus.Desc - FailoverPeriod *prometheus.Desc - FailoverThreshold *prometheus.Desc - FaultDomain *prometheus.Desc - Flags *prometheus.Desc - GroupType *prometheus.Desc - PlacementOptions *prometheus.Desc - Priority *prometheus.Desc - ResiliencyPeriod *prometheus.Desc - State *prometheus.Desc -} - -func newMSCluster_ResourceGroupCollector(logger log.Logger) (Collector, error) { - const subsystem = "mscluster_resourcegroup" - return &MSCluster_ResourceGroupCollector{ - logger: log.With(logger, "collector", subsystem), - AutoFailbackType: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "auto_failback_type"), - "Provides access to the group's AutoFailbackType property.", - []string{"name"}, - nil, - ), - Characteristics: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "characteristics"), - "Provides the characteristics of the group.", - []string{"name"}, - nil, - ), - ColdStartSetting: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cold_start_setting"), - "Indicates whether a group can start after a cluster cold start.", - []string{"name"}, - nil, - ), - DefaultOwner: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "default_owner"), - "Number of the last node the resource group was activated on or explicitly moved to.", - []string{"name"}, - nil, - ), - FailbackWindowEnd: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failback_window_end"), - "The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node.", - []string{"name"}, - nil, - ), - FailbackWindowStart: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failback_window_start"), - "The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node.", - []string{"name"}, - nil, - ), - FailoverPeriod: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_period"), - "The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur.", - []string{"name"}, - nil, - ), - FailoverThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_threshold"), - "The FailoverThreshold property specifies the maximum number of failover attempts.", - []string{"name"}, - nil, - ), - Flags: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "flags"), - "Provides access to the flags set for the group. ", - []string{"name"}, - nil, - ), - GroupType: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "group_type"), - "The Type of the resource group.", - []string{"name"}, - nil, - ), - Priority: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "priority"), - "Priority value of the resource group", - []string{"name"}, - nil, - ), - ResiliencyPeriod: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "resiliency_period"), - "The resiliency period for this group, in seconds.", - []string{"name"}, - nil, - ), - State: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "state"), - "The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending", - []string{"name"}, - nil, - ), - }, nil -} - -// MSCluster_ResourceGroup docs: -// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup -type MSCluster_ResourceGroup struct { - Name string - - AutoFailbackType uint - Characteristics uint - ColdStartSetting uint - DefaultOwner uint - FailbackWindowEnd int - FailbackWindowStart int - FailoverPeriod uint - FailoverThreshold uint - Flags uint - GroupType uint - Priority uint - ResiliencyPeriod uint - State uint -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *MSCluster_ResourceGroupCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - var dst []MSCluster_ResourceGroup - q := queryAll(&dst, c.logger) - if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { - return err - } - - for _, v := range dst { - - ch <- prometheus.MustNewConstMetric( - c.AutoFailbackType, - prometheus.GaugeValue, - float64(v.AutoFailbackType), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Characteristics, - prometheus.GaugeValue, - float64(v.Characteristics), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ColdStartSetting, - prometheus.GaugeValue, - float64(v.ColdStartSetting), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.DefaultOwner, - prometheus.GaugeValue, - float64(v.DefaultOwner), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.FailbackWindowEnd, - prometheus.GaugeValue, - float64(v.FailbackWindowEnd), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.FailbackWindowStart, - prometheus.GaugeValue, - float64(v.FailbackWindowStart), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.FailoverPeriod, - prometheus.GaugeValue, - float64(v.FailoverPeriod), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.FailoverThreshold, - prometheus.GaugeValue, - float64(v.FailoverThreshold), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Flags, - prometheus.GaugeValue, - float64(v.Flags), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.GroupType, - prometheus.GaugeValue, - float64(v.GroupType), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Priority, - prometheus.GaugeValue, - float64(v.Priority), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ResiliencyPeriod, - prometheus.GaugeValue, - float64(v.ResiliencyPeriod), - v.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.State, - prometheus.GaugeValue, - float64(v.State), - v.Name, - ) - - } - - return nil -} diff --git a/collector/msmq.go b/collector/msmq.go deleted file mode 100644 index 038374464e..0000000000 --- a/collector/msmq.go +++ /dev/null @@ -1,137 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "strings" - - "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -const ( - FlagMsmqWhereClause = "collector.msmq.msmq-where" -) - -var ( - msmqWhereClause *string -) - -// A Win32_PerfRawData_MSMQ_MSMQQueueCollector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics -type Win32_PerfRawData_MSMQ_MSMQQueueCollector struct { - logger log.Logger - - BytesinJournalQueue *prometheus.Desc - BytesinQueue *prometheus.Desc - MessagesinJournalQueue *prometheus.Desc - MessagesinQueue *prometheus.Desc - - queryWhereClause string -} - -// newMSMQCollectorFlags .. -func newMSMQCollectorFlags(app *kingpin.Application) { - msmqWhereClause = app.Flag(FlagMsmqWhereClause, "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response.").String() -} - -// NewWin32_PerfRawData_MSMQ_MSMQQueueCollector ... -func newMSMQCollector(logger log.Logger) (Collector, error) { - const subsystem = "msmq" - logger = log.With(logger, "collector", subsystem) - - if *msmqWhereClause == "" { - _ = level.Warn(logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!") - } - - return &Win32_PerfRawData_MSMQ_MSMQQueueCollector{ - logger: logger, - - BytesinJournalQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_in_journal_queue"), - "Size of queue journal in bytes", - []string{"name"}, - nil, - ), - BytesinQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_in_queue"), - "Size of queue in bytes", - []string{"name"}, - nil, - ), - MessagesinJournalQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_in_journal_queue"), - "Count messages in queue journal", - []string{"name"}, - nil, - ), - MessagesinQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_in_queue"), - "Count messages in queue", - []string{"name"}, - nil, - ), - queryWhereClause: *msmqWhereClause, - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting msmq metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_MSMQ_MSMQQueue struct { - Name string - - BytesinJournalQueue uint64 - BytesinQueue uint64 - MessagesinJournalQueue uint64 - MessagesinQueue uint64 -} - -func (c *Win32_PerfRawData_MSMQ_MSMQQueueCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_MSMQ_MSMQQueue - q := queryAllWhere(&dst, c.queryWhereClause, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, msmq := range dst { - ch <- prometheus.MustNewConstMetric( - c.BytesinJournalQueue, - prometheus.GaugeValue, - float64(msmq.BytesinJournalQueue), - strings.ToLower(msmq.Name), - ) - - ch <- prometheus.MustNewConstMetric( - c.BytesinQueue, - prometheus.GaugeValue, - float64(msmq.BytesinQueue), - strings.ToLower(msmq.Name), - ) - - ch <- prometheus.MustNewConstMetric( - c.MessagesinJournalQueue, - prometheus.GaugeValue, - float64(msmq.MessagesinJournalQueue), - strings.ToLower(msmq.Name), - ) - - ch <- prometheus.MustNewConstMetric( - c.MessagesinQueue, - prometheus.GaugeValue, - float64(msmq.MessagesinQueue), - strings.ToLower(msmq.Name), - ) - } - return nil, nil -} diff --git a/collector/msmq_test.go b/collector/msmq_test.go deleted file mode 100644 index 86512bf8ff..0000000000 --- a/collector/msmq_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkMsmqCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newMSMQCollector) -} diff --git a/collector/mssql_test.go b/collector/mssql_test.go deleted file mode 100644 index 5230a72bb5..0000000000 --- a/collector/mssql_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkMSSQLCollector(b *testing.B) { - benchmarkCollector(b, "mssql", newMSSQLCollector) -} diff --git a/collector/netframework_clrexceptions.go b/collector/netframework_clrexceptions.go deleted file mode 100644 index d12bcc4e70..0000000000 --- a/collector/netframework_clrexceptions.go +++ /dev/null @@ -1,119 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRExceptionsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics -type NETFramework_NETCLRExceptionsCollector struct { - logger log.Logger - - NumberofExcepsThrown *prometheus.Desc - NumberofFilters *prometheus.Desc - NumberofFinallys *prometheus.Desc - ThrowToCatchDepth *prometheus.Desc -} - -// newNETFramework_NETCLRExceptionsCollector ... -func newNETFramework_NETCLRExceptionsCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrexceptions" - return &NETFramework_NETCLRExceptionsCollector{ - logger: log.With(logger, "collector", subsystem), - - NumberofExcepsThrown: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "exceptions_thrown_total"), - "Displays the total number of exceptions thrown since the application started. This includes both .NET exceptions and unmanaged exceptions that are converted into .NET exceptions.", - []string{"process"}, - nil, - ), - NumberofFilters: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "exceptions_filters_total"), - "Displays the total number of .NET exception filters executed. An exception filter evaluates regardless of whether an exception is handled.", - []string{"process"}, - nil, - ), - NumberofFinallys: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "exceptions_finallys_total"), - "Displays the total number of finally blocks executed. Only the finally blocks executed for an exception are counted; finally blocks on normal code paths are not counted by this counter.", - []string{"process"}, - nil, - ), - ThrowToCatchDepth: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "throw_to_catch_depth_total"), - "Displays the total number of stack frames traversed, from the frame that threw the exception to the frame that handled the exception.", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRExceptionsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRExceptions struct { - Name string - - NumberofExcepsThrown uint32 - NumberofExcepsThrownPersec uint32 - NumberofFiltersPersec uint32 - NumberofFinallysPersec uint32 - ThrowToCatchDepthPersec uint32 -} - -func (c *NETFramework_NETCLRExceptionsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.NumberofExcepsThrown, - prometheus.CounterValue, - float64(process.NumberofExcepsThrown), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NumberofFilters, - prometheus.CounterValue, - float64(process.NumberofFiltersPersec), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NumberofFinallys, - prometheus.CounterValue, - float64(process.NumberofFinallysPersec), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ThrowToCatchDepth, - prometheus.CounterValue, - float64(process.ThrowToCatchDepthPersec), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrexceptions_test.go b/collector/netframework_clrexceptions_test.go deleted file mode 100644 index a9f3512bf2..0000000000 --- a/collector/netframework_clrexceptions_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNetFrameworkNETCLRExceptionsCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRExceptionsCollector) -} diff --git a/collector/netframework_clrinterop.go b/collector/netframework_clrinterop.go deleted file mode 100644 index 4254163855..0000000000 --- a/collector/netframework_clrinterop.go +++ /dev/null @@ -1,104 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRInteropCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics -type NETFramework_NETCLRInteropCollector struct { - logger log.Logger - - NumberofCCWs *prometheus.Desc - Numberofmarshalling *prometheus.Desc - NumberofStubs *prometheus.Desc -} - -// newNETFramework_NETCLRInteropCollector ... -func newNETFramework_NETCLRInteropCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrinterop" - return &NETFramework_NETCLRInteropCollector{ - logger: log.With(logger, "collector", subsystem), - NumberofCCWs: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "com_callable_wrappers_total"), - "Displays the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client.", - []string{"process"}, - nil, - ), - Numberofmarshalling: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "interop_marshalling_total"), - "Displays the total number of times arguments and return values have been marshaled from managed to unmanaged code, and vice versa, since the application started.", - []string{"process"}, - nil, - ), - NumberofStubs: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "interop_stubs_created_total"), - "Displays the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call.", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRInteropCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrinterop metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRInterop struct { - Name string - - NumberofCCWs uint32 - Numberofmarshalling uint32 - NumberofStubs uint32 - NumberofTLBexportsPersec uint32 - NumberofTLBimportsPersec uint32 -} - -func (c *NETFramework_NETCLRInteropCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRInterop - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.NumberofCCWs, - prometheus.CounterValue, - float64(process.NumberofCCWs), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Numberofmarshalling, - prometheus.CounterValue, - float64(process.Numberofmarshalling), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NumberofStubs, - prometheus.CounterValue, - float64(process.NumberofStubs), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrinterop_test.go b/collector/netframework_clrinterop_test.go deleted file mode 100644 index ff94d91c37..0000000000 --- a/collector/netframework_clrinterop_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRInteropCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRInteropCollector) -} diff --git a/collector/netframework_clrjit.go b/collector/netframework_clrjit.go deleted file mode 100644 index efd97317de..0000000000 --- a/collector/netframework_clrjit.go +++ /dev/null @@ -1,120 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRJitCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics -type NETFramework_NETCLRJitCollector struct { - logger log.Logger - - NumberofMethodsJitted *prometheus.Desc - TimeinJit *prometheus.Desc - StandardJitFailures *prometheus.Desc - TotalNumberofILBytesJitted *prometheus.Desc -} - -// newNETFramework_NETCLRJitCollector ... -func newNETFramework_NETCLRJitCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrjit" - return &NETFramework_NETCLRJitCollector{ - logger: log.With(logger, "collector", subsystem), - NumberofMethodsJitted: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "jit_methods_total"), - "Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.", - []string{"process"}, - nil, - ), - TimeinJit: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "jit_time_percent"), - "Displays the percentage of time spent in JIT compilation. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled.", - []string{"process"}, - nil, - ), - StandardJitFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "jit_standard_failures_total"), - "Displays the peak number of methods the JIT compiler has failed to compile since the application started. This failure can occur if the MSIL cannot be verified or if there is an internal error in the JIT compiler.", - []string{"process"}, - nil, - ), - TotalNumberofILBytesJitted: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "jit_il_bytes_total"), - "Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by the just-in-time (JIT) compiler since the application started", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRJitCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrjit metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRJit struct { - Name string - - Frequency_PerfTime uint32 - ILBytesJittedPersec uint32 - NumberofILBytesJitted uint32 - NumberofMethodsJitted uint32 - PercentTimeinJit uint32 - StandardJitFailures uint32 - TotalNumberofILBytesJitted uint32 -} - -func (c *NETFramework_NETCLRJitCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRJit - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.NumberofMethodsJitted, - prometheus.CounterValue, - float64(process.NumberofMethodsJitted), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TimeinJit, - prometheus.GaugeValue, - float64(process.PercentTimeinJit)/float64(process.Frequency_PerfTime), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.StandardJitFailures, - prometheus.GaugeValue, - float64(process.StandardJitFailures), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalNumberofILBytesJitted, - prometheus.CounterValue, - float64(process.TotalNumberofILBytesJitted), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrjit_test.go b/collector/netframework_clrjit_test.go deleted file mode 100644 index 05a3296d0c..0000000000 --- a/collector/netframework_clrjit_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRJitCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRJitCollector) -} diff --git a/collector/netframework_clrloading.go b/collector/netframework_clrloading.go deleted file mode 100644 index afd69aebfd..0000000000 --- a/collector/netframework_clrloading.go +++ /dev/null @@ -1,199 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRLoadingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics -type NETFramework_NETCLRLoadingCollector struct { - logger log.Logger - - BytesinLoaderHeap *prometheus.Desc - Currentappdomains *prometheus.Desc - CurrentAssemblies *prometheus.Desc - CurrentClassesLoaded *prometheus.Desc - TotalAppdomains *prometheus.Desc - Totalappdomainsunloaded *prometheus.Desc - TotalAssemblies *prometheus.Desc - TotalClassesLoaded *prometheus.Desc - TotalNumberofLoadFailures *prometheus.Desc -} - -// newNETFramework_NETCLRLoadingCollector ... -func newNETFramework_NETCLRLoadingCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrloading" - return &NETFramework_NETCLRLoadingCollector{ - logger: log.With(logger, "collector", subsystem), - BytesinLoaderHeap: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "loader_heap_size_bytes"), - "Displays the current size, in bytes, of the memory committed by the class loader across all application domains. Committed memory is the physical space reserved in the disk paging file.", - []string{"process"}, - nil, - ), - Currentappdomains: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "appdomains_loaded_current"), - "Displays the current number of application domains loaded in this application.", - []string{"process"}, - nil, - ), - CurrentAssemblies: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "assemblies_loaded_current"), - "Displays the current number of assemblies loaded across all application domains in the currently running application. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", - []string{"process"}, - nil, - ), - CurrentClassesLoaded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "classes_loaded_current"), - "Displays the current number of classes loaded in all assemblies.", - []string{"process"}, - nil, - ), - TotalAppdomains: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "appdomains_loaded_total"), - "Displays the peak number of application domains loaded since the application started.", - []string{"process"}, - nil, - ), - Totalappdomainsunloaded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "appdomains_unloaded_total"), - "Displays the total number of application domains unloaded since the application started. If an application domain is loaded and unloaded multiple times, this counter increments each time the application domain is unloaded.", - []string{"process"}, - nil, - ), - TotalAssemblies: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "assemblies_loaded_total"), - "Displays the total number of assemblies loaded since the application started. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", - []string{"process"}, - nil, - ), - TotalClassesLoaded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "classes_loaded_total"), - "Displays the cumulative number of classes loaded in all assemblies since the application started.", - []string{"process"}, - nil, - ), - TotalNumberofLoadFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "class_load_failures_total"), - "Displays the peak number of classes that have failed to load since the application started.", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRLoadingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrloading metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRLoading struct { - Name string - - AssemblySearchLength uint32 - BytesinLoaderHeap uint64 - Currentappdomains uint32 - CurrentAssemblies uint32 - CurrentClassesLoaded uint32 - PercentTimeLoading uint64 - Rateofappdomains uint32 - Rateofappdomainsunloaded uint32 - RateofAssemblies uint32 - RateofClassesLoaded uint32 - RateofLoadFailures uint32 - TotalAppdomains uint32 - Totalappdomainsunloaded uint32 - TotalAssemblies uint32 - TotalClassesLoaded uint32 - TotalNumberofLoadFailures uint32 -} - -func (c *NETFramework_NETCLRLoadingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRLoading - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.BytesinLoaderHeap, - prometheus.GaugeValue, - float64(process.BytesinLoaderHeap), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Currentappdomains, - prometheus.GaugeValue, - float64(process.Currentappdomains), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.CurrentAssemblies, - prometheus.GaugeValue, - float64(process.CurrentAssemblies), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.CurrentClassesLoaded, - prometheus.GaugeValue, - float64(process.CurrentClassesLoaded), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalAppdomains, - prometheus.CounterValue, - float64(process.TotalAppdomains), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Totalappdomainsunloaded, - prometheus.CounterValue, - float64(process.Totalappdomainsunloaded), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalAssemblies, - prometheus.CounterValue, - float64(process.TotalAssemblies), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalClassesLoaded, - prometheus.CounterValue, - float64(process.TotalClassesLoaded), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalNumberofLoadFailures, - prometheus.CounterValue, - float64(process.TotalNumberofLoadFailures), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrloading_test.go b/collector/netframework_clrloading_test.go deleted file mode 100644 index 8ea1974a36..0000000000 --- a/collector/netframework_clrloading_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRLoadingCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRLoadingCollector) -} diff --git a/collector/netframework_clrlocksandthreads.go b/collector/netframework_clrlocksandthreads.go deleted file mode 100644 index 82827d0ce2..0000000000 --- a/collector/netframework_clrlocksandthreads.go +++ /dev/null @@ -1,165 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRLocksAndThreadsCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics -type NETFramework_NETCLRLocksAndThreadsCollector struct { - logger log.Logger - - CurrentQueueLength *prometheus.Desc - NumberofcurrentlogicalThreads *prometheus.Desc - NumberofcurrentphysicalThreads *prometheus.Desc - Numberofcurrentrecognizedthreads *prometheus.Desc - Numberoftotalrecognizedthreads *prometheus.Desc - QueueLengthPeak *prometheus.Desc - TotalNumberofContentions *prometheus.Desc -} - -// newNETFramework_NETCLRLocksAndThreadsCollector ... -func newNETFramework_NETCLRLocksAndThreadsCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrlocksandthreads" - return &NETFramework_NETCLRLocksAndThreadsCollector{ - logger: log.With(logger, "collector", subsystem), - CurrentQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_queue_length"), - "Displays the total number of threads that are currently waiting to acquire a managed lock in the application.", - []string{"process"}, - nil, - ), - NumberofcurrentlogicalThreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_logical_threads"), - "Displays the number of current managed thread objects in the application. This counter maintains the count of both running and stopped threads. ", - []string{"process"}, - nil, - ), - NumberofcurrentphysicalThreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "physical_threads_current"), - "Displays the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process.", - []string{"process"}, - nil, - ), - Numberofcurrentrecognizedthreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "recognized_threads_current"), - "Displays the number of threads that are currently recognized by the runtime. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", - []string{"process"}, - nil, - ), - Numberoftotalrecognizedthreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "recognized_threads_total"), - "Displays the total number of threads that have been recognized by the runtime since the application started. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", - []string{"process"}, - nil, - ), - QueueLengthPeak: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "queue_length_total"), - "Displays the total number of threads that waited to acquire a managed lock since the application started.", - []string{"process"}, - nil, - ), - TotalNumberofContentions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "contentions_total"), - "Displays the total number of times that threads in the runtime have attempted to acquire a managed lock unsuccessfully.", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRLocksAndThreadsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct { - Name string - - ContentionRatePersec uint32 - CurrentQueueLength uint32 - NumberofcurrentlogicalThreads uint32 - NumberofcurrentphysicalThreads uint32 - Numberofcurrentrecognizedthreads uint32 - Numberoftotalrecognizedthreads uint32 - QueueLengthPeak uint32 - QueueLengthPersec uint32 - RateOfRecognizedThreadsPersec uint32 - TotalNumberofContentions uint32 -} - -func (c *NETFramework_NETCLRLocksAndThreadsCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.CurrentQueueLength, - prometheus.GaugeValue, - float64(process.CurrentQueueLength), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NumberofcurrentlogicalThreads, - prometheus.GaugeValue, - float64(process.NumberofcurrentlogicalThreads), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.NumberofcurrentphysicalThreads, - prometheus.GaugeValue, - float64(process.NumberofcurrentphysicalThreads), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Numberofcurrentrecognizedthreads, - prometheus.GaugeValue, - float64(process.Numberofcurrentrecognizedthreads), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Numberoftotalrecognizedthreads, - prometheus.CounterValue, - float64(process.Numberoftotalrecognizedthreads), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.QueueLengthPeak, - prometheus.CounterValue, - float64(process.QueueLengthPeak), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalNumberofContentions, - prometheus.CounterValue, - float64(process.TotalNumberofContentions), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrlocksandthreads_test.go b/collector/netframework_clrlocksandthreads_test.go deleted file mode 100644 index 4e169d668d..0000000000 --- a/collector/netframework_clrlocksandthreads_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRLocksAndThreadsCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRLocksAndThreadsCollector) -} diff --git a/collector/netframework_clrmemory_test.go b/collector/netframework_clrmemory_test.go deleted file mode 100644 index 82f64ae3e3..0000000000 --- a/collector/netframework_clrmemory_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRMemoryCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRMemoryCollector) -} diff --git a/collector/netframework_clrremoting.go b/collector/netframework_clrremoting.go deleted file mode 100644 index f3437bd55a..0000000000 --- a/collector/netframework_clrremoting.go +++ /dev/null @@ -1,148 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRRemotingCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics -type NETFramework_NETCLRRemotingCollector struct { - logger log.Logger - - Channels *prometheus.Desc - ContextBoundClassesLoaded *prometheus.Desc - ContextBoundObjects *prometheus.Desc - ContextProxies *prometheus.Desc - Contexts *prometheus.Desc - TotalRemoteCalls *prometheus.Desc -} - -// newNETFramework_NETCLRRemotingCollector ... -func newNETFramework_NETCLRRemotingCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrremoting" - return &NETFramework_NETCLRRemotingCollector{ - logger: log.With(logger, "collector", subsystem), - Channels: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "channels_total"), - "Displays the total number of remoting channels registered across all application domains since application started.", - []string{"process"}, - nil, - ), - ContextBoundClassesLoaded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "context_bound_classes_loaded"), - "Displays the current number of context-bound classes that are loaded.", - []string{"process"}, - nil, - ), - ContextBoundObjects: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "context_bound_objects_total"), - "Displays the total number of context-bound objects allocated.", - []string{"process"}, - nil, - ), - ContextProxies: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "context_proxies_total"), - "Displays the total number of remoting proxy objects in this process since it started.", - []string{"process"}, - nil, - ), - Contexts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "contexts"), - "Displays the current number of remoting contexts in the application.", - []string{"process"}, - nil, - ), - TotalRemoteCalls: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "remote_calls_total"), - "Displays the total number of remote procedure calls invoked since the application started.", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRRemotingCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrremoting metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRRemoting struct { - Name string - - Channels uint32 - ContextBoundClassesLoaded uint32 - ContextBoundObjectsAllocPersec uint32 - ContextProxies uint32 - Contexts uint32 - RemoteCallsPersec uint32 - TotalRemoteCalls uint32 -} - -func (c *NETFramework_NETCLRRemotingCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.Channels, - prometheus.CounterValue, - float64(process.Channels), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ContextBoundClassesLoaded, - prometheus.GaugeValue, - float64(process.ContextBoundClassesLoaded), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ContextBoundObjects, - prometheus.CounterValue, - float64(process.ContextBoundObjectsAllocPersec), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.ContextProxies, - prometheus.CounterValue, - float64(process.ContextProxies), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.Contexts, - prometheus.GaugeValue, - float64(process.Contexts), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalRemoteCalls, - prometheus.CounterValue, - float64(process.TotalRemoteCalls), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrremoting_test.go b/collector/netframework_clrremoting_test.go deleted file mode 100644 index b07d2c8269..0000000000 --- a/collector/netframework_clrremoting_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRRemotingCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRRemotingCollector) -} diff --git a/collector/netframework_clrsecurity.go b/collector/netframework_clrsecurity.go deleted file mode 100644 index eebf32738f..0000000000 --- a/collector/netframework_clrsecurity.go +++ /dev/null @@ -1,119 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -// A NETFramework_NETCLRSecurityCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics -type NETFramework_NETCLRSecurityCollector struct { - logger log.Logger - - NumberLinkTimeChecks *prometheus.Desc - TimeinRTchecks *prometheus.Desc - StackWalkDepth *prometheus.Desc - TotalRuntimeChecks *prometheus.Desc -} - -// newNETFramework_NETCLRSecurityCollector ... -func newNETFramework_NETCLRSecurityCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrsecurity" - return &NETFramework_NETCLRSecurityCollector{ - logger: log.With(logger, "collector", subsystem), - NumberLinkTimeChecks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "link_time_checks_total"), - "Displays the total number of link-time code access security checks since the application started.", - []string{"process"}, - nil, - ), - TimeinRTchecks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rt_checks_time_percent"), - "Displays the percentage of time spent performing runtime code access security checks in the last sample.", - []string{"process"}, - nil, - ), - StackWalkDepth: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "stack_walk_depth"), - "Displays the depth of the stack during that last runtime code access security check.", - []string{"process"}, - nil, - ), - TotalRuntimeChecks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "runtime_checks_total"), - "Displays the total number of runtime code access security checks performed since the application started.", - []string{"process"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRSecurityCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics", "desc", desc, "err", err) - return err - } - return nil -} - -type Win32_PerfRawData_NETFramework_NETCLRSecurity struct { - Name string - - Frequency_PerfTime uint32 - NumberLinkTimeChecks uint32 - PercentTimeinRTchecks uint32 - PercentTimeSigAuthenticating uint64 - StackWalkDepth uint32 - TotalRuntimeChecks uint32 -} - -func (c *NETFramework_NETCLRSecurityCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity - q := queryAll(&dst, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return nil, err - } - - for _, process := range dst { - - if process.Name == "_Global_" { - continue - } - - ch <- prometheus.MustNewConstMetric( - c.NumberLinkTimeChecks, - prometheus.CounterValue, - float64(process.NumberLinkTimeChecks), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TimeinRTchecks, - prometheus.GaugeValue, - float64(process.PercentTimeinRTchecks)/float64(process.Frequency_PerfTime), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.StackWalkDepth, - prometheus.GaugeValue, - float64(process.StackWalkDepth), - process.Name, - ) - - ch <- prometheus.MustNewConstMetric( - c.TotalRuntimeChecks, - prometheus.CounterValue, - float64(process.TotalRuntimeChecks), - process.Name, - ) - } - - return nil, nil -} diff --git a/collector/netframework_clrsecurity_test.go b/collector/netframework_clrsecurity_test.go deleted file mode 100644 index b628686373..0000000000 --- a/collector/netframework_clrsecurity_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNETFrameworkNETCLRSecurityCollector(b *testing.B) { - // No context name required as collector source is WMI - benchmarkCollector(b, "", newNETFramework_NETCLRSecurityCollector) -} diff --git a/collector/nps_test.go b/collector/nps_test.go deleted file mode 100644 index 6514a73ea1..0000000000 --- a/collector/nps_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkNPSCollector(b *testing.B) { - benchmarkCollector(b, "nps", newNPSCollector) -} diff --git a/collector/os_test.go b/collector/os_test.go deleted file mode 100644 index 874fba2ae8..0000000000 --- a/collector/os_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkOSCollector(b *testing.B) { - benchmarkCollector(b, "os", newOSCollector) -} diff --git a/collector/physical_disk.go b/collector/physical_disk.go deleted file mode 100644 index 1f64a44d7b..0000000000 --- a/collector/physical_disk.go +++ /dev/null @@ -1,298 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "fmt" - "regexp" - "strings" - - "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -const ( - FlagPhysicalDiskExclude = "collector.physical_disk.disk-exclude" - FlagPhysicalDiskInclude = "collector.physical_disk.disk-include" -) - -var ( - diskInclude *string - diskExclude *string - - diskIncludeSet bool - diskExcludeSet bool -) - -// A PhysicalDiskCollector is a Prometheus collector for perflib PhysicalDisk metrics -type PhysicalDiskCollector struct { - logger log.Logger - - RequestsQueued *prometheus.Desc - ReadBytesTotal *prometheus.Desc - ReadsTotal *prometheus.Desc - WriteBytesTotal *prometheus.Desc - WritesTotal *prometheus.Desc - ReadTime *prometheus.Desc - WriteTime *prometheus.Desc - IdleTime *prometheus.Desc - SplitIOs *prometheus.Desc - ReadLatency *prometheus.Desc - WriteLatency *prometheus.Desc - ReadWriteLatency *prometheus.Desc - - diskIncludePattern *regexp.Regexp - diskExcludePattern *regexp.Regexp -} - -// newPhysicalDiskCollectorFlags ... -func newPhysicalDiskCollectorFlags(app *kingpin.Application) { - diskInclude = app.Flag( - FlagPhysicalDiskInclude, - "Regexp of disks to include. Disk number must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - diskIncludeSet = true - return nil - }).String() - - diskExclude = app.Flag( - FlagPhysicalDiskExclude, - "Regexp of disks to exclude. Disk number must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - diskExcludeSet = true - return nil - }).String() -} - -// NewPhysicalDiskCollector ... -func NewPhysicalDiskCollector(logger log.Logger) (Collector, error) { - const subsystem = "physical_disk" - logger = log.With(logger, "collector", subsystem) - - return &PhysicalDiskCollector{ - logger: logger, - - RequestsQueued: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "requests_queued"), - "The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)", - []string{"disk"}, - nil, - ), - - ReadBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_bytes_total"), - "The number of bytes transferred from the disk during read operations (PhysicalDisk.DiskReadBytesPerSec)", - []string{"disk"}, - nil, - ), - - ReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "reads_total"), - "The number of read operations on the disk (PhysicalDisk.DiskReadsPerSec)", - []string{"disk"}, - nil, - ), - - WriteBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_bytes_total"), - "The number of bytes transferred to the disk during write operations (PhysicalDisk.DiskWriteBytesPerSec)", - []string{"disk"}, - nil, - ), - - WritesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "writes_total"), - "The number of write operations on the disk (PhysicalDisk.DiskWritesPerSec)", - []string{"disk"}, - nil, - ), - - ReadTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_seconds_total"), - "Seconds that the disk was busy servicing read requests (PhysicalDisk.PercentDiskReadTime)", - []string{"disk"}, - nil, - ), - - WriteTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_seconds_total"), - "Seconds that the disk was busy servicing write requests (PhysicalDisk.PercentDiskWriteTime)", - []string{"disk"}, - nil, - ), - - IdleTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "idle_seconds_total"), - "Seconds that the disk was idle (PhysicalDisk.PercentIdleTime)", - []string{"disk"}, - nil, - ), - - SplitIOs: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "split_ios_total"), - "The number of I/Os to the disk were split into multiple I/Os (PhysicalDisk.SplitIOPerSec)", - []string{"disk"}, - nil, - ), - - ReadLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_latency_seconds_total"), - "Shows the average time, in seconds, of a read operation from the disk (PhysicalDisk.AvgDiskSecPerRead)", - []string{"disk"}, - nil, - ), - - WriteLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "write_latency_seconds_total"), - "Shows the average time, in seconds, of a write operation to the disk (PhysicalDisk.AvgDiskSecPerWrite)", - []string{"disk"}, - nil, - ), - - ReadWriteLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_write_latency_seconds_total"), - "Shows the time, in seconds, of the average disk transfer (PhysicalDisk.AvgDiskSecPerTransfer)", - []string{"disk"}, - nil, - ), - - diskIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *diskInclude)), - diskExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *diskExclude)), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *PhysicalDiskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting physical_disk metrics", "desc", desc, "err", err) - return err - } - return nil -} - -// Win32_PerfRawData_PerfDisk_PhysicalDisk docs: -// - https://docs.microsoft.com/en-us/previous-versions/aa394308(v=vs.85) - Win32_PerfRawData_PerfDisk_PhysicalDisk class -type PhysicalDisk struct { - Name string - CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` - DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"` - DiskReadsPerSec float64 `perflib:"Disk Reads/sec"` - DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"` - DiskWritesPerSec float64 `perflib:"Disk Writes/sec"` - PercentDiskReadTime float64 `perflib:"% Disk Read Time"` - PercentDiskWriteTime float64 `perflib:"% Disk Write Time"` - PercentIdleTime float64 `perflib:"% Idle Time"` - SplitIOPerSec float64 `perflib:"Split IO/Sec"` - AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"` - AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"` - AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"` -} - -func (c *PhysicalDiskCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []PhysicalDisk - if err := unmarshalObject(ctx.perfObjects["PhysicalDisk"], &dst, c.logger); err != nil { - return nil, err - } - - for _, disk := range dst { - if disk.Name == "_Total" || - c.diskExcludePattern.MatchString(disk.Name) || - !c.diskIncludePattern.MatchString(disk.Name) { - continue - } - - // Parse physical disk number from disk.Name. Mountpoint information is - // sometimes included, e.g. "1 C:". - disk_number, _, _ := strings.Cut(disk.Name, " ") - - ch <- prometheus.MustNewConstMetric( - c.RequestsQueued, - prometheus.GaugeValue, - disk.CurrentDiskQueueLength, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadBytesTotal, - prometheus.CounterValue, - disk.DiskReadBytesPerSec, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadsTotal, - prometheus.CounterValue, - disk.DiskReadsPerSec, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteBytesTotal, - prometheus.CounterValue, - disk.DiskWriteBytesPerSec, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.WritesTotal, - prometheus.CounterValue, - disk.DiskWritesPerSec, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadTime, - prometheus.CounterValue, - disk.PercentDiskReadTime, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteTime, - prometheus.CounterValue, - disk.PercentDiskWriteTime, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.IdleTime, - prometheus.CounterValue, - disk.PercentIdleTime, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.SplitIOs, - prometheus.CounterValue, - disk.SplitIOPerSec, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadLatency, - prometheus.CounterValue, - disk.AvgDiskSecPerRead*ticksToSecondsScaleFactor, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.WriteLatency, - prometheus.CounterValue, - disk.AvgDiskSecPerWrite*ticksToSecondsScaleFactor, - disk_number, - ) - - ch <- prometheus.MustNewConstMetric( - c.ReadWriteLatency, - prometheus.CounterValue, - disk.AvgDiskSecPerTransfer*ticksToSecondsScaleFactor, - disk_number, - ) - } - - return nil, nil -} diff --git a/collector/process_test.go b/collector/process_test.go deleted file mode 100644 index 9efa51be7a..0000000000 --- a/collector/process_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkProcessCollector(b *testing.B) { - // Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all processes. - localProcessInclude := ".+" - processInclude = &localProcessInclude - - // No context name required as collector source is WMI - benchmarkCollector(b, "", newProcessCollector) -} diff --git a/collector/remote_fx_test.go b/collector/remote_fx_test.go deleted file mode 100644 index 6e921f06d9..0000000000 --- a/collector/remote_fx_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkRemoteFXCollector(b *testing.B) { - benchmarkCollector(b, "remote_fx", newRemoteFx) -} diff --git a/collector/scheduled_task_test.go b/collector/scheduled_task_test.go deleted file mode 100644 index 5bf5bf8d36..0000000000 --- a/collector/scheduled_task_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkScheduledTaskCollector(b *testing.B) { - benchmarkCollector(b, "scheduled_task", newScheduledTask) -} diff --git a/collector/service.go b/collector/service.go deleted file mode 100644 index ee3275c709..0000000000 --- a/collector/service.go +++ /dev/null @@ -1,332 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "fmt" - "strings" - "syscall" - - "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" - "golang.org/x/sys/windows" - "golang.org/x/sys/windows/svc/mgr" -) - -const ( - FlagServiceWhereClause = "collector.service.services-where" - FlagServiceUseAPI = "collector.service.use-api" -) - -var ( - serviceWhereClause *string - useAPI *bool -) - -// A serviceCollector is a Prometheus collector for WMI Win32_Service metrics -type serviceCollector struct { - logger log.Logger - - Information *prometheus.Desc - State *prometheus.Desc - StartMode *prometheus.Desc - Status *prometheus.Desc - - queryWhereClause string -} - -// newServiceCollectorFlags ... -func newServiceCollectorFlags(app *kingpin.Application) { - serviceWhereClause = app.Flag( - FlagServiceWhereClause, - "WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.", - ).Default("").String() - useAPI = app.Flag( - FlagServiceUseAPI, - "Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.", - ).Default("false").Bool() -} - -// newserviceCollector ... -func newserviceCollector(logger log.Logger) (Collector, error) { - const subsystem = "service" - logger = log.With(logger, "collector", subsystem) - - if *serviceWhereClause == "" { - _ = level.Warn(logger).Log("msg", "No where-clause specified for service collector. This will generate a very large number of metrics!") - } - if *useAPI { - _ = level.Warn(logger).Log("msg", "API collection is enabled.") - } - - return &serviceCollector{ - logger: logger, - - Information: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "info"), - "A metric with a constant '1' value labeled with service information", - []string{"name", "display_name", "process_id", "run_as"}, - nil, - ), - State: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "state"), - "The state of the service (State)", - []string{"name", "state"}, - nil, - ), - StartMode: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "start_mode"), - "The start mode of the service (StartMode)", - []string{"name", "start_mode"}, - nil, - ), - Status: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "status"), - "The status of the service (Status)", - []string{"name", "status"}, - nil, - ), - queryWhereClause: *serviceWhereClause, - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *serviceCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if *useAPI { - if err := c.collectAPI(ch); err != nil { - _ = level.Error(c.logger).Log("msg", "failed collecting API service metrics:", "err", err) - return err - } - } else { - if err := c.collectWMI(ch); err != nil { - _ = level.Error(c.logger).Log("msg", "failed collecting WMI service metrics:", "err", err) - return err - } - } - return nil -} - -// Win32_Service docs: -// - https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx -type Win32_Service struct { - DisplayName string - Name string - ProcessId uint32 - State string - Status string - StartMode string - StartName *string -} - -var ( - allStates = []string{ - "stopped", - "start pending", - "stop pending", - "running", - "continue pending", - "pause pending", - "paused", - "unknown", - } - apiStateValues = map[uint]string{ - windows.SERVICE_CONTINUE_PENDING: "continue pending", - windows.SERVICE_PAUSE_PENDING: "pause pending", - windows.SERVICE_PAUSED: "paused", - windows.SERVICE_RUNNING: "running", - windows.SERVICE_START_PENDING: "start pending", - windows.SERVICE_STOP_PENDING: "stop pending", - windows.SERVICE_STOPPED: "stopped", - } - allStartModes = []string{ - "boot", - "system", - "auto", - "manual", - "disabled", - } - apiStartModeValues = map[uint32]string{ - windows.SERVICE_AUTO_START: "auto", - windows.SERVICE_BOOT_START: "boot", - windows.SERVICE_DEMAND_START: "manual", - windows.SERVICE_DISABLED: "disabled", - windows.SERVICE_SYSTEM_START: "system", - } - allStatuses = []string{ - "ok", - "error", - "degraded", - "unknown", - "pred fail", - "starting", - "stopping", - "service", - "stressed", - "nonrecover", - "no contact", - "lost comm", - } -) - -func (c *serviceCollector) collectWMI(ch chan<- prometheus.Metric) error { - var dst []Win32_Service - q := queryAllWhere(&dst, c.queryWhereClause, c.logger) - if err := wmi.Query(q, &dst); err != nil { - return err - } - for _, service := range dst { - pid := fmt.Sprintf("%d", uint64(service.ProcessId)) - - runAs := "" - if service.StartName != nil { - runAs = *service.StartName - } - ch <- prometheus.MustNewConstMetric( - c.Information, - prometheus.GaugeValue, - 1.0, - strings.ToLower(service.Name), - service.DisplayName, - pid, - runAs, - ) - - for _, state := range allStates { - isCurrentState := 0.0 - if state == strings.ToLower(service.State) { - isCurrentState = 1.0 - } - ch <- prometheus.MustNewConstMetric( - c.State, - prometheus.GaugeValue, - isCurrentState, - strings.ToLower(service.Name), - state, - ) - } - - for _, startMode := range allStartModes { - isCurrentStartMode := 0.0 - if startMode == strings.ToLower(service.StartMode) { - isCurrentStartMode = 1.0 - } - ch <- prometheus.MustNewConstMetric( - c.StartMode, - prometheus.GaugeValue, - isCurrentStartMode, - strings.ToLower(service.Name), - startMode, - ) - } - - for _, status := range allStatuses { - isCurrentStatus := 0.0 - if status == strings.ToLower(service.Status) { - isCurrentStatus = 1.0 - } - ch <- prometheus.MustNewConstMetric( - c.Status, - prometheus.GaugeValue, - isCurrentStatus, - strings.ToLower(service.Name), - status, - ) - } - } - return nil -} - -func (c *serviceCollector) collectAPI(ch chan<- prometheus.Metric) error { - svcmgrConnection, err := mgr.Connect() - if err != nil { - return err - } - defer svcmgrConnection.Disconnect() //nolint:errcheck - - // List All Services from the Services Manager. - serviceList, err := svcmgrConnection.ListServices() - if err != nil { - return err - } - - // Iterate through the Services List. - for _, service := range serviceList { - // Get UTF16 service name. - serviceName, err := syscall.UTF16PtrFromString(service) - if err != nil { - _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Service %s get name error: %#v", service, err)) - continue - } - - // Open connection for service handler. - serviceHandle, err := windows.OpenService(svcmgrConnection.Handle, serviceName, windows.GENERIC_READ) - if err != nil { - _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Open service %s error: %#v", service, err)) - continue - } - - // Create handle for each service. - serviceManager := &mgr.Service{Name: service, Handle: serviceHandle} - defer serviceManager.Close() - - // Get Service Configuration. - serviceConfig, err := serviceManager.Config() - if err != nil { - _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get ervice %s config error: %#v", service, err)) - continue - } - - // Get Service Current Status. - serviceStatus, err := serviceManager.Query() - if err != nil { - _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get service %s status error: %#v", service, err)) - continue - } - - pid := fmt.Sprintf("%d", uint64(serviceStatus.ProcessId)) - - ch <- prometheus.MustNewConstMetric( - c.Information, - prometheus.GaugeValue, - 1.0, - strings.ToLower(service), - serviceConfig.DisplayName, - pid, - serviceConfig.ServiceStartName, - ) - - for _, state := range apiStateValues { - isCurrentState := 0.0 - if state == apiStateValues[uint(serviceStatus.State)] { - isCurrentState = 1.0 - } - ch <- prometheus.MustNewConstMetric( - c.State, - prometheus.GaugeValue, - isCurrentState, - strings.ToLower(service), - state, - ) - } - - for _, startMode := range apiStartModeValues { - isCurrentStartMode := 0.0 - if startMode == apiStartModeValues[serviceConfig.StartType] { - isCurrentStartMode = 1.0 - } - ch <- prometheus.MustNewConstMetric( - c.StartMode, - prometheus.GaugeValue, - isCurrentStartMode, - strings.ToLower(service), - startMode, - ) - } - } - return nil -} diff --git a/collector/service_test.go b/collector/service_test.go deleted file mode 100644 index f2d5d57cf6..0000000000 --- a/collector/service_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkServiceCollector(b *testing.B) { - benchmarkCollector(b, "service", newserviceCollector) -} diff --git a/collector/smtp_test.go b/collector/smtp_test.go deleted file mode 100644 index 0234c48e15..0000000000 --- a/collector/smtp_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkSmtpCollector(b *testing.B) { - benchmarkCollector(b, "smtp", newSMTPCollector) -} diff --git a/collector/system.go b/collector/system.go deleted file mode 100644 index 3d0ffdfed8..0000000000 --- a/collector/system.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -// A SystemCollector is a Prometheus collector for WMI metrics -type SystemCollector struct { - logger log.Logger - - ContextSwitchesTotal *prometheus.Desc - ExceptionDispatchesTotal *prometheus.Desc - ProcessorQueueLength *prometheus.Desc - SystemCallsTotal *prometheus.Desc - SystemUpTime *prometheus.Desc - Threads *prometheus.Desc -} - -// newSystemCollector ... -func newSystemCollector(logger log.Logger) (Collector, error) { - const subsystem = "system" - - return &SystemCollector{ - logger: log.With(logger, "collector", subsystem), - ContextSwitchesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "context_switches_total"), - "Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)", - nil, - nil, - ), - ExceptionDispatchesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "exception_dispatches_total"), - "Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)", - nil, - nil, - ), - ProcessorQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_queue_length"), - "Length of processor queue (WMI source: PerfOS_System.ProcessorQueueLength)", - nil, - nil, - ), - SystemCallsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_calls_total"), - "Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)", - nil, - nil, - ), - SystemUpTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "system_up_time"), - "System boot time (WMI source: PerfOS_System.SystemUpTime)", - nil, - nil, - ), - Threads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "threads"), - "Current number of threads (WMI source: PerfOS_System.Threads)", - nil, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *SystemCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting system metrics", "desc", desc, "err", err) - return err - } - return nil -} - -// Win32_PerfRawData_PerfOS_System docs: -// - https://web.archive.org/web/20050830140516/http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_perfrawdata_perfos_system.asp -type system struct { - ContextSwitchesPersec float64 `perflib:"Context Switches/sec"` - ExceptionDispatchesPersec float64 `perflib:"Exception Dispatches/sec"` - ProcessorQueueLength float64 `perflib:"Processor Queue Length"` - SystemCallsPersec float64 `perflib:"System Calls/sec"` - SystemUpTime float64 `perflib:"System Up Time"` - Threads float64 `perflib:"Threads"` -} - -func (c *SystemCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []system - if err := unmarshalObject(ctx.perfObjects["System"], &dst, c.logger); err != nil { - return nil, err - } - - ch <- prometheus.MustNewConstMetric( - c.ContextSwitchesTotal, - prometheus.CounterValue, - dst[0].ContextSwitchesPersec, - ) - ch <- prometheus.MustNewConstMetric( - c.ExceptionDispatchesTotal, - prometheus.CounterValue, - dst[0].ExceptionDispatchesPersec, - ) - ch <- prometheus.MustNewConstMetric( - c.ProcessorQueueLength, - prometheus.GaugeValue, - dst[0].ProcessorQueueLength, - ) - ch <- prometheus.MustNewConstMetric( - c.SystemCallsTotal, - prometheus.CounterValue, - dst[0].SystemCallsPersec, - ) - ch <- prometheus.MustNewConstMetric( - c.SystemUpTime, - prometheus.GaugeValue, - dst[0].SystemUpTime, - ) - ch <- prometheus.MustNewConstMetric( - c.Threads, - prometheus.GaugeValue, - dst[0].Threads, - ) - return nil, nil -} diff --git a/collector/system_test.go b/collector/system_test.go deleted file mode 100644 index 3191bf2f8e..0000000000 --- a/collector/system_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkSystemCollector(b *testing.B) { - benchmarkCollector(b, "system", newSystemCollector) -} diff --git a/collector/tcp_test.go b/collector/tcp_test.go deleted file mode 100644 index 0d33c49711..0000000000 --- a/collector/tcp_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkTCPCollector(b *testing.B) { - benchmarkCollector(b, "tcp", newTCPCollector) -} diff --git a/collector/teradici_pcoip_test.go b/collector/teradici_pcoip_test.go deleted file mode 100644 index 41dc270d37..0000000000 --- a/collector/teradici_pcoip_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkTeradiciPcoipCollector(b *testing.B) { - benchmarkCollector(b, "teradici_pcoip", newTeradiciPcoipCollector) -} diff --git a/collector/terminal_services.go b/collector/terminal_services.go deleted file mode 100644 index eefbc32d17..0000000000 --- a/collector/terminal_services.go +++ /dev/null @@ -1,411 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "errors" - "strings" - - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" -) - -const ConnectionBrokerFeatureID uint32 = 133 - -type Win32_ServerFeature struct { - ID uint32 -} - -func isConnectionBrokerServer(logger log.Logger) bool { - var dst []Win32_ServerFeature - q := queryAll(&dst, logger) - if err := wmi.Query(q, &dst); err != nil { - return false - } - for _, d := range dst { - if d.ID == ConnectionBrokerFeatureID { - return true - } - } - _ = level.Debug(logger).Log("msg", "host is not a connection broker skipping Connection Broker performance metrics.") - return false -} - -// A TerminalServicesCollector is a Prometheus collector for WMI -// Win32_PerfRawData_LocalSessionManager_TerminalServices & Win32_PerfRawData_TermService_TerminalServicesSession metrics -// https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85) -// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/ -type TerminalServicesCollector struct { - logger log.Logger - connectionBrokerEnabled bool - - LocalSessionCount *prometheus.Desc - ConnectionBrokerPerformance *prometheus.Desc - HandleCount *prometheus.Desc - PageFaultsPersec *prometheus.Desc - PageFileBytes *prometheus.Desc - PageFileBytesPeak *prometheus.Desc - PercentPrivilegedTime *prometheus.Desc - PercentProcessorTime *prometheus.Desc - PercentUserTime *prometheus.Desc - PoolNonpagedBytes *prometheus.Desc - PoolPagedBytes *prometheus.Desc - PrivateBytes *prometheus.Desc - ThreadCount *prometheus.Desc - VirtualBytes *prometheus.Desc - VirtualBytesPeak *prometheus.Desc - WorkingSet *prometheus.Desc - WorkingSetPeak *prometheus.Desc -} - -// newTerminalServicesCollector ... -func newTerminalServicesCollector(logger log.Logger) (Collector, error) { - const subsystem = "terminal_services" - logger = log.With(logger, "collector", subsystem) - return &TerminalServicesCollector{ - logger: logger, - connectionBrokerEnabled: isConnectionBrokerServer(logger), - - LocalSessionCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "local_session_count"), - "Number of Terminal Services sessions", - []string{"session"}, - nil, - ), - ConnectionBrokerPerformance: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_broker_performance_total"), - "The total number of connections handled by the Connection Brokers since the service started.", - []string{"connection"}, - nil, - ), - HandleCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "handles"), - "Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process.", - []string{"session_name"}, - nil, - ), - PageFaultsPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "page_fault_total"), - "Rate at which page faults occur in the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page.", - []string{"session_name"}, - nil, - ), - PageFileBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"), - "Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", - []string{"session_name"}, - nil, - ), - PageFileBytesPeak: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes_peak"), - "Maximum number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", - []string{"session_name"}, - nil, - ), - PercentPrivilegedTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "privileged_time_seconds_total"), - "Total elapsed time that the threads of the process have spent executing code in privileged mode.", - []string{"session_name"}, - nil, - ), - PercentProcessorTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_time_seconds_total"), - "Total elapsed time that all of the threads of this process used the processor to execute instructions.", - []string{"session_name"}, - nil, - ), - PercentUserTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "user_time_seconds_total"), - "Total elapsed time that this process's threads have spent executing code in user mode. Applications, environment subsystems, and integral subsystems execute in user mode.", - []string{"session_name"}, - nil, - ), - PoolNonpagedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_non_paged_bytes"), - "Number of bytes in the non-paged pool, an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. This property displays the last observed value only; it is not an average.", - []string{"session_name"}, - nil, - ), - PoolPagedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_paged_bytes"), - "Number of bytes in the paged pool, an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. This property displays the last observed value only; it is not an average.", - []string{"session_name"}, - nil, - ), - PrivateBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "private_bytes"), - "Current number of bytes this process has allocated that cannot be shared with other processes.", - []string{"session_name"}, - nil, - ), - ThreadCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "threads"), - "Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.", - []string{"session_name"}, - nil, - ), - VirtualBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"), - "Current size, in bytes, of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.", - []string{"session_name"}, - nil, - ), - VirtualBytesPeak: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes_peak"), - "Maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process might limit its ability to load libraries.", - []string{"session_name"}, - nil, - ), - WorkingSet: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes"), - "Current number of bytes in the working set of this process. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", - []string{"session_name"}, - nil, - ), - WorkingSetPeak: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes_peak"), - "Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", - []string{"session_name"}, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *TerminalServicesCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collectTSSessionCount(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err) - return err - } - if desc, err := c.collectTSSessionCounters(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err) - return err - } - - // only collect CollectionBrokerPerformance if host is a Connection Broker - if c.connectionBrokerEnabled { - if desc, err := c.collectCollectionBrokerPerformanceCounter(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting Connection Broker performance metrics", "desc", desc, "err", err) - return err - } - } - return nil -} - -type perflibTerminalServices struct { - ActiveSessions float64 `perflib:"Active Sessions"` - InactiveSessions float64 `perflib:"Inactive Sessions"` - TotalSessions float64 `perflib:"Total Sessions"` -} - -func (c *TerminalServicesCollector) collectTSSessionCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - dst := make([]perflibTerminalServices, 0) - err := unmarshalObject(ctx.perfObjects["Terminal Services"], &dst, c.logger) - if err != nil { - return nil, err - } - if len(dst) == 0 { - return nil, errors.New("WMI query returned empty result set") - } - - ch <- prometheus.MustNewConstMetric( - c.LocalSessionCount, - prometheus.GaugeValue, - dst[0].ActiveSessions, - "active", - ) - - ch <- prometheus.MustNewConstMetric( - c.LocalSessionCount, - prometheus.GaugeValue, - dst[0].InactiveSessions, - "inactive", - ) - - ch <- prometheus.MustNewConstMetric( - c.LocalSessionCount, - prometheus.GaugeValue, - dst[0].TotalSessions, - "total", - ) - - return nil, nil -} - -type perflibTerminalServicesSession struct { - Name string - HandleCount float64 `perflib:"Handle Count"` - PageFaultsPersec float64 `perflib:"Page Faults/sec"` - PageFileBytes float64 `perflib:"Page File Bytes"` - PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"` - PercentPrivilegedTime float64 `perflib:"% Privileged Time"` - PercentProcessorTime float64 `perflib:"% Processor Time"` - PercentUserTime float64 `perflib:"% User Time"` - PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` - PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` - PrivateBytes float64 `perflib:"Private Bytes"` - ThreadCount float64 `perflib:"Thread Count"` - VirtualBytes float64 `perflib:"Virtual Bytes"` - VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"` - WorkingSet float64 `perflib:"Working Set"` - WorkingSetPeak float64 `perflib:"Working Set Peak"` -} - -func (c *TerminalServicesCollector) collectTSSessionCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - dst := make([]perflibTerminalServicesSession, 0) - err := unmarshalObject(ctx.perfObjects["Terminal Services Session"], &dst, c.logger) - if err != nil { - return nil, err - } - names := make(map[string]bool) - - for _, d := range dst { - // only connect metrics for remote named sessions - n := strings.ToLower(d.Name) - if n == "" || n == "services" || n == "console" { - continue - } - // don't add name already present in labels list - if _, ok := names[n]; ok { - continue - } - names[n] = true - - ch <- prometheus.MustNewConstMetric( - c.HandleCount, - prometheus.GaugeValue, - d.HandleCount, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PageFaultsPersec, - prometheus.CounterValue, - d.PageFaultsPersec, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PageFileBytes, - prometheus.GaugeValue, - d.PageFileBytes, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PageFileBytesPeak, - prometheus.GaugeValue, - d.PageFileBytesPeak, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PercentPrivilegedTime, - prometheus.CounterValue, - d.PercentPrivilegedTime, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PercentProcessorTime, - prometheus.CounterValue, - d.PercentProcessorTime, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PercentUserTime, - prometheus.CounterValue, - d.PercentUserTime, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PoolNonpagedBytes, - prometheus.GaugeValue, - d.PoolNonpagedBytes, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PoolPagedBytes, - prometheus.GaugeValue, - d.PoolPagedBytes, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.PrivateBytes, - prometheus.GaugeValue, - d.PrivateBytes, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.ThreadCount, - prometheus.GaugeValue, - d.ThreadCount, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.VirtualBytes, - prometheus.GaugeValue, - d.VirtualBytes, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.VirtualBytesPeak, - prometheus.GaugeValue, - d.VirtualBytesPeak, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.WorkingSet, - prometheus.GaugeValue, - d.WorkingSet, - d.Name, - ) - ch <- prometheus.MustNewConstMetric( - c.WorkingSetPeak, - prometheus.GaugeValue, - d.WorkingSetPeak, - d.Name, - ) - } - return nil, nil -} - -type perflibRemoteDesktopConnectionBrokerCounterset struct { - SuccessfulConnections float64 `perflib:"Successful Connections"` - PendingConnections float64 `perflib:"Pending Connections"` - FailedConnections float64 `perflib:"Failed Connections"` -} - -func (c *TerminalServicesCollector) collectCollectionBrokerPerformanceCounter(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - - dst := make([]perflibRemoteDesktopConnectionBrokerCounterset, 0) - err := unmarshalObject(ctx.perfObjects["Remote Desktop Connection Broker Counterset"], &dst, c.logger) - if err != nil { - return nil, err - } - if len(dst) == 0 { - return nil, errors.New("WMI query returned empty result set") - } - - ch <- prometheus.MustNewConstMetric( - c.ConnectionBrokerPerformance, - prometheus.CounterValue, - dst[0].SuccessfulConnections, - "Successful", - ) - - ch <- prometheus.MustNewConstMetric( - c.ConnectionBrokerPerformance, - prometheus.CounterValue, - dst[0].PendingConnections, - "Pending", - ) - - ch <- prometheus.MustNewConstMetric( - c.ConnectionBrokerPerformance, - prometheus.CounterValue, - dst[0].FailedConnections, - "Failed", - ) - - return nil, nil -} diff --git a/collector/terminal_services_test.go b/collector/terminal_services_test.go deleted file mode 100644 index 5f0ad28c2d..0000000000 --- a/collector/terminal_services_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkTerminalServicesCollector(b *testing.B) { - benchmarkCollector(b, "terminal_services", newTerminalServicesCollector) -} diff --git a/collector/thermalzone_test.go b/collector/thermalzone_test.go deleted file mode 100644 index 1a6346bd3e..0000000000 --- a/collector/thermalzone_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkThermalZoneCollector(b *testing.B) { - benchmarkCollector(b, "thermalzone", newThermalZoneCollector) -} diff --git a/collector/time.go b/collector/time.go deleted file mode 100644 index 697f2bbda5..0000000000 --- a/collector/time.go +++ /dev/null @@ -1,132 +0,0 @@ -//go:build windows -// +build windows - -package collector - -import ( - "errors" - - "github.com/go-kit/log" - "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" -) - -// TimeCollector is a Prometheus collector for Perflib counter metrics -type TimeCollector struct { - logger log.Logger - - ClockFrequencyAdjustmentPPBTotal *prometheus.Desc - ComputedTimeOffset *prometheus.Desc - NTPClientTimeSourceCount *prometheus.Desc - NTPRoundtripDelay *prometheus.Desc - NTPServerIncomingRequestsTotal *prometheus.Desc - NTPServerOutgoingResponsesTotal *prometheus.Desc -} - -func newTimeCollector(logger log.Logger) (Collector, error) { - if getWindowsVersion(logger) <= 6.1 { - return nil, errors.New("Windows version older than Server 2016 detected. The time collector will not run and should be disabled via CLI flags or configuration file") - } - - const subsystem = "time" - logger = log.With(logger, "collector", subsystem) - - return &TimeCollector{ - logger: logger, - ClockFrequencyAdjustmentPPBTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clock_frequency_adjustment_ppb_total"), - "Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units.", - nil, - nil, - ), - ComputedTimeOffset: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "computed_time_offset_seconds"), - "Absolute time offset between the system clock and the chosen time source, in seconds", - nil, - nil, - ), - NTPClientTimeSourceCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ntp_client_time_sources"), - "Active number of NTP Time sources being used by the client", - nil, - nil, - ), - NTPRoundtripDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ntp_round_trip_delay_seconds"), - "Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds", - nil, - nil, - ), - NTPServerOutgoingResponsesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ntp_server_outgoing_responses_total"), - "Total number of requests responded to by NTP server", - nil, - nil, - ), - NTPServerIncomingRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ntp_server_incoming_requests_total"), - "Total number of requests received by NTP server", - nil, - nil, - ), - }, nil -} - -// Collect sends the metric values for each metric -// to the provided prometheus Metric channel. -func (c *TimeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - if desc, err := c.collect(ctx, ch); err != nil { - _ = level.Error(c.logger).Log("failed collecting time metrics", "desc", desc, "err", err) - return err - } - return nil -} - -// Perflib "Windows Time Service" -type windowsTime struct { - ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"` - ComputedTimeOffset float64 `perflib:"Computed Time Offset"` - NTPClientTimeSourceCount float64 `perflib:"NTP Client Time Source Count"` - NTPRoundtripDelay float64 `perflib:"NTP Roundtrip Delay"` - NTPServerIncomingRequestsTotal float64 `perflib:"NTP Server Incoming Requests"` - NTPServerOutgoingResponsesTotal float64 `perflib:"NTP Server Outgoing Responses"` -} - -func (c *TimeCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { - var dst []windowsTime // Single-instance class, array is required but will have single entry. - if err := unmarshalObject(ctx.perfObjects["Windows Time Service"], &dst, c.logger); err != nil { - return nil, err - } - - ch <- prometheus.MustNewConstMetric( - c.ClockFrequencyAdjustmentPPBTotal, - prometheus.CounterValue, - dst[0].ClockFrequencyAdjustmentPPBTotal, - ) - ch <- prometheus.MustNewConstMetric( - c.ComputedTimeOffset, - prometheus.GaugeValue, - dst[0].ComputedTimeOffset/1000000, // microseconds -> seconds - ) - ch <- prometheus.MustNewConstMetric( - c.NTPClientTimeSourceCount, - prometheus.GaugeValue, - dst[0].NTPClientTimeSourceCount, - ) - ch <- prometheus.MustNewConstMetric( - c.NTPRoundtripDelay, - prometheus.GaugeValue, - dst[0].NTPRoundtripDelay/1000000, // microseconds -> seconds - ) - ch <- prometheus.MustNewConstMetric( - c.NTPServerIncomingRequestsTotal, - prometheus.CounterValue, - dst[0].NTPServerIncomingRequestsTotal, - ) - ch <- prometheus.MustNewConstMetric( - c.NTPServerOutgoingResponsesTotal, - prometheus.CounterValue, - dst[0].NTPServerOutgoingResponsesTotal, - ) - return nil, nil -} diff --git a/collector/time_test.go b/collector/time_test.go deleted file mode 100644 index 9107bea970..0000000000 --- a/collector/time_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkTimeCollector(b *testing.B) { - benchmarkCollector(b, "time", newTimeCollector) -} diff --git a/collector/vmware_blast_test.go b/collector/vmware_blast_test.go deleted file mode 100644 index ff1b645bda..0000000000 --- a/collector/vmware_blast_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkVmwareBlastCollector(b *testing.B) { - benchmarkCollector(b, "vmware_blast", newVmwareBlastCollector) -} diff --git a/collector/vmware_test.go b/collector/vmware_test.go deleted file mode 100644 index d07d171c38..0000000000 --- a/collector/vmware_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package collector - -import ( - "testing" -) - -func BenchmarkVmwareCollector(b *testing.B) { - benchmarkCollector(b, "vmware", newVmwareCollector) -} diff --git a/exporter.go b/exporter.go index 390824a1dd..3f050c4128 100644 --- a/exporter.go +++ b/exporter.go @@ -1,37 +1,30 @@ //go:build windows -// +build windows package main import ( - //Its important that we do these first so that we can register with the windows service control ASAP to avoid timeouts - "github.com/prometheus-community/windows_exporter/initiate" - winlog "github.com/prometheus-community/windows_exporter/log" - "encoding/json" "fmt" - stdlog "log" "net/http" _ "net/http/pprof" "os" "os/user" "runtime" "sort" - "strconv" "strings" - "time" - "github.com/prometheus-community/windows_exporter/collector" - "github.com/prometheus-community/windows_exporter/config" - "github.com/prometheus-community/windows_exporter/log/flag" - "github.com/yusufpapurcu/wmi" + // Its important that we do these first so that we can register with the windows service control ASAP to avoid timeouts + "github.com/prometheus-community/windows_exporter/pkg/initiate" + winlog "github.com/prometheus-community/windows_exporter/pkg/log" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/alecthomas/kingpin/v2" - "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/prometheus/client_golang/prometheus" - "github.com/prometheus/client_golang/prometheus/collectors" - "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus-community/windows_exporter/pkg/collector" + "github.com/prometheus-community/windows_exporter/pkg/config" + "github.com/prometheus-community/windows_exporter/pkg/log/flag" "github.com/prometheus/common/version" "github.com/prometheus/exporter-toolkit/web" webflag "github.com/prometheus/exporter-toolkit/web/kingpinflag" @@ -48,56 +41,6 @@ type prometheusVersion struct { GoVersion string `json:"goVersion"` } -const ( - defaultCollectors = "cpu,cs,logical_disk,physical_disk,net,os,service,system,textfile" - defaultCollectorsPlaceholder = "[defaults]" -) - -func expandEnabledCollectors(enabled string) []string { - expanded := strings.Replace(enabled, defaultCollectorsPlaceholder, defaultCollectors, -1) - separated := strings.Split(expanded, ",") - unique := map[string]bool{} - for _, s := range separated { - if s != "" { - unique[s] = true - } - } - result := make([]string, 0, len(unique)) - for s := range unique { - result = append(result, s) - } - return result -} - -func loadCollectors(list string, logger log.Logger) (map[string]collector.Collector, error) { - collectors := map[string]collector.Collector{} - enabled := expandEnabledCollectors(list) - - for _, name := range enabled { - c, err := collector.Build(name, logger) - if err != nil { - return nil, err - } - collectors[name] = c - } - - return collectors, nil -} - -func initWbem(logger log.Logger) { - // This initialization prevents a memory leak on WMF 5+. See - // https://github.com/prometheus-community/windows_exporter/issues/77 and - // linked issues for details. - _ = level.Debug(logger).Log("msg", "Initializing SWbemServices") - s, err := wmi.InitializeSWbemServices(wmi.DefaultClient) - if err != nil { - _ = level.Error(logger).Log("err", err) - os.Exit(1) - } - wmi.DefaultClient.AllowMissingFields = true - wmi.DefaultClient.SWbemServicesClient = s -} - func main() { app := kingpin.New("windows_exporter", "A metrics collector for Windows.") var ( @@ -125,7 +68,7 @@ func main() { enabledCollectors = app.Flag( "collectors.enabled", "Comma-separated list of collectors to use. Use '[defaults]' as a placeholder for all the collectors enabled by default."). - Default(defaultCollectors).String() + Default(types.DefaultCollectors).String() printCollectors = app.Flag( "collectors.print", "If true, print available collectors and exit.", @@ -143,7 +86,7 @@ func main() { app.HelpFlag.Short('h') // Initialize collectors before loading and parsing CLI arguments - collector.RegisterCollectorsFlags(app) + collectors := collector.NewWithFlags(app) // Load values from configuration file(s). Executable flags must first be parsed, in order // to load the specified file(s). @@ -155,6 +98,7 @@ func main() { } _ = level.Debug(logger).Log("msg", "Logging has Started") + if *configFile != "" { resolver, err := config.NewResolver(*configFile, logger, *insecure_skip_verify) if err != nil { @@ -183,25 +127,28 @@ func main() { } if *printCollectors { - collectors := collector.Available() - collectorNames := make(sort.StringSlice, 0, len(collectors)) - for _, n := range collectors { - collectorNames = append(collectorNames, n) - } - collectorNames.Sort() + collectorNames := collector.Available() + sort.Strings(collectorNames) + fmt.Printf("Available collectors:\n") for _, n := range collectorNames { fmt.Printf(" - %s\n", n) } + return } - initWbem(logger) + if err = wmi.InitWbem(logger); err != nil { + _ = level.Error(logger).Log("err", err) + os.Exit(1) + } + + enabledCollectorList := utils.ExpandEnabledCollectors(*enabledCollectors) + collectors.Enable(enabledCollectorList) + collectors.SetLogger(logger) // Initialize collectors before loading - collector.RegisterCollectors(logger) - - collectors, err := loadCollectors(*enabledCollectors, logger) + err = collectors.Build() if err != nil { _ = level.Error(logger).Log("msg", "Couldn't load collectors", "err", err) os.Exit(1) @@ -214,34 +161,14 @@ func main() { } _ = level.Info(logger).Log("msg", fmt.Sprintf("Running as %v", u.Username)) + if strings.Contains(u.Username, "ContainerAdministrator") || strings.Contains(u.Username, "ContainerUser") { _ = level.Warn(logger).Log("msg", "Running as a preconfigured Windows Container user. This may mean you do not have Windows HostProcess containers configured correctly and some functionality will not work as expected.") } - _ = level.Info(logger).Log("msg", fmt.Sprintf("Enabled collectors: %v", strings.Join(keys(collectors), ", "))) - - h := &metricsHandler{ - timeoutMargin: *timeoutMargin, - includeExporterMetrics: *disableExporterMetrics, - collectorFactory: func(timeout time.Duration, requestedCollectors []string) (error, *collector.Prometheus) { - filteredCollectors := make(map[string]collector.Collector) - // scrape all enabled collectors if no collector is requested - if len(requestedCollectors) == 0 { - filteredCollectors = collectors - } - for _, name := range requestedCollectors { - col, exists := collectors[name] - if !exists { - return fmt.Errorf("unavailable collector: %s", name), nil - } - filteredCollectors[name] = col - } - return nil, collector.NewPrometheus(timeout, filteredCollectors, logger) - }, - logger: logger, - } + _ = level.Info(logger).Log("msg", fmt.Sprintf("Enabled collectors: %v", strings.Join(enabledCollectorList, ", "))) - http.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, h.ServeHTTP)) + http.HandleFunc(*metricsPath, withConcurrencyLimit(*maxRequests, collectors.BuildServeHTTP(*disableExporterMetrics, *timeoutMargin))) http.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") _, err := fmt.Fprintln(w, `{"status":"ok"}`) @@ -312,14 +239,6 @@ func main() { } } -func keys(m map[string]collector.Collector) []string { - ret := make([]string, 0, len(m)) - for key := range m { - ret = append(ret, key) - } - return ret -} - func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc { if n <= 0 { return next @@ -338,49 +257,3 @@ func withConcurrencyLimit(n int, next http.HandlerFunc) http.HandlerFunc { next(w, r) } } - -type metricsHandler struct { - timeoutMargin float64 - includeExporterMetrics bool - collectorFactory func(timeout time.Duration, requestedCollectors []string) (error, *collector.Prometheus) - logger log.Logger -} - -func (mh *metricsHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { - const defaultTimeout = 10.0 - - var timeoutSeconds float64 - if v := r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds"); v != "" { - var err error - timeoutSeconds, err = strconv.ParseFloat(v, 64) - if err != nil { - _ = level.Warn(mh.logger).Log("msg", fmt.Sprintf("Couldn't parse X-Prometheus-Scrape-Timeout-Seconds: %q. Defaulting timeout to %f", v, defaultTimeout)) - } - } - if timeoutSeconds == 0 { - timeoutSeconds = defaultTimeout - } - timeoutSeconds = timeoutSeconds - mh.timeoutMargin - - reg := prometheus.NewRegistry() - err, wc := mh.collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"]) - if err != nil { - _ = level.Warn(mh.logger).Log("msg", "Couldn't create filtered metrics handler", "err", err) - w.WriteHeader(http.StatusBadRequest) - w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err))) //nolint:errcheck - return - } - reg.MustRegister(wc) - if !mh.includeExporterMetrics { - reg.MustRegister( - collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}), - collectors.NewGoCollector(), - version.NewCollector("windows_exporter"), - ) - } - - h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{ - ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(mh.logger)), "", stdlog.Lshortfile), - }) - h.ServeHTTP(w, r) -} diff --git a/exporter_test.go b/exporter_test.go deleted file mode 100644 index 52b709b66b..0000000000 --- a/exporter_test.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build windows -// +build windows - -package main - -import ( - "sort" - "strings" - "testing" -) - -type expansionTestCase struct { - input string - expectedOutput []string -} - -func TestExpandEnabled(t *testing.T) { - expansionTests := []expansionTestCase{ - {"", []string{}}, - // Default case - {"cs,os", []string{"cs", "os"}}, - // Placeholder expansion - {defaultCollectorsPlaceholder, strings.Split(defaultCollectors, ",")}, - // De-duplication - {"cs,cs", []string{"cs"}}, - // De-duplicate placeholder - {defaultCollectorsPlaceholder + "," + defaultCollectorsPlaceholder, strings.Split(defaultCollectors, ",")}, - // Composite case - {"foo," + defaultCollectorsPlaceholder + ",bar", append(strings.Split(defaultCollectors, ","), "foo", "bar")}, - } - - for _, testCase := range expansionTests { - output := expandEnabledCollectors(testCase.input) - sort.Strings(output) - - success := true - if len(output) != len(testCase.expectedOutput) { - success = false - } else { - sort.Strings(testCase.expectedOutput) - for idx := range output { - if output[idx] != testCase.expectedOutput[idx] { - success = false - break - } - } - } - if !success { - t.Error("For", testCase.input, "expected", testCase.expectedOutput, "got", output) - } - } -} diff --git a/go.mod b/go.mod index 586ec4ffd9..6f67dd0c53 100644 --- a/go.mod +++ b/go.mod @@ -15,10 +15,15 @@ require ( github.com/sirupsen/logrus v1.9.3 // indirect github.com/yusufpapurcu/wmi v1.2.3 go.opencensus.io v0.24.0 // indirect - golang.org/x/sys v0.12.0 + golang.org/x/sys v0.13.0 gopkg.in/yaml.v3 v3.0.1 ) +require ( + github.com/stretchr/testify v1.8.2 + golang.org/x/exp v0.0.0-20231006140011-7918f672742d +) + require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/alecthomas/units v0.0.0-20211218093645-b94a6e3cc137 // indirect @@ -27,6 +32,7 @@ require ( github.com/containerd/cgroups v1.1.0 // indirect github.com/containerd/containerd v1.7.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/go-logfmt/logfmt v0.5.1 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect @@ -36,15 +42,16 @@ require ( github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/mwitkow/go-conntrack v0.0.0-20190716064945-2f068394615f // indirect github.com/pkg/errors v0.9.1 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.11.1 // indirect github.com/xhit/go-str2duration/v2 v2.1.0 // indirect - golang.org/x/crypto v0.9.0 // indirect - golang.org/x/mod v0.10.0 // indirect - golang.org/x/net v0.10.0 // indirect + golang.org/x/crypto v0.14.0 // indirect + golang.org/x/mod v0.13.0 // indirect + golang.org/x/net v0.16.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect - golang.org/x/sync v0.3.0 // indirect - golang.org/x/text v0.9.0 // indirect - golang.org/x/tools v0.8.0 // indirect + golang.org/x/sync v0.4.0 // indirect + golang.org/x/text v0.13.0 // indirect + golang.org/x/tools v0.14.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/genproto v0.0.0-20230410155749-daa745c078e1 // indirect google.golang.org/grpc v1.56.2 // indirect diff --git a/go.sum b/go.sum index d1af611682..4295dfa8da 100644 --- a/go.sum +++ b/go.sum @@ -106,6 +106,7 @@ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/xhit/go-str2duration/v2 v2.1.0 h1:lxklc02Drh6ynqX+DdPyp5pCKLUQpRT8bp8Ydu2Bstc= github.com/xhit/go-str2duration/v2 v2.1.0/go.mod h1:ohY8p+0f07DiV6Em5LKB0s2YpLtXVyJfNt1+BlmyAsU= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= @@ -117,16 +118,18 @@ go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g= -golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= +golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk= -golang.org/x/mod v0.10.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/mod v0.13.0 h1:I/DsJXRlw/8l/0c24sM9yb0T4z9liZTduXvdAWYiysY= +golang.org/x/mod v0.13.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -137,8 +140,8 @@ golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M= -golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= +golang.org/x/net v0.16.0 h1:7eBu7KsSvFDtSXUIDbh3aqlK4DPsZ1rByC8PFfBThos= +golang.org/x/net v0.16.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.8.0 h1:6dkIjl3j3LtZ/O3sTgZTMsLKSftL/B8Zgq4huOIIUu8= golang.org/x/oauth2 v0.8.0/go.mod h1:yr7u4HXZRm1R1kBWqr/xKNqewf0plRYoB7sla+BCIXE= @@ -148,8 +151,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.3.0 h1:ftCYgMx6zT/asHUrPw8BLLscYtGznsLAnjq5RH9P66E= -golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= +golang.org/x/sync v0.4.0 h1:zxkM55ReGkDlKSM+Fu41A+zmbZuaPVbGMzvvdUPznYQ= +golang.org/x/sync v0.4.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -157,13 +160,13 @@ golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0 h1:CM0HF96J0hcLAwsHPJZjfdNzs0gftsLfgKt57wWHJ0o= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= +golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= @@ -172,8 +175,8 @@ golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBn golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= -golang.org/x/tools v0.8.0 h1:vSDcovVPld282ceKgDimkRSC8kpaH1dgyc9UMzlt84Y= -golang.org/x/tools v0.8.0/go.mod h1:JxBZ99ISMI5ViVkT1tr6tdNmXeTrcpVSD3vZ1RsRdN4= +golang.org/x/tools v0.14.0 h1:jvNa2pY0M4r62jkRQ6RwEZZyPcymeL9XZMLBbV7U2nc= +golang.org/x/tools v0.14.0/go.mod h1:uYBEerGOWcJyEORxN+Ek8+TT266gXkNlHdJBwexUsBg= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/collector/ad.go b/pkg/collector/ad/ad.go similarity index 77% rename from collector/ad.go rename to pkg/collector/ad/ad.go index 1630438872..12502cf02b 100644 --- a/collector/ad.go +++ b/pkg/collector/ad/ad.go @@ -1,19 +1,26 @@ //go:build windows -// +build windows -package collector +package ad import ( "errors" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A ADCollector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics -type ADCollector struct { +const Name = "ad" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_DirectoryServices_DirectoryServices metrics +type collector struct { logger log.Logger AddressBookOperationsTotal *prometheus.Desc @@ -80,390 +87,409 @@ type ADCollector struct { TombstonedObjectsVisitedTotal *prometheus.Desc } -// newADCollector ... -func newADCollector(logger log.Logger) (Collector, error) { - const subsystem = "ad" - return &ADCollector{ - logger: log.With(logger, "collector", subsystem), +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} - AddressBookOperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "address_book_operations_total"), - "", - []string{"operation"}, - nil, - ), - AddressBookClientSessions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "address_book_client_sessions"), - "", - nil, - nil, - ), - ApproximateHighestDistinguishedNameTag: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "approximate_highest_distinguished_name_tag"), - "", - nil, - nil, - ), - AtqEstimatedDelaySeconds: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "atq_estimated_delay_seconds"), - "", - nil, - nil, - ), - AtqOutstandingRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "atq_outstanding_requests"), - "", - nil, - nil, - ), - AtqAverageRequestLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "atq_average_request_latency"), - "", - nil, - nil, - ), - AtqCurrentThreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "atq_current_threads"), - "", - []string{"service"}, - nil, - ), - SearchesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "searches_total"), - "", - []string{"scope"}, - nil, - ), - DatabaseOperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "database_operations_total"), - "", - []string{"operation"}, - nil, - ), - BindsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "binds_total"), - "", - []string{"bind_method"}, - nil, - ), - ReplicationHighestUsn: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_highest_usn"), - "", - []string{"state"}, - nil, - ), - IntrasiteReplicationDataBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_data_intrasite_bytes_total"), - "", - []string{"direction"}, - nil, - ), - IntersiteReplicationDataBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_data_intersite_bytes_total"), - "", - []string{"direction"}, - nil, - ), - ReplicationInboundSyncObjectsRemaining: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_sync_objects_remaining"), - "", - nil, - nil, - ), - ReplicationInboundLinkValueUpdatesRemaining: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_link_value_updates_remaining"), - "", - nil, - nil, - ), - ReplicationInboundObjectsUpdatedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_objects_updated_total"), - "", - nil, - nil, - ), - ReplicationInboundObjectsFilteredTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_objects_filtered_total"), - "", - nil, - nil, - ), - ReplicationInboundPropertiesUpdatedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_properties_updated_total"), - "", - nil, - nil, - ), - ReplicationInboundPropertiesFilteredTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_inbound_properties_filtered_total"), - "", - nil, - nil, - ), - ReplicationPendingOperations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_pending_operations"), - "", - nil, - nil, - ), - ReplicationPendingSynchronizations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_pending_synchronizations"), - "", - nil, - nil, - ), - ReplicationSyncRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_sync_requests_total"), - "", - nil, - nil, - ), - ReplicationSyncRequestsSuccessTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_sync_requests_success_total"), - "", - nil, - nil, - ), - ReplicationSyncRequestsSchemaMismatchFailureTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "replication_sync_requests_schema_mismatch_failure_total"), - "", - nil, - nil, - ), - NameTranslationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "name_translations_total"), - "", - []string{"target_name"}, - nil, - ), - ChangeMonitorsRegistered: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "change_monitors_registered"), - "", - nil, - nil, - ), - ChangeMonitorUpdatesPending: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "change_monitor_updates_pending"), - "", - nil, - nil, - ), - NameCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "name_cache_hits_total"), - "", - nil, - nil, - ), - NameCacheLookupsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "name_cache_lookups_total"), - "", - nil, - nil, - ), - DirectoryOperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "directory_operations_total"), - "", - []string{"operation", "origin"}, - nil, - ), - DirectorySearchSuboperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "directory_search_suboperations_total"), - "", - nil, - nil, - ), - SecurityDescriptorPropagationEventsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_events_total"), - "", - nil, - nil, - ), - SecurityDescriptorPropagationEventsQueued: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_events_queued"), - "", - nil, - nil, - ), - SecurityDescriptorPropagationAccessWaitTotalSeconds: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_access_wait_total_seconds"), - "", - nil, - nil, - ), - SecurityDescriptorPropagationItemsQueuedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "security_descriptor_propagation_items_queued_total"), - "", - nil, - nil, - ), - DirectoryServiceThreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "directory_service_threads"), - "", - nil, - nil, - ), - LdapClosedConnectionsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_closed_connections_total"), - "", - nil, - nil, - ), - LdapOpenedConnectionsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_opened_connections_total"), - "", - []string{"type"}, - nil, - ), - LdapActiveThreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_active_threads"), - "", - nil, - nil, - ), - LdapLastBindTimeSeconds: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_last_bind_time_seconds"), - "", - nil, - nil, - ), - LdapSearchesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_searches_total"), - "", - nil, - nil, - ), - LdapUdpOperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_udp_operations_total"), - "", - nil, - nil, - ), - LdapWritesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_writes_total"), - "", - nil, - nil, - ), - LdapClientSessions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ldap_client_sessions"), - "This is the number of sessions opened by LDAP clients at the time the data is taken. This is helpful in determining LDAP client activity and if the DC is able to handle the load. Of course, spikes during normal periods of authentication — such as first thing in the morning — are not necessarily a problem, but long sustained periods of high values indicate an overworked DC.", - nil, - nil, - ), - LinkValuesCleanedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "link_values_cleaned_total"), - "", - nil, - nil, - ), - PhantomObjectsCleanedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "phantom_objects_cleaned_total"), - "", - nil, - nil, - ), - PhantomObjectsVisitedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "phantom_objects_visited_total"), - "", - nil, - nil, - ), - SamGroupMembershipEvaluationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_evaluations_total"), - "", - []string{"group_type"}, - nil, - ), - SamGroupMembershipGlobalCatalogEvaluationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_global_catalog_evaluations_total"), - "", - nil, - nil, - ), - SamGroupMembershipEvaluationsNontransitiveTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_evaluations_nontransitive_total"), - "", - nil, - nil, - ), - SamGroupMembershipEvaluationsTransitiveTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_group_membership_evaluations_transitive_total"), - "", - nil, - nil, - ), - SamGroupEvaluationLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_group_evaluation_latency"), - "The mean latency of the last 100 group evaluations performed for authentication", - []string{"evaluation_type"}, - nil, - ), - SamComputerCreationRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_computer_creation_requests_total"), - "", - nil, - nil, - ), - SamComputerCreationSuccessfulRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_computer_creation_successful_requests_total"), - "", - nil, - nil, - ), - SamUserCreationRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_user_creation_requests_total"), - "", - nil, - nil, - ), - SamUserCreationSuccessfulRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_user_creation_successful_requests_total"), - "", - nil, - nil, - ), - SamQueryDisplayRequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_query_display_requests_total"), - "", - nil, - nil, - ), - SamEnumerationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_enumerations_total"), - "", - nil, - nil, - ), - SamMembershipChangesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_membership_changes_total"), - "", - nil, - nil, - ), - SamPasswordChangesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sam_password_changes_total"), - "", - nil, - nil, - ), - TombstonedObjectsCollectedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tombstoned_objects_collected_total"), - "", - nil, - nil, - ), - TombstonedObjectsVisitedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tombstoned_objects_visited_total"), - "", - nil, - nil, - ), - }, nil +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.AddressBookOperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "address_book_operations_total"), + "", + []string{"operation"}, + nil, + ) + c.AddressBookClientSessions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "address_book_client_sessions"), + "", + nil, + nil, + ) + c.ApproximateHighestDistinguishedNameTag = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "approximate_highest_distinguished_name_tag"), + "", + nil, + nil, + ) + c.AtqEstimatedDelaySeconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "atq_estimated_delay_seconds"), + "", + nil, + nil, + ) + c.AtqOutstandingRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "atq_outstanding_requests"), + "", + nil, + nil, + ) + c.AtqAverageRequestLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "atq_average_request_latency"), + "", + nil, + nil, + ) + c.AtqCurrentThreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "atq_current_threads"), + "", + []string{"service"}, + nil, + ) + c.SearchesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "searches_total"), + "", + []string{"scope"}, + nil, + ) + c.DatabaseOperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "database_operations_total"), + "", + []string{"operation"}, + nil, + ) + c.BindsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "binds_total"), + "", + []string{"bind_method"}, + nil, + ) + c.ReplicationHighestUsn = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_highest_usn"), + "", + []string{"state"}, + nil, + ) + c.IntrasiteReplicationDataBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_data_intrasite_bytes_total"), + "", + []string{"direction"}, + nil, + ) + c.IntersiteReplicationDataBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_data_intersite_bytes_total"), + "", + []string{"direction"}, + nil, + ) + c.ReplicationInboundSyncObjectsRemaining = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_inbound_sync_objects_remaining"), + "", + nil, + nil, + ) + c.ReplicationInboundLinkValueUpdatesRemaining = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_inbound_link_value_updates_remaining"), + "", + nil, + nil, + ) + c.ReplicationInboundObjectsUpdatedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_inbound_objects_updated_total"), + "", + nil, + nil, + ) + c.ReplicationInboundObjectsFilteredTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_inbound_objects_filtered_total"), + "", + nil, + nil, + ) + c.ReplicationInboundPropertiesUpdatedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_inbound_properties_updated_total"), + "", + nil, + nil, + ) + c.ReplicationInboundPropertiesFilteredTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_inbound_properties_filtered_total"), + "", + nil, + nil, + ) + c.ReplicationPendingOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_pending_operations"), + "", + nil, + nil, + ) + c.ReplicationPendingSynchronizations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_pending_synchronizations"), + "", + nil, + nil, + ) + c.ReplicationSyncRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_sync_requests_total"), + "", + nil, + nil, + ) + c.ReplicationSyncRequestsSuccessTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_sync_requests_success_total"), + "", + nil, + nil, + ) + c.ReplicationSyncRequestsSchemaMismatchFailureTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "replication_sync_requests_schema_mismatch_failure_total"), + "", + nil, + nil, + ) + c.NameTranslationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "name_translations_total"), + "", + []string{"target_name"}, + nil, + ) + c.ChangeMonitorsRegistered = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "change_monitors_registered"), + "", + nil, + nil, + ) + c.ChangeMonitorUpdatesPending = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "change_monitor_updates_pending"), + "", + nil, + nil, + ) + c.NameCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "name_cache_hits_total"), + "", + nil, + nil, + ) + c.NameCacheLookupsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "name_cache_lookups_total"), + "", + nil, + nil, + ) + c.DirectoryOperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "directory_operations_total"), + "", + []string{"operation", "origin"}, + nil, + ) + c.DirectorySearchSuboperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "directory_search_suboperations_total"), + "", + nil, + nil, + ) + c.SecurityDescriptorPropagationEventsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "security_descriptor_propagation_events_total"), + "", + nil, + nil, + ) + c.SecurityDescriptorPropagationEventsQueued = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "security_descriptor_propagation_events_queued"), + "", + nil, + nil, + ) + c.SecurityDescriptorPropagationAccessWaitTotalSeconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "security_descriptor_propagation_access_wait_total_seconds"), + "", + nil, + nil, + ) + c.SecurityDescriptorPropagationItemsQueuedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "security_descriptor_propagation_items_queued_total"), + "", + nil, + nil, + ) + c.DirectoryServiceThreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "directory_service_threads"), + "", + nil, + nil, + ) + c.LdapClosedConnectionsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_closed_connections_total"), + "", + nil, + nil, + ) + c.LdapOpenedConnectionsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_opened_connections_total"), + "", + []string{"type"}, + nil, + ) + c.LdapActiveThreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_active_threads"), + "", + nil, + nil, + ) + c.LdapLastBindTimeSeconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_last_bind_time_seconds"), + "", + nil, + nil, + ) + c.LdapSearchesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_searches_total"), + "", + nil, + nil, + ) + c.LdapUdpOperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_udp_operations_total"), + "", + nil, + nil, + ) + c.LdapWritesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_writes_total"), + "", + nil, + nil, + ) + c.LdapClientSessions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ldap_client_sessions"), + "This is the number of sessions opened by LDAP clients at the time the data is taken. This is helpful in determining LDAP client activity and if the DC is able to handle the load. Of course, spikes during normal periods of authentication — such as first thing in the morning — are not necessarily a problem, but long sustained periods of high values indicate an overworked DC.", + nil, + nil, + ) + c.LinkValuesCleanedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "link_values_cleaned_total"), + "", + nil, + nil, + ) + c.PhantomObjectsCleanedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "phantom_objects_cleaned_total"), + "", + nil, + nil, + ) + c.PhantomObjectsVisitedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "phantom_objects_visited_total"), + "", + nil, + nil, + ) + c.SamGroupMembershipEvaluationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_group_membership_evaluations_total"), + "", + []string{"group_type"}, + nil, + ) + c.SamGroupMembershipGlobalCatalogEvaluationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_group_membership_global_catalog_evaluations_total"), + "", + nil, + nil, + ) + c.SamGroupMembershipEvaluationsNontransitiveTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_group_membership_evaluations_nontransitive_total"), + "", + nil, + nil, + ) + c.SamGroupMembershipEvaluationsTransitiveTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_group_membership_evaluations_transitive_total"), + "", + nil, + nil, + ) + c.SamGroupEvaluationLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_group_evaluation_latency"), + "The mean latency of the last 100 group evaluations performed for authentication", + []string{"evaluation_type"}, + nil, + ) + c.SamComputerCreationRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_computer_creation_requests_total"), + "", + nil, + nil, + ) + c.SamComputerCreationSuccessfulRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_computer_creation_successful_requests_total"), + "", + nil, + nil, + ) + c.SamUserCreationRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_user_creation_requests_total"), + "", + nil, + nil, + ) + c.SamUserCreationSuccessfulRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_user_creation_successful_requests_total"), + "", + nil, + nil, + ) + c.SamQueryDisplayRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_query_display_requests_total"), + "", + nil, + nil, + ) + c.SamEnumerationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_enumerations_total"), + "", + nil, + nil, + ) + c.SamMembershipChangesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_membership_changes_total"), + "", + nil, + nil, + ) + c.SamPasswordChangesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sam_password_changes_total"), + "", + nil, + nil, + ) + + c.TombstonedObjectsCollectedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tombstoned_objects_collected_total"), + "", + nil, + nil, + ) + c.TombstonedObjectsVisitedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tombstoned_objects_visited_total"), + "", + nil, + nil, + ) + + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *ADCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting ad metrics", "desc", desc, "err", err) return err @@ -623,9 +649,9 @@ type Win32_PerfRawData_DirectoryServices_DirectoryServices struct { TransitivesuboperationsPersec uint32 } -func (c *ADCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_DirectoryServices_DirectoryServices - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/ad/ad_test.go b/pkg/collector/ad/ad_test.go new file mode 100644 index 0000000000..693ba762e5 --- /dev/null +++ b/pkg/collector/ad/ad_test.go @@ -0,0 +1,12 @@ +package ad_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/ad" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, ad.Name, ad.NewWithFlags) +} diff --git a/collector/adcs.go b/pkg/collector/adcs/adcs.go similarity index 52% rename from collector/adcs.go rename to pkg/collector/adcs/adcs.go index aa2516ad53..84eb22ed9a 100644 --- a/collector/adcs.go +++ b/pkg/collector/adcs/adcs.go @@ -1,18 +1,27 @@ //go:build windows -// +build windows -package collector +package adcs import ( "errors" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" ) -type adcsCollector struct { +const Name = "adcs" + +type Config struct{} + +var ConfigDefaults = Config{} + +type collector struct { logger log.Logger RequestsPerSecond *prometheus.Desc @@ -30,94 +39,112 @@ type adcsCollector struct { SignedCertificateTimestampListProcessingTime *prometheus.Desc } -// ADCSCollectorMethod ... -func adcsCollectorMethod(logger log.Logger) (Collector, error) { - const subsystem = "adcs" - return &adcsCollector{ - logger: log.With(logger, "collector", subsystem), - - RequestsPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "requests_total"), - "Total certificate requests processed", - []string{"cert_template"}, - nil, - ), - RequestProcessingTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "request_processing_time_seconds"), - "Last time elapsed for certificate requests", - []string{"cert_template"}, - nil, - ), - RetrievalsPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "retrievals_total"), - "Total certificate retrieval requests processed", - []string{"cert_template"}, - nil, - ), - RetrievalProcessingTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "retrievals_processing_time_seconds"), - "Last time elapsed for certificate retrieval request", - []string{"cert_template"}, - nil, - ), - FailedRequestsPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failed_requests_total"), - "Total failed certificate requests processed", - []string{"cert_template"}, - nil, - ), - IssuedRequestsPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "issued_requests_total"), - "Total issued certificate requests processed", - []string{"cert_template"}, - nil, - ), - PendingRequestsPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pending_requests_total"), - "Total pending certificate requests processed", - []string{"cert_template"}, - nil, - ), - RequestCryptographicSigningTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "request_cryptographic_signing_time_seconds"), - "Last time elapsed for signing operation request", - []string{"cert_template"}, - nil, - ), - RequestPolicyModuleProcessingTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "request_policy_module_processing_time_seconds"), - "Last time elapsed for policy module processing request", - []string{"cert_template"}, - nil, - ), - ChallengeResponsesPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "challenge_responses_total"), - "Total certificate challenge responses processed", - []string{"cert_template"}, - nil, - ), - ChallengeResponseProcessingTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "challenge_response_processing_time_seconds"), - "Last time elapsed for challenge response", - []string{"cert_template"}, - nil, - ), - SignedCertificateTimestampListsPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "signed_certificate_timestamp_lists_total"), - "Total Signed Certificate Timestamp Lists processed", - []string{"cert_template"}, - nil, - ), - SignedCertificateTimestampListProcessingTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "signed_certificate_timestamp_list_processing_time_seconds"), - "Last time elapsed for Signed Certificate Timestamp List", - []string{"cert_template"}, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Certification Authority"}, nil +} + +func (c *collector) Build() error { + c.RequestsPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "requests_total"), + "Total certificate requests processed", + []string{"cert_template"}, + nil, + ) + c.RequestProcessingTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "request_processing_time_seconds"), + "Last time elapsed for certificate requests", + []string{"cert_template"}, + nil, + ) + c.RetrievalsPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "retrievals_total"), + "Total certificate retrieval requests processed", + []string{"cert_template"}, + nil, + ) + c.RetrievalProcessingTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "retrievals_processing_time_seconds"), + "Last time elapsed for certificate retrieval request", + []string{"cert_template"}, + nil, + ) + c.FailedRequestsPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failed_requests_total"), + "Total failed certificate requests processed", + []string{"cert_template"}, + nil, + ) + c.IssuedRequestsPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "issued_requests_total"), + "Total issued certificate requests processed", + []string{"cert_template"}, + nil, + ) + c.PendingRequestsPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pending_requests_total"), + "Total pending certificate requests processed", + []string{"cert_template"}, + nil, + ) + c.RequestCryptographicSigningTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "request_cryptographic_signing_time_seconds"), + "Last time elapsed for signing operation request", + []string{"cert_template"}, + nil, + ) + c.RequestPolicyModuleProcessingTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "request_policy_module_processing_time_seconds"), + "Last time elapsed for policy module processing request", + []string{"cert_template"}, + nil, + ) + c.ChallengeResponsesPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "challenge_responses_total"), + "Total certificate challenge responses processed", + []string{"cert_template"}, + nil, + ) + c.ChallengeResponseProcessingTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "challenge_response_processing_time_seconds"), + "Last time elapsed for challenge response", + []string{"cert_template"}, + nil, + ) + c.SignedCertificateTimestampListsPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "signed_certificate_timestamp_lists_total"), + "Total Signed Certificate Timestamp Lists processed", + []string{"cert_template"}, + nil, + ) + c.SignedCertificateTimestampListProcessingTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "signed_certificate_timestamp_list_processing_time_seconds"), + "Last time elapsed for Signed Certificate Timestamp List", + []string{"cert_template"}, + nil, + ) + + return nil } -func (c *adcsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectADCSCounters(ctx, ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting ADCS metrics", "desc", desc, "err", err) return err @@ -142,17 +169,17 @@ type perflibADCS struct { SignedCertificateTimestampListProcessingTime float64 `perflib:"Signed Certificate Timestamp List processing time (ms)"` } -func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectADCSCounters(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { dst := make([]perflibADCS, 0) - if _, ok := ctx.perfObjects["Certification Authority"]; !ok { - return nil, errors.New("Perflib did not contain an entry for Certification Authority") + if _, ok := ctx.PerfObjects["Certification Authority"]; !ok { + return nil, errors.New("perflib did not contain an entry for Certification Authority") } - err := unmarshalObject(ctx.perfObjects["Certification Authority"], &dst, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["Certification Authority"], &dst, c.logger) if err != nil { return nil, err } if len(dst) == 0 { - return nil, errors.New("Perflib query for Certification Authority (ADCS) returned empty result set") + return nil, errors.New("perflib query for Certification Authority (ADCS) returned empty result set") } for _, d := range dst { @@ -169,7 +196,7 @@ func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- promet ch <- prometheus.MustNewConstMetric( c.RequestProcessingTime, prometheus.GaugeValue, - milliSecToSec(d.RequestProcessingTime), + utils.MilliSecToSec(d.RequestProcessingTime), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -181,7 +208,7 @@ func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- promet ch <- prometheus.MustNewConstMetric( c.RetrievalProcessingTime, prometheus.GaugeValue, - milliSecToSec(d.RetrievalProcessingTime), + utils.MilliSecToSec(d.RetrievalProcessingTime), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -205,13 +232,13 @@ func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- promet ch <- prometheus.MustNewConstMetric( c.RequestCryptographicSigningTime, prometheus.GaugeValue, - milliSecToSec(d.RequestCryptographicSigningTime), + utils.MilliSecToSec(d.RequestCryptographicSigningTime), d.Name, ) ch <- prometheus.MustNewConstMetric( c.RequestPolicyModuleProcessingTime, prometheus.GaugeValue, - milliSecToSec(d.RequestPolicyModuleProcessingTime), + utils.MilliSecToSec(d.RequestPolicyModuleProcessingTime), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -223,7 +250,7 @@ func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- promet ch <- prometheus.MustNewConstMetric( c.ChallengeResponseProcessingTime, prometheus.GaugeValue, - milliSecToSec(d.ChallengeResponseProcessingTime), + utils.MilliSecToSec(d.ChallengeResponseProcessingTime), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -235,7 +262,7 @@ func (c *adcsCollector) collectADCSCounters(ctx *ScrapeContext, ch chan<- promet ch <- prometheus.MustNewConstMetric( c.SignedCertificateTimestampListProcessingTime, prometheus.GaugeValue, - milliSecToSec(d.SignedCertificateTimestampListProcessingTime), + utils.MilliSecToSec(d.SignedCertificateTimestampListProcessingTime), d.Name, ) } diff --git a/pkg/collector/adcs/adcs_test.go b/pkg/collector/adcs/adcs_test.go new file mode 100644 index 0000000000..5f4b9680b1 --- /dev/null +++ b/pkg/collector/adcs/adcs_test.go @@ -0,0 +1,12 @@ +package adcs_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/adcs" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, adcs.Name, adcs.NewWithFlags) +} diff --git a/collector/adfs.go b/pkg/collector/adfs/adfs.go similarity index 60% rename from collector/adfs.go rename to pkg/collector/adfs/adfs.go index 1ed0f8d783..545d959c14 100644 --- a/collector/adfs.go +++ b/pkg/collector/adfs/adfs.go @@ -1,16 +1,24 @@ //go:build windows -// +build windows -package collector +package adfs import ( "math" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) -type adfsCollector struct { +const Name = "adfs" + +type Config struct{} + +var ConfigDefaults = Config{} + +type collector struct { logger log.Logger adLoginConnectionFailures *prometheus.Desc @@ -58,272 +66,289 @@ type adfsCollector struct { federationMetadataRequests *prometheus.Desc } -// newADFSCollector constructs a new adfsCollector -func newADFSCollector(logger log.Logger) (Collector, error) { - const subsystem = "adfs" - - return &adfsCollector{ - logger: log.With(logger, "collector", subsystem), - - adLoginConnectionFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ad_login_connection_failures_total"), - "Total number of connection failures to an Active Directory domain controller", - nil, - nil, - ), - certificateAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "certificate_authentications_total"), - "Total number of User Certificate authentications", - nil, - nil, - ), - deviceAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "device_authentications_total"), - "Total number of Device authentications", - nil, - nil, - ), - extranetAccountLockouts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "extranet_account_lockouts_total"), - "Total number of Extranet Account Lockouts", - nil, - nil, - ), - federatedAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "federated_authentications_total"), - "Total number of authentications from a federated source", - nil, - nil, - ), - passportAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "passport_authentications_total"), - "Total number of Microsoft Passport SSO authentications", - nil, - nil, - ), - passiveRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "passive_requests_total"), - "Total number of passive (browser-based) requests", - nil, - nil, - ), - passwordChangeFailed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "password_change_failed_total"), - "Total number of failed password changes", - nil, - nil, - ), - passwordChangeSucceeded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "password_change_succeeded_total"), - "Total number of successful password changes", - nil, - nil, - ), - tokenRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "token_requests_total"), - "Total number of token requests", - nil, - nil, - ), - windowsIntegratedAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "windows_integrated_authentications_total"), - "Total number of Windows integrated authentications (Kerberos/NTLM)", - nil, - nil, - ), - oAuthAuthZRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_authorization_requests_total"), - "Total number of incoming requests to the OAuth Authorization endpoint", - nil, - nil, - ), - oAuthClientAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_authentication_success_total"), - "Total number of successful OAuth client Authentications", - nil, - nil, - ), - oAuthClientAuthenticationsFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_authentication_failure_total"), - "Total number of failed OAuth client Authentications", - nil, - nil, - ), - oAuthClientCredentialsRequestFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_credentials_failure_total"), - "Total number of failed OAuth Client Credentials Requests", - nil, - nil, - ), - oAuthClientCredentialsRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_credentials_success_total"), - "Total number of successful RP tokens issued for OAuth Client Credentials Requests", - nil, - nil, - ), - oAuthClientPrivateKeyJwtAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jwt_authentication_failure_total"), - "Total number of failed OAuth Client Private Key Jwt Authentications", - nil, - nil, - ), - oAuthClientPrivateKeyJwtAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_privkey_jwt_authentications_success_total"), - "Total number of successful OAuth Client Private Key Jwt Authentications", - nil, - nil, - ), - oAuthClientSecretBasicAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_basic_authentications_failure_total"), - "Total number of failed OAuth Client Secret Basic Authentications", - nil, - nil, - ), - oAuthClientSecretBasicAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_basic_authentications_success_total"), - "Total number of successful OAuth Client Secret Basic Authentications", - nil, - nil, - ), - oAuthClientSecretPostAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_post_authentications_failure_total"), - "Total number of failed OAuth Client Secret Post Authentications", - nil, - nil, - ), - oAuthClientSecretPostAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_secret_post_authentications_success_total"), - "Total number of successful OAuth Client Secret Post Authentications", - nil, - nil, - ), - oAuthClientWindowsIntegratedAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_windows_authentications_failure_total"), - "Total number of failed OAuth Client Windows Integrated Authentications", - nil, - nil, - ), - oAuthClientWindowsIntegratedAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_client_windows_authentications_success_total"), - "Total number of successful OAuth Client Windows Integrated Authentications", - nil, - nil, - ), - oAuthLogonCertificateRequestFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_logon_certificate_requests_failure_total"), - "Total number of failed OAuth Logon Certificate Requests", - nil, - nil, - ), - oAuthLogonCertificateTokenRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_logon_certificate_token_requests_success_total"), - "Total number of successful RP tokens issued for OAuth Logon Certificate Requests", - nil, - nil, - ), - oAuthPasswordGrantRequestFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_password_grant_requests_failure_total"), - "Total number of failed OAuth Password Grant Requests", - nil, - nil, - ), - oAuthPasswordGrantRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_password_grant_requests_success_total"), - "Total number of successful OAuth Password Grant Requests", - nil, - nil, - ), - oAuthTokenRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "oauth_token_requests_success_total"), - "Total number of successful RP tokens issued over OAuth protocol", - nil, - nil, - ), - samlPTokenRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "samlp_token_requests_success_total"), - "Total number of successful RP tokens issued over SAML-P protocol", - nil, - nil, - ), - ssoAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sso_authentications_failure_total"), - "Total number of failed SSO authentications", - nil, - nil, - ), - ssoAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sso_authentications_success_total"), - "Total number of successful SSO authentications", - nil, - nil, - ), - wsfedTokenRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "wsfed_token_requests_success_total"), - "Total number of successful RP tokens issued over WS-Fed protocol", - nil, - nil, - ), - wstrustTokenRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "wstrust_token_requests_success_total"), - "Total number of successful RP tokens issued over WS-Trust protocol", - nil, - nil, - ), - upAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "userpassword_authentications_failure_total"), - "Total number of failed AD U/P authentications", - nil, - nil, - ), - upAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "userpassword_authentications_success_total"), - "Total number of successful AD U/P authentications", - nil, - nil, - ), - externalAuthenticationFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "external_authentications_failure_total"), - "Total number of failed authentications from external MFA providers", - nil, - nil, - ), - externalAuthentications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "external_authentications_success_total"), - "Total number of successful authentications from external MFA providers", - nil, - nil, - ), - artifactDBFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "db_artifact_failure_total"), - "Total number of failures connecting to the artifact database", - nil, - nil, - ), - avgArtifactDBQueryTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "db_artifact_query_time_seconds_total"), - "Accumulator of time taken for an artifact database query", - nil, - nil, - ), - configDBFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "db_config_failure_total"), - "Total number of failures connecting to the configuration database", - nil, - nil, - ), - avgConfigDBQueryTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "db_config_query_time_seconds_total"), - "Accumulator of time taken for a configuration database query", - nil, - nil, - ), - federationMetadataRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "federation_metadata_requests_total"), - "Total number of Federation Metadata requests", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"AD FS"}, nil +} + +func (c *collector) Build() error { + c.adLoginConnectionFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ad_login_connection_failures_total"), + "Total number of connection failures to an Active Directory domain controller", + nil, + nil, + ) + c.certificateAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "certificate_authentications_total"), + "Total number of User Certificate authentications", + nil, + nil, + ) + c.deviceAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "device_authentications_total"), + "Total number of Device authentications", + nil, + nil, + ) + c.extranetAccountLockouts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "extranet_account_lockouts_total"), + "Total number of Extranet Account Lockouts", + nil, + nil, + ) + c.federatedAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "federated_authentications_total"), + "Total number of authentications from a federated source", + nil, + nil, + ) + c.passportAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "passport_authentications_total"), + "Total number of Microsoft Passport SSO authentications", + nil, + nil, + ) + c.passiveRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "passive_requests_total"), + "Total number of passive (browser-based) requests", + nil, + nil, + ) + c.passwordChangeFailed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "password_change_failed_total"), + "Total number of failed password changes", + nil, + nil, + ) + c.passwordChangeSucceeded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "password_change_succeeded_total"), + "Total number of successful password changes", + nil, + nil, + ) + c.tokenRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "token_requests_total"), + "Total number of token requests", + nil, + nil, + ) + c.windowsIntegratedAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "windows_integrated_authentications_total"), + "Total number of Windows integrated authentications (Kerberos/NTLM)", + nil, + nil, + ) + c.oAuthAuthZRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_authorization_requests_total"), + "Total number of incoming requests to the OAuth Authorization endpoint", + nil, + nil, + ) + c.oAuthClientAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_authentication_success_total"), + "Total number of successful OAuth client Authentications", + nil, + nil, + ) + c.oAuthClientAuthenticationsFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_authentication_failure_total"), + "Total number of failed OAuth client Authentications", + nil, + nil, + ) + c.oAuthClientCredentialsRequestFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_credentials_failure_total"), + "Total number of failed OAuth Client Credentials Requests", + nil, + nil, + ) + c.oAuthClientCredentialsRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_credentials_success_total"), + "Total number of successful RP tokens issued for OAuth Client Credentials Requests", + nil, + nil, + ) + c.oAuthClientPrivateKeyJwtAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_privkey_jwt_authentication_failure_total"), + "Total number of failed OAuth Client Private Key Jwt Authentications", + nil, + nil, + ) + c.oAuthClientPrivateKeyJwtAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_privkey_jwt_authentications_success_total"), + "Total number of successful OAuth Client Private Key Jwt Authentications", + nil, + nil, + ) + c.oAuthClientSecretBasicAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_secret_basic_authentications_failure_total"), + "Total number of failed OAuth Client Secret Basic Authentications", + nil, + nil, + ) + c.oAuthClientSecretBasicAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_secret_basic_authentications_success_total"), + "Total number of successful OAuth Client Secret Basic Authentications", + nil, + nil, + ) + c.oAuthClientSecretPostAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_secret_post_authentications_failure_total"), + "Total number of failed OAuth Client Secret Post Authentications", + nil, + nil, + ) + c.oAuthClientSecretPostAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_secret_post_authentications_success_total"), + "Total number of successful OAuth Client Secret Post Authentications", + nil, + nil, + ) + c.oAuthClientWindowsIntegratedAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_windows_authentications_failure_total"), + "Total number of failed OAuth Client Windows Integrated Authentications", + nil, + nil, + ) + c.oAuthClientWindowsIntegratedAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_client_windows_authentications_success_total"), + "Total number of successful OAuth Client Windows Integrated Authentications", + nil, + nil, + ) + c.oAuthLogonCertificateRequestFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_logon_certificate_requests_failure_total"), + "Total number of failed OAuth Logon Certificate Requests", + nil, + nil, + ) + c.oAuthLogonCertificateTokenRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_logon_certificate_token_requests_success_total"), + "Total number of successful RP tokens issued for OAuth Logon Certificate Requests", + nil, + nil, + ) + c.oAuthPasswordGrantRequestFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_password_grant_requests_failure_total"), + "Total number of failed OAuth Password Grant Requests", + nil, + nil, + ) + c.oAuthPasswordGrantRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_password_grant_requests_success_total"), + "Total number of successful OAuth Password Grant Requests", + nil, + nil, + ) + c.oAuthTokenRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "oauth_token_requests_success_total"), + "Total number of successful RP tokens issued over OAuth protocol", + nil, + nil, + ) + c.samlPTokenRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "samlp_token_requests_success_total"), + "Total number of successful RP tokens issued over SAML-P protocol", + nil, + nil, + ) + c.ssoAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sso_authentications_failure_total"), + "Total number of failed SSO authentications", + nil, + nil, + ) + c.ssoAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sso_authentications_success_total"), + "Total number of successful SSO authentications", + nil, + nil, + ) + c.wsfedTokenRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "wsfed_token_requests_success_total"), + "Total number of successful RP tokens issued over WS-Fed protocol", + nil, + nil, + ) + c.wstrustTokenRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "wstrust_token_requests_success_total"), + "Total number of successful RP tokens issued over WS-Trust protocol", + nil, + nil, + ) + c.upAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "userpassword_authentications_failure_total"), + "Total number of failed AD U/P authentications", + nil, + nil, + ) + c.upAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "userpassword_authentications_success_total"), + "Total number of successful AD U/P authentications", + nil, + nil, + ) + c.externalAuthenticationFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "external_authentications_failure_total"), + "Total number of failed authentications from external MFA providers", + nil, + nil, + ) + c.externalAuthentications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "external_authentications_success_total"), + "Total number of successful authentications from external MFA providers", + nil, + nil, + ) + c.artifactDBFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "db_artifact_failure_total"), + "Total number of failures connecting to the artifact database", + nil, + nil, + ) + c.avgArtifactDBQueryTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "db_artifact_query_time_seconds_total"), + "Accumulator of time taken for an artifact database query", + nil, + nil, + ) + c.configDBFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "db_config_failure_total"), + "Total number of failures connecting to the configuration database", + nil, + nil, + ) + c.avgConfigDBQueryTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "db_config_query_time_seconds_total"), + "Accumulator of time taken for a configuration database query", + nil, + nil, + ) + c.federationMetadataRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "federation_metadata_requests_total"), + "Total number of Federation Metadata requests", + nil, + nil, + ) + + return nil } type perflibADFS struct { @@ -372,9 +397,9 @@ type perflibADFS struct { FederationMetadataRequests float64 `perflib:"Federation Metadata Requests"` } -func (c *adfsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var adfsData []perflibADFS - err := unmarshalObject(ctx.perfObjects["AD FS"], &adfsData, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["AD FS"], &adfsData, c.logger) if err != nil { return err } diff --git a/pkg/collector/adfs/adfs_test.go b/pkg/collector/adfs/adfs_test.go new file mode 100644 index 0000000000..255f2685ed --- /dev/null +++ b/pkg/collector/adfs/adfs_test.go @@ -0,0 +1,12 @@ +package adfs_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/adfs" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, adfs.Name, adfs.NewWithFlags) +} diff --git a/collector/cache.go b/pkg/collector/cache/cache.go similarity index 58% rename from collector/cache.go rename to pkg/collector/cache/cache.go index 8cf494165e..8ba31912d5 100644 --- a/collector/cache.go +++ b/pkg/collector/cache/cache.go @@ -1,16 +1,24 @@ //go:build windows -// +build windows -package collector +package cache import ( + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) -// A CacheCollector is a Prometheus collector for Perflib Cache metrics -type CacheCollector struct { +const Name = "cache" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for Perflib Cache metrics +type collector struct { logger log.Logger AsyncCopyReadsTotal *prometheus.Desc @@ -44,191 +52,208 @@ type CacheCollector struct { SyncPinReadsTotal *prometheus.Desc } -// NewCacheCollector ... -func newCacheCollector(logger log.Logger) (Collector, error) { - const subsystem = "cache" - return &CacheCollector{ - logger: log.With(logger, "collector", subsystem), - - AsyncCopyReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "async_copy_reads_total"), - "(AsyncCopyReadsTotal)", - nil, - nil, - ), - AsyncDataMapsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "async_data_maps_total"), - "(AsyncDataMapsTotal)", - nil, - nil, - ), - AsyncFastReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "async_fast_reads_total"), - "(AsyncFastReadsTotal)", - nil, - nil, - ), - AsyncMDLReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "async_mdl_reads_total"), - "(AsyncMDLReadsTotal)", - nil, - nil, - ), - AsyncPinReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "async_pin_reads_total"), - "(AsyncPinReadsTotal)", - nil, - nil, - ), - CopyReadHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "copy_read_hits_total"), - "(CopyReadHitsTotal)", - nil, - nil, - ), - CopyReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "copy_reads_total"), - "(CopyReadsTotal)", - nil, - nil, - ), - DataFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "data_flushes_total"), - "(DataFlushesTotal)", - nil, - nil, - ), - DataFlushPagesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "data_flush_pages_total"), - "(DataFlushPagesTotal)", - nil, - nil, - ), - DataMapHitsPercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "data_map_hits_percent"), - "(DataMapHitsPercent)", - nil, - nil, - ), - DataMapPinsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "data_map_pins_total"), - "(DataMapPinsTotal)", - nil, - nil, - ), - DataMapsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "data_maps_total"), - "(DataMapsTotal)", - nil, - nil, - ), - DirtyPages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dirty_pages"), - "(DirtyPages)", - nil, - nil, - ), - DirtyPageThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dirty_page_threshold"), - "(DirtyPageThreshold)", - nil, - nil, - ), - FastReadNotPossiblesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "fast_read_not_possibles_total"), - "(FastReadNotPossiblesTotal)", - nil, - nil, - ), - FastReadResourceMissesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "fast_read_resource_misses_total"), - "(FastReadResourceMissesTotal)", - nil, - nil, - ), - FastReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "fast_reads_total"), - "(FastReadsTotal)", - nil, - nil, - ), - LazyWriteFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "lazy_write_flushes_total"), - "(LazyWriteFlushesTotal)", - nil, - nil, - ), - LazyWritePagesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "lazy_write_pages_total"), - "(LazyWritePagesTotal)", - nil, - nil, - ), - MDLReadHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mdl_read_hits_total"), - "(MDLReadHitsTotal)", - nil, - nil, - ), - MDLReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mdl_reads_total"), - "(MDLReadsTotal)", - nil, - nil, - ), - PinReadHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pin_read_hits_total"), - "(PinReadHitsTotal)", - nil, - nil, - ), - PinReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pin_reads_total"), - "(PinReadsTotal)", - nil, - nil, - ), - ReadAheadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "read_aheads_total"), - "(ReadAheadsTotal)", - nil, - nil, - ), - SyncCopyReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sync_copy_reads_total"), - "(SyncCopyReadsTotal)", - nil, - nil, - ), - SyncDataMapsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sync_data_maps_total"), - "(SyncDataMapsTotal)", - nil, - nil, - ), - SyncFastReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sync_fast_reads_total"), - "(SyncFastReadsTotal)", - nil, - nil, - ), - SyncMDLReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sync_mdl_reads_total"), - "(SyncMDLReadsTotal)", - nil, - nil, - ), - SyncPinReadsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sync_pin_reads_total"), - "(SyncPinReadsTotal)", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.AsyncCopyReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "async_copy_reads_total"), + "(AsyncCopyReadsTotal)", + nil, + nil, + ) + c.AsyncDataMapsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "async_data_maps_total"), + "(AsyncDataMapsTotal)", + nil, + nil, + ) + c.AsyncFastReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "async_fast_reads_total"), + "(AsyncFastReadsTotal)", + nil, + nil, + ) + c.AsyncMDLReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "async_mdl_reads_total"), + "(AsyncMDLReadsTotal)", + nil, + nil, + ) + c.AsyncPinReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "async_pin_reads_total"), + "(AsyncPinReadsTotal)", + nil, + nil, + ) + c.CopyReadHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "copy_read_hits_total"), + "(CopyReadHitsTotal)", + nil, + nil, + ) + c.CopyReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "copy_reads_total"), + "(CopyReadsTotal)", + nil, + nil, + ) + c.DataFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "data_flushes_total"), + "(DataFlushesTotal)", + nil, + nil, + ) + c.DataFlushPagesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "data_flush_pages_total"), + "(DataFlushPagesTotal)", + nil, + nil, + ) + c.DataMapHitsPercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "data_map_hits_percent"), + "(DataMapHitsPercent)", + nil, + nil, + ) + c.DataMapPinsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "data_map_pins_total"), + "(DataMapPinsTotal)", + nil, + nil, + ) + c.DataMapsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "data_maps_total"), + "(DataMapsTotal)", + nil, + nil, + ) + c.DirtyPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dirty_pages"), + "(DirtyPages)", + nil, + nil, + ) + c.DirtyPageThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dirty_page_threshold"), + "(DirtyPageThreshold)", + nil, + nil, + ) + c.FastReadNotPossiblesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "fast_read_not_possibles_total"), + "(FastReadNotPossiblesTotal)", + nil, + nil, + ) + c.FastReadResourceMissesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "fast_read_resource_misses_total"), + "(FastReadResourceMissesTotal)", + nil, + nil, + ) + c.FastReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "fast_reads_total"), + "(FastReadsTotal)", + nil, + nil, + ) + c.LazyWriteFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "lazy_write_flushes_total"), + "(LazyWriteFlushesTotal)", + nil, + nil, + ) + c.LazyWritePagesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "lazy_write_pages_total"), + "(LazyWritePagesTotal)", + nil, + nil, + ) + c.MDLReadHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mdl_read_hits_total"), + "(MDLReadHitsTotal)", + nil, + nil, + ) + c.MDLReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mdl_reads_total"), + "(MDLReadsTotal)", + nil, + nil, + ) + c.PinReadHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pin_read_hits_total"), + "(PinReadHitsTotal)", + nil, + nil, + ) + c.PinReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pin_reads_total"), + "(PinReadsTotal)", + nil, + nil, + ) + c.ReadAheadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_aheads_total"), + "(ReadAheadsTotal)", + nil, + nil, + ) + c.SyncCopyReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sync_copy_reads_total"), + "(SyncCopyReadsTotal)", + nil, + nil, + ) + c.SyncDataMapsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sync_data_maps_total"), + "(SyncDataMapsTotal)", + nil, + nil, + ) + c.SyncFastReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sync_fast_reads_total"), + "(SyncFastReadsTotal)", + nil, + nil, + ) + c.SyncMDLReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sync_mdl_reads_total"), + "(SyncMDLReadsTotal)", + nil, + nil, + ) + c.SyncPinReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sync_pin_reads_total"), + "(SyncPinReadsTotal)", + nil, + nil, + ) + return nil } // Collect implements the Collector interface -func (c *CacheCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ctx, ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting cache metrics", "desc", desc, "err", err) return err @@ -270,9 +295,9 @@ type perflibCache struct { SyncPinReadsTotal float64 `perflib:"Sync Pin Reads/sec"` } -func (c *CacheCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []perflibCache // Single-instance class, array is required but will have single entry. - if err := unmarshalObject(ctx.perfObjects["Cache"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["Cache"], &dst, c.logger); err != nil { return nil, err } diff --git a/pkg/collector/collector.go b/pkg/collector/collector.go new file mode 100644 index 0000000000..ae90f87e23 --- /dev/null +++ b/pkg/collector/collector.go @@ -0,0 +1,105 @@ +//go:build windows + +package collector + +import ( + "slices" + "strings" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" +) + +type Collectors struct { + logger log.Logger + + collectors map[string]types.Collector + perfCounterQuery string +} + +// NewWithFlags To be called by the exporter for collector initialization before running kingpin.Parse +func NewWithFlags(app *kingpin.Application) Collectors { + collectors := map[string]types.Collector{} + + for name, builder := range Map { + collectors[name] = builder(app) + } + + return New(collectors) +} + +// New To be called by the external libraries for collector initialization without running kingpin.Parse +func New(collectors map[string]types.Collector) Collectors { + return Collectors{ + collectors: collectors, + } +} + +func (c *Collectors) SetLogger(logger log.Logger) { + c.logger = logger + + for _, collector := range c.collectors { + collector.SetLogger(logger) + } +} + +func (c *Collectors) SetPerfCounterQuery() error { + var ( + err error + + perfCounterDependencies []string + perfCounterNames []string + perfIndicies []string + ) + + for _, collector := range c.collectors { + perfCounterNames, err = collector.GetPerfCounter() + if err != nil { + return err + } + + perfIndicies = make([]string, 0, len(perfCounterNames)) + for _, cn := range perfCounterNames { + perfIndicies = append(perfIndicies, perflib.MapCounterToIndex(cn)) + } + + perfCounterDependencies = append(perfCounterDependencies, strings.Join(perfIndicies, " ")) + } + + c.perfCounterQuery = strings.Join(perfCounterDependencies, " ") + + return nil +} + +// Enable removes all collectors that not enabledCollectors +func (c *Collectors) Enable(enabledCollectors []string) { + for name := range c.collectors { + if !slices.Contains(enabledCollectors, name) { + delete(c.collectors, name) + } + } +} + +// Build To be called by the exporter for collector initialization +func (c *Collectors) Build() error { + var err error + for _, collector := range c.collectors { + if err = collector.Build(); err != nil { + return err + } + } + + return nil +} + +// PrepareScrapeContext creates a ScrapeContext to be used during a single scrape +func (c *Collectors) PrepareScrapeContext() (*types.ScrapeContext, error) { + objs, err := perflib.GetPerflibSnapshot(c.perfCounterQuery) + if err != nil { + return nil, err + } + + return &types.ScrapeContext{PerfObjects: objs}, nil +} diff --git a/pkg/collector/config.go b/pkg/collector/config.go new file mode 100644 index 0000000000..8944e03086 --- /dev/null +++ b/pkg/collector/config.go @@ -0,0 +1,165 @@ +package collector + +import ( + "github.com/prometheus-community/windows_exporter/pkg/collector/ad" + "github.com/prometheus-community/windows_exporter/pkg/collector/adcs" + "github.com/prometheus-community/windows_exporter/pkg/collector/adfs" + "github.com/prometheus-community/windows_exporter/pkg/collector/cache" + "github.com/prometheus-community/windows_exporter/pkg/collector/container" + "github.com/prometheus-community/windows_exporter/pkg/collector/cpu" + "github.com/prometheus-community/windows_exporter/pkg/collector/cpu_info" + "github.com/prometheus-community/windows_exporter/pkg/collector/cs" + "github.com/prometheus-community/windows_exporter/pkg/collector/dfsr" + "github.com/prometheus-community/windows_exporter/pkg/collector/dhcp" + "github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive" + "github.com/prometheus-community/windows_exporter/pkg/collector/dns" + "github.com/prometheus-community/windows_exporter/pkg/collector/exchange" + "github.com/prometheus-community/windows_exporter/pkg/collector/hyperv" + "github.com/prometheus-community/windows_exporter/pkg/collector/iis" + "github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk" + "github.com/prometheus-community/windows_exporter/pkg/collector/logon" + "github.com/prometheus-community/windows_exporter/pkg/collector/memory" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_cluster" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_network" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_node" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resource" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resourcegroup" + "github.com/prometheus-community/windows_exporter/pkg/collector/msmq" + "github.com/prometheus-community/windows_exporter/pkg/collector/mssql" + "github.com/prometheus-community/windows_exporter/pkg/collector/net" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrexceptions" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrinterop" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrjit" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrloading" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrlocksandthreads" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrmemory" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrremoting" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrsecurity" + "github.com/prometheus-community/windows_exporter/pkg/collector/nps" + "github.com/prometheus-community/windows_exporter/pkg/collector/os" + "github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk" + "github.com/prometheus-community/windows_exporter/pkg/collector/process" + "github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx" + "github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task" + "github.com/prometheus-community/windows_exporter/pkg/collector/service" + "github.com/prometheus-community/windows_exporter/pkg/collector/smtp" + "github.com/prometheus-community/windows_exporter/pkg/collector/system" + "github.com/prometheus-community/windows_exporter/pkg/collector/tcp" + "github.com/prometheus-community/windows_exporter/pkg/collector/teradici_pcoip" + "github.com/prometheus-community/windows_exporter/pkg/collector/terminal_services" + "github.com/prometheus-community/windows_exporter/pkg/collector/textfile" + "github.com/prometheus-community/windows_exporter/pkg/collector/thermalzone" + "github.com/prometheus-community/windows_exporter/pkg/collector/time" + "github.com/prometheus-community/windows_exporter/pkg/collector/vmware" + "github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast" +) + +type Config struct { + Ad ad.Config `yaml:"ad"` + Adcs adcs.Config `yaml:"adcs"` + Adfs adfs.Config `yaml:"adfs"` + Cache cache.Config `yaml:"cache"` + Container container.Config `yaml:"container"` + Cpu cpu.Config `yaml:"cpu"` + CpuInfo cpu_info.Config `yaml:"cpu_info"` + Cs cs.Config `yaml:"cs"` + Dfsr dfsr.Config `yaml:"dfsr"` + Dhcp dhcp.Config `yaml:"dhcp"` + Diskdrive diskdrive.Config `yaml:"diskdrive"` + Dns dns.Config `yaml:"dns"` + Exchange exchange.Config `yaml:"exchange"` + Fsrmquota exchange.Config `yaml:"fsrmquota"` + Hyperv hyperv.Config `yaml:"hyperv"` + Iis iis.Config `yaml:"iis"` + LogicalDisk logical_disk.Config `yaml:"logical_disk"` + Logon logon.Config `yaml:"logon"` + Memory memory.Config `yaml:"memory"` + MsclusterCluster mscluster_cluster.Config `yaml:"mscluster_cluster"` + MsclusterNetwork mscluster_network.Config `yaml:"mscluster_network"` + MsclusterNode mscluster_node.Config `yaml:"mscluster_node"` + MsclusterResource mscluster_resource.Config `yaml:"mscluster_resource"` + MsclusterResourceGroup mscluster_resourcegroup.Config `yaml:"mscluster_resourcegroup"` + Msmq msmq.Config `yaml:"msmq"` + Mssql mssql.Config `yaml:"mssql"` + Net net.Config `yaml:"net"` + NetframeworkClrexceptions netframework_clrexceptions.Config `yaml:"netframework_clrexceptions"` + NetframeworkClrinterop netframework_clrinterop.Config `yaml:"netframework_clrinterop"` + NetframeworkClrjit netframework_clrjit.Config `yaml:"netframework_clrjit"` + NetframeworkClrloading netframework_clrloading.Config `yaml:"netframework_clrloading"` + NetframeworkClrlocksandthreads netframework_clrlocksandthreads.Config `yaml:"netframework_clrlocksandthreads"` + NetframeworkClrmemory netframework_clrmemory.Config `yaml:"netframework_clrmemory"` + NetframeworkClrremoting netframework_clrremoting.Config `yaml:"netframework_clrremoting"` + NetframeworkClrsecurity netframework_clrsecurity.Config `yaml:"netframework_clrsecurity"` + Nps nps.Config `yaml:"nps"` + Os os.Config `yaml:"os"` + PhysicalDisk physical_disk.Config `yaml:"physical_disk"` + Process process.Config `yaml:"process"` + RemoteFx remote_fx.Config `yaml:"remote_fx"` + ScheduledTask scheduled_task.Config `yaml:"scheduled_task"` + Service service.Config `yaml:"service"` + Smtp smtp.Config `yaml:"smtp"` + System system.Config `yaml:"system"` + TeradiciPcoip teradici_pcoip.Config `yaml:"teradici_pcoip"` + Tcp tcp.Config `yaml:"tcp"` + TerminalServices terminal_services.Config `yaml:"terminal_services"` + Textfile textfile.Config `yaml:"textfile"` + Thermalzone thermalzone.Config `yaml:"thermalzone"` + Time time.Config `yaml:"time"` + Vmware vmware.Config `yaml:"vmware"` + VmwareBlast vmware_blast.Config `yaml:"vmware_blast"` +} + +var ConfigDefaults = Config{ + Ad: ad.ConfigDefaults, + Adcs: adcs.ConfigDefaults, + Adfs: adfs.ConfigDefaults, + Cache: cache.ConfigDefaults, + Container: container.ConfigDefaults, + Cpu: cpu.ConfigDefaults, + CpuInfo: cpu_info.ConfigDefaults, + Cs: cs.ConfigDefaults, + Dfsr: dfsr.ConfigDefaults, + Dhcp: dhcp.ConfigDefaults, + Diskdrive: diskdrive.ConfigDefaults, + Dns: dns.ConfigDefaults, + Exchange: exchange.ConfigDefaults, + Fsrmquota: exchange.ConfigDefaults, + Hyperv: hyperv.ConfigDefaults, + Iis: iis.ConfigDefaults, + LogicalDisk: logical_disk.ConfigDefaults, + Logon: logon.ConfigDefaults, + Memory: memory.ConfigDefaults, + MsclusterCluster: mscluster_cluster.ConfigDefaults, + MsclusterNetwork: mscluster_network.ConfigDefaults, + MsclusterNode: mscluster_node.ConfigDefaults, + MsclusterResource: mscluster_resource.ConfigDefaults, + MsclusterResourceGroup: mscluster_resourcegroup.ConfigDefaults, + Msmq: msmq.ConfigDefaults, + Mssql: mssql.ConfigDefaults, + Net: net.ConfigDefaults, + NetframeworkClrexceptions: netframework_clrexceptions.ConfigDefaults, + NetframeworkClrinterop: netframework_clrinterop.ConfigDefaults, + NetframeworkClrjit: netframework_clrjit.ConfigDefaults, + NetframeworkClrloading: netframework_clrloading.ConfigDefaults, + NetframeworkClrlocksandthreads: netframework_clrlocksandthreads.ConfigDefaults, + NetframeworkClrmemory: netframework_clrmemory.ConfigDefaults, + NetframeworkClrremoting: netframework_clrremoting.ConfigDefaults, + NetframeworkClrsecurity: netframework_clrsecurity.ConfigDefaults, + Nps: nps.ConfigDefaults, + Os: os.ConfigDefaults, + PhysicalDisk: physical_disk.ConfigDefaults, + Process: process.ConfigDefaults, + RemoteFx: remote_fx.ConfigDefaults, + ScheduledTask: scheduled_task.ConfigDefaults, + Service: service.ConfigDefaults, + Smtp: smtp.ConfigDefaults, + System: system.ConfigDefaults, + TeradiciPcoip: teradici_pcoip.ConfigDefaults, + Tcp: tcp.ConfigDefaults, + TerminalServices: terminal_services.ConfigDefaults, + Textfile: textfile.ConfigDefaults, + Thermalzone: thermalzone.ConfigDefaults, + Time: time.ConfigDefaults, + Vmware: vmware.ConfigDefaults, + VmwareBlast: vmware_blast.ConfigDefaults, +} diff --git a/pkg/collector/container/container.go b/pkg/collector/container/container.go new file mode 100644 index 0000000000..65dea5b147 --- /dev/null +++ b/pkg/collector/container/container.go @@ -0,0 +1,400 @@ +//go:build windows + +package container + +import ( + "fmt" + "strings" + + "github.com/Microsoft/hcsshim" + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "container" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for containers metrics +type collector struct { + logger log.Logger + + // Presence + ContainerAvailable *prometheus.Desc + + // Number of containers + ContainersCount *prometheus.Desc + // memory + UsageCommitBytes *prometheus.Desc + UsageCommitPeakBytes *prometheus.Desc + UsagePrivateWorkingSetBytes *prometheus.Desc + + // CPU + RuntimeTotal *prometheus.Desc + RuntimeUser *prometheus.Desc + RuntimeKernel *prometheus.Desc + + // Network + BytesReceived *prometheus.Desc + BytesSent *prometheus.Desc + PacketsReceived *prometheus.Desc + PacketsSent *prometheus.Desc + DroppedPacketsIncoming *prometheus.Desc + DroppedPacketsOutgoing *prometheus.Desc + + // Storage + ReadCountNormalized *prometheus.Desc + ReadSizeBytes *prometheus.Desc + WriteCountNormalized *prometheus.Desc + WriteSizeBytes *prometheus.Desc +} + +// New constructs a new collector +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.ContainerAvailable = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "available"), + "Available", + []string{"container_id"}, + nil, + ) + c.ContainersCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "count"), + "Number of containers", + nil, + nil, + ) + c.UsageCommitBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_bytes"), + "Memory Usage Commit Bytes", + []string{"container_id"}, + nil, + ) + c.UsageCommitPeakBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memory_usage_commit_peak_bytes"), + "Memory Usage Commit Peak Bytes", + []string{"container_id"}, + nil, + ) + c.UsagePrivateWorkingSetBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memory_usage_private_working_set_bytes"), + "Memory Usage Private Working Set Bytes", + []string{"container_id"}, + nil, + ) + c.RuntimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_total"), + "Total Run time in Seconds", + []string{"container_id"}, + nil, + ) + c.RuntimeUser = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_usermode"), + "Run Time in User mode in Seconds", + []string{"container_id"}, + nil, + ) + c.RuntimeKernel = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_usage_seconds_kernelmode"), + "Run time in Kernel mode in Seconds", + []string{"container_id"}, + nil, + ) + c.BytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "network_receive_bytes_total"), + "Bytes Received on Interface", + []string{"container_id", "interface"}, + nil, + ) + c.BytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "network_transmit_bytes_total"), + "Bytes Sent on Interface", + []string{"container_id", "interface"}, + nil, + ) + c.PacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_total"), + "Packets Received on Interface", + []string{"container_id", "interface"}, + nil, + ) + c.PacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_total"), + "Packets Sent on Interface", + []string{"container_id", "interface"}, + nil, + ) + c.DroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "network_receive_packets_dropped_total"), + "Dropped Incoming Packets on Interface", + []string{"container_id", "interface"}, + nil, + ) + c.DroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "network_transmit_packets_dropped_total"), + "Dropped Outgoing Packets on Interface", + []string{"container_id", "interface"}, + nil, + ) + c.ReadCountNormalized = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "storage_read_count_normalized_total"), + "Read Count Normalized", + []string{"container_id"}, + nil, + ) + c.ReadSizeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "storage_read_size_bytes_total"), + "Read Size Bytes", + []string{"container_id"}, + nil, + ) + c.WriteCountNormalized = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "storage_write_count_normalized_total"), + "Write Count Normalized", + []string{"container_id"}, + nil, + ) + c.WriteSizeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "storage_write_size_bytes_total"), + "Write Size Bytes", + []string{"container_id"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("msg", "failed collecting collector metrics", "desc", desc, "err", err) + return err + } + return nil +} + +// containerClose closes the container resource +func (c *collector) containerClose(container hcsshim.Container) { + err := container.Close() + if err != nil { + _ = level.Error(c.logger).Log("err", err) + } +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + // Types Container is passed to get the containers compute systems only + containers, err := hcsshim.GetContainers(hcsshim.ComputeSystemQuery{Types: []string{"Container"}}) + if err != nil { + _ = level.Error(c.logger).Log("msg", "Err in Getting containers", "err", err) + return nil, err + } + + count := len(containers) + + ch <- prometheus.MustNewConstMetric( + c.ContainersCount, + prometheus.GaugeValue, + float64(count), + ) + if count == 0 { + return nil, nil + } + + containerPrefixes := make(map[string]string) + + for _, containerDetails := range containers { + // https://stackoverflow.com/questions/45617758/proper-way-to-release-resources-with-defer-in-a-loop + func() { + container, err := hcsshim.OpenContainer(containerDetails.ID) + if container != nil { + defer c.containerClose(container) + } + if err != nil { + _ = level.Error(c.logger).Log("msg", "err in opening container", "containerId", containerDetails.ID, "err", err) + return + } + + cstats, err := container.Statistics() + if err != nil { + _ = level.Error(c.logger).Log("msg", "err in fetching container Statistics", "containerId", containerDetails.ID, "err", err) + return + } + + containerIdWithPrefix := getContainerIdWithPrefix(containerDetails) + containerPrefixes[containerDetails.ID] = containerIdWithPrefix + + ch <- prometheus.MustNewConstMetric( + c.ContainerAvailable, + prometheus.CounterValue, + 1, + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.UsageCommitBytes, + prometheus.GaugeValue, + float64(cstats.Memory.UsageCommitBytes), + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.UsageCommitPeakBytes, + prometheus.GaugeValue, + float64(cstats.Memory.UsageCommitPeakBytes), + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.UsagePrivateWorkingSetBytes, + prometheus.GaugeValue, + float64(cstats.Memory.UsagePrivateWorkingSetBytes), + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.RuntimeTotal, + prometheus.CounterValue, + float64(cstats.Processor.TotalRuntime100ns)*perflib.TicksToSecondScaleFactor, + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.RuntimeUser, + prometheus.CounterValue, + float64(cstats.Processor.RuntimeUser100ns)*perflib.TicksToSecondScaleFactor, + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.RuntimeKernel, + prometheus.CounterValue, + float64(cstats.Processor.RuntimeKernel100ns)*perflib.TicksToSecondScaleFactor, + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.ReadCountNormalized, + prometheus.CounterValue, + float64(cstats.Storage.ReadCountNormalized), + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.ReadSizeBytes, + prometheus.CounterValue, + float64(cstats.Storage.ReadSizeBytes), + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.WriteCountNormalized, + prometheus.CounterValue, + float64(cstats.Storage.WriteCountNormalized), + containerIdWithPrefix, + ) + ch <- prometheus.MustNewConstMetric( + c.WriteSizeBytes, + prometheus.CounterValue, + float64(cstats.Storage.WriteSizeBytes), + containerIdWithPrefix, + ) + }() + } + + hnsEndpoints, err := hcsshim.HNSListEndpointRequest() + if err != nil { + _ = level.Warn(c.logger).Log("msg", "Failed to collect network stats for containers") + return nil, nil + } + + if len(hnsEndpoints) == 0 { + _ = level.Info(c.logger).Log("msg", fmt.Sprintf("No network stats for containers to collect")) + return nil, nil + } + + for _, endpoint := range hnsEndpoints { + endpointStats, err := hcsshim.GetHNSEndpointStats(endpoint.Id) + if err != nil { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for interface %s", endpoint.Id), "err", err) + continue + } + + for _, containerId := range endpoint.SharedContainers { + containerIdWithPrefix, ok := containerPrefixes[containerId] + endpointId := strings.ToUpper(endpoint.Id) + + if !ok { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Failed to collect network stats for container %s", containerId)) + continue + } + + ch <- prometheus.MustNewConstMetric( + c.BytesReceived, + prometheus.CounterValue, + float64(endpointStats.BytesReceived), + containerIdWithPrefix, endpointId, + ) + + ch <- prometheus.MustNewConstMetric( + c.BytesSent, + prometheus.CounterValue, + float64(endpointStats.BytesSent), + containerIdWithPrefix, endpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsReceived, + prometheus.CounterValue, + float64(endpointStats.PacketsReceived), + containerIdWithPrefix, endpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.PacketsSent, + prometheus.CounterValue, + float64(endpointStats.PacketsSent), + containerIdWithPrefix, endpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.DroppedPacketsIncoming, + prometheus.CounterValue, + float64(endpointStats.DroppedPacketsIncoming), + containerIdWithPrefix, endpointId, + ) + ch <- prometheus.MustNewConstMetric( + c.DroppedPacketsOutgoing, + prometheus.CounterValue, + float64(endpointStats.DroppedPacketsOutgoing), + containerIdWithPrefix, endpointId, + ) + } + } + + return nil, nil +} + +func getContainerIdWithPrefix(containerDetails hcsshim.ContainerProperties) string { + switch containerDetails.Owner { + case "containerd-shim-runhcs-v1.exe": + return "containerd://" + containerDetails.ID + default: + // default to docker or if owner is not set + return "docker://" + containerDetails.ID + } +} diff --git a/pkg/collector/container/container_test.go b/pkg/collector/container/container_test.go new file mode 100644 index 0000000000..88f5032de2 --- /dev/null +++ b/pkg/collector/container/container_test.go @@ -0,0 +1,12 @@ +package container_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/container" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, container.Name, container.NewWithFlags) +} diff --git a/collector/cpu.go b/pkg/collector/cpu/cpu.go similarity index 59% rename from collector/cpu.go rename to pkg/collector/cpu/cpu.go index 4d99473980..9dc7638f78 100644 --- a/collector/cpu.go +++ b/pkg/collector/cpu/cpu.go @@ -1,30 +1,32 @@ //go:build windows -// +build windows -package collector +package cpu import ( "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/winversion" "github.com/prometheus/client_golang/prometheus" ) -type cpuCollectorBasic struct { +const Name = "cpu" + +type Config struct{} + +var ConfigDefaults = Config{} + +type collector struct { logger log.Logger CStateSecondsTotal *prometheus.Desc TimeTotal *prometheus.Desc InterruptsTotal *prometheus.Desc DPCsTotal *prometheus.Desc -} -type cpuCollectorFull struct { - logger log.Logger - CStateSecondsTotal *prometheus.Desc - TimeTotal *prometheus.Desc - InterruptsTotal *prometheus.Desc - DPCsTotal *prometheus.Desc ClockInterruptsTotal *prometheus.Desc IdleBreakEventsTotal *prometheus.Desc ParkingStatus *prometheus.Desc @@ -37,129 +39,155 @@ type cpuCollectorFull struct { ProcessorPrivUtility *prometheus.Desc } -// newCPUCollector constructs a new cpuCollector, appropriate for the running OS -func newCPUCollector(logger log.Logger) (Collector, error) { - const subsystem = "cpu" - logger = log.With(logger, "collector", subsystem) +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + if winversion.WindowsVersionFloat > 6.05 { + return []string{"Processor Information"}, nil + } + return []string{"Processor"}, nil +} + +func (c *collector) Build() error { + c.CStateSecondsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"), + "Time spent in low-power idle state", + []string{"core", "state"}, + nil, + ) + c.TimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "time_total"), + "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", + []string{"core", "mode"}, + nil, + ) + c.InterruptsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"), + "Total number of received and serviced hardware interrupts", + []string{"core"}, + nil, + ) + c.DPCsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"), + "Total number of received and serviced deferred procedure calls (DPCs)", + []string{"core"}, + nil, + ) - version := getWindowsVersion(logger) // For Windows 2008 (version 6.0) or earlier we only have the "Processor" // class. As of Windows 2008 R2 (version 6.1) the more detailed // "Processor Information" set is available (although some of the counters // are added in later versions, so we aren't guaranteed to get all of // them). // Value 6.05 was selected to split between Windows versions. - if version < 6.05 { - return &cpuCollectorBasic{ - logger: logger, - CStateSecondsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"), - "Time spent in low-power idle state", - []string{"core", "state"}, - nil, - ), - TimeTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "time_total"), - "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", - []string{"core", "mode"}, - nil, - ), - InterruptsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "interrupts_total"), - "Total number of received and serviced hardware interrupts", - []string{"core"}, - nil, - ), - DPCsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dpcs_total"), - "Total number of received and serviced deferred procedure calls (DPCs)", - []string{"core"}, - nil, - ), - }, nil + if winversion.WindowsVersionFloat < 6.05 { + return nil + } + + c.CStateSecondsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cstate_seconds_total"), + "Time spent in low-power idle state", + []string{"core", "state"}, + nil, + ) + c.TimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "time_total"), + "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", + []string{"core", "mode"}, + nil, + ) + c.InterruptsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "interrupts_total"), + "Total number of received and serviced hardware interrupts", + []string{"core"}, + nil, + ) + c.DPCsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dpcs_total"), + "Total number of received and serviced deferred procedure calls (DPCs)", + []string{"core"}, + nil, + ) + c.ClockInterruptsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clock_interrupts_total"), + "Total number of received and serviced clock tick interrupts", + []string{"core"}, + nil, + ) + c.IdleBreakEventsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "idle_break_events_total"), + "Total number of time processor was woken from idle", + []string{"core"}, + nil, + ) + c.ParkingStatus = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "parking_status"), + "Parking Status represents whether a processor is parked or not", + []string{"core"}, + nil, + ) + c.ProcessorFrequencyMHz = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "core_frequency_mhz"), + "Core frequency in megahertz", + []string{"core"}, + nil, + ) + c.ProcessorPerformance = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_performance_total"), + "Processor Performance is the average performance of the processor while it is executing instructions, as a percentage of the nominal performance of the processor. On some processors, Processor Performance may exceed 100%", + []string{"core"}, + nil, + ) + c.ProcessorMPerf = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_mperf_total"), + "Processor MPerf is the number of TSC ticks incremented while executing instructions", + []string{"core"}, + nil, + ) + c.ProcessorRTC = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_rtc_total"), + "Processor RTC represents the number of RTC ticks made since the system booted. It should consistently be 64e6, and can be used to properly derive Processor Utility Rate", + []string{"core"}, + nil, + ) + c.ProcessorUtility = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_utility_total"), + "Processor Utility represents is the amount of time the core spends executing instructions", + []string{"core"}, + nil, + ) + c.ProcessorPrivUtility = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_privileged_utility_total"), + "Processor Privilieged Utility represents is the amount of time the core has spent executing instructions inside the kernel", + []string{"core"}, + nil, + ) + + return nil +} + +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if winversion.WindowsVersionFloat > 6.05 { + return c.CollectFull(ctx, ch) } - return &cpuCollectorFull{ - logger: logger, - CStateSecondsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cstate_seconds_total"), - "Time spent in low-power idle state", - []string{"core", "state"}, - nil, - ), - TimeTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "time_total"), - "Time that processor spent in different modes (dpc, idle, interrupt, privileged, user)", - []string{"core", "mode"}, - nil, - ), - InterruptsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "interrupts_total"), - "Total number of received and serviced hardware interrupts", - []string{"core"}, - nil, - ), - DPCsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dpcs_total"), - "Total number of received and serviced deferred procedure calls (DPCs)", - []string{"core"}, - nil, - ), - ClockInterruptsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clock_interrupts_total"), - "Total number of received and serviced clock tick interrupts", - []string{"core"}, - nil, - ), - IdleBreakEventsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "idle_break_events_total"), - "Total number of time processor was woken from idle", - []string{"core"}, - nil, - ), - ParkingStatus: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "parking_status"), - "Parking Status represents whether a processor is parked or not", - []string{"core"}, - nil, - ), - ProcessorFrequencyMHz: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "core_frequency_mhz"), - "Core frequency in megahertz", - []string{"core"}, - nil, - ), - ProcessorPerformance: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_performance_total"), - "Processor Performance is the average performance of the processor while it is executing instructions, as a percentage of the nominal performance of the processor. On some processors, Processor Performance may exceed 100%", - []string{"core"}, - nil, - ), - ProcessorMPerf: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_mperf_total"), - "Processor MPerf is the number of TSC ticks incremented while executing instructions", - []string{"core"}, - nil, - ), - ProcessorRTC: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_rtc_total"), - "Processor RTC represents the number of RTC ticks made since the system booted. It should consistently be 64e6, and can be used to properly derive Processor Utility Rate", - []string{"core"}, - nil, - ), - ProcessorUtility: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_utility_total"), - "Processor Utility represents is the amount of time the core spends executing instructions", - []string{"core"}, - nil, - ), - ProcessorPrivUtility: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processor_privileged_utility_total"), - "Processor Privilieged Utility represents is the amount of time the core has spent executing instructions inside the kernel", - []string{"core"}, - nil, - ), - }, nil + return c.CollectBasic(ctx, ch) } type perflibProcessor struct { @@ -181,9 +209,9 @@ type perflibProcessor struct { PercentUserTime float64 `perflib:"% User Time"` } -func (c *cpuCollectorBasic) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) CollectBasic(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { data := make([]perflibProcessor, 0) - err := unmarshalObject(ctx.perfObjects["Processor"], &data, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["Processor"], &data, c.logger) if err != nil { return err } @@ -290,9 +318,9 @@ type perflibProcessorInformation struct { UserTimeSeconds float64 `perflib:"% User Time"` } -func (c *cpuCollectorFull) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) CollectFull(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { data := make([]perflibProcessorInformation, 0) - err := unmarshalObject(ctx.perfObjects["Processor Information"], &data, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["Processor Information"], &data, c.logger) if err != nil { return err } diff --git a/pkg/collector/cpu/cpu_test.go b/pkg/collector/cpu/cpu_test.go new file mode 100644 index 0000000000..ac164f7140 --- /dev/null +++ b/pkg/collector/cpu/cpu_test.go @@ -0,0 +1,12 @@ +package cpu_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/cpu" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, cpu.Name, cpu.NewWithFlags) +} diff --git a/collector/cpu_info.go b/pkg/collector/cpu_info/cpu_info.go similarity index 53% rename from collector/cpu_info.go rename to pkg/collector/cpu_info/cpu_info.go index a47556476d..012dd5402d 100644 --- a/collector/cpu_info.go +++ b/pkg/collector/cpu_info/cpu_info.go @@ -1,50 +1,76 @@ //go:build windows -// +build windows -package collector +package cpu_info import ( "errors" "strconv" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// If you are adding additional labels to the metric, make sure that they get added in here as well. See below for explanation. const ( + Name = "cpu_info" + // If you are adding additional labels to the metric, make sure that they get added in here as well. See below for explanation. win32ProcessorQuery = "SELECT Architecture, DeviceId, Description, Family, L2CacheSize, L3CacheSize, Name FROM Win32_Processor" ) -// A CpuInfoCollector is a Prometheus collector for a few WMI metrics in Win32_Processor -type CpuInfoCollector struct { - logger log.Logger +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for a few WMI metrics in Win32_Processor +type collector struct { + logger log.Logger + CpuInfo *prometheus.Desc } -func newCpuInfoCollector(logger log.Logger) (Collector, error) { - const subsystem = "cpu_info" - - return &CpuInfoCollector{ - logger: log.With(logger, "collector", subsystem), - - CpuInfo: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "", subsystem), - "Labeled CPU information as provided provided by Win32_Processor", - []string{ - "architecture", - "device_id", - "description", - "family", - "l2_cache_size", - "l3_cache_size", - "name"}, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.CpuInfo = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, "", Name), + "Labeled CPU information as provided provided by Win32_Processor", + []string{ + "architecture", + "device_id", + "description", + "family", + "l2_cache_size", + "l3_cache_size", + "name", + }, + nil, + ) + + return nil } type win32_Processor struct { @@ -59,7 +85,7 @@ type win32_Processor struct { // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *CpuInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting cpu_info metrics", "desc", desc, "err", err) return err @@ -67,10 +93,10 @@ func (c *CpuInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr return nil } -func (c *CpuInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_Processor // We use a static query here because the provided methods in wmi.go all issue a SELECT *; - // This results in the time consuming LoadPercentage field being read which seems to measure each CPU + // This results in the time-consuming LoadPercentage field being read which seems to measure each CPU // serially over a 1 second interval, so the scrape time is at least 1s * num_sockets if err := wmi.Query(win32ProcessorQuery, &dst); err != nil { return nil, err diff --git a/pkg/collector/cs/cs.go b/pkg/collector/cs/cs.go new file mode 100644 index 0000000000..ba8cc8b27c --- /dev/null +++ b/pkg/collector/cs/cs.go @@ -0,0 +1,132 @@ +//go:build windows + +package cs + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/headers/sysinfoapi" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "cs" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI metrics +type collector struct { + logger log.Logger + + PhysicalMemoryBytes *prometheus.Desc + LogicalProcessors *prometheus.Desc + Hostname *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.LogicalProcessors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "logical_processors"), + "ComputerSystem.NumberOfLogicalProcessors", + nil, + nil, + ) + c.PhysicalMemoryBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "physical_memory_bytes"), + "ComputerSystem.TotalPhysicalMemory", + nil, + nil, + ) + c.Hostname = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hostname"), + "Labeled system hostname information as provided by ComputerSystem.DNSHostName and ComputerSystem.Domain", + []string{ + "hostname", + "domain", + "fqdn", + }, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("msg", "failed collecting cs metrics", "desc", desc, "err", err) + return err + } + return nil +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + // Get systeminfo for number of processors + systemInfo := sysinfoapi.GetSystemInfo() + + // Get memory status for physical memory + mem, err := sysinfoapi.GlobalMemoryStatusEx() + if err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.LogicalProcessors, + prometheus.GaugeValue, + float64(systemInfo.NumberOfProcessors), + ) + + ch <- prometheus.MustNewConstMetric( + c.PhysicalMemoryBytes, + prometheus.GaugeValue, + float64(mem.TotalPhys), + ) + + hostname, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSHostname) + if err != nil { + return nil, err + } + domain, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSDomain) + if err != nil { + return nil, err + } + fqdn, err := sysinfoapi.GetComputerName(sysinfoapi.ComputerNameDNSFullyQualified) + if err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.Hostname, + prometheus.GaugeValue, + 1.0, + hostname, + domain, + fqdn, + ) + + return nil, nil +} diff --git a/pkg/collector/cs/cs_test.go b/pkg/collector/cs/cs_test.go new file mode 100644 index 0000000000..4f34174a77 --- /dev/null +++ b/pkg/collector/cs/cs_test.go @@ -0,0 +1,12 @@ +package cs_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/cs" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, cs.Name, cs.NewWithFlags) +} diff --git a/collector/dfsr.go b/pkg/collector/dfsr/dfsr.go similarity index 55% rename from collector/dfsr.go rename to pkg/collector/dfsr/dfsr.go index 8afb3eb606..c68a5346ee 100644 --- a/collector/dfsr.go +++ b/pkg/collector/dfsr/dfsr.go @@ -1,25 +1,36 @@ //go:build windows -// +build windows -package collector +package dfsr import ( "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" ) const ( + Name = "dfsr" FlagDfsrEnabledCollectors = "collectors.dfsr.sources-enabled" ) -var dfsrEnabledCollectors *string +type Config struct { + DfsrEnabledCollectors string `yaml:"enabled_collectors"` +} + +var ConfigDefaults = Config{ + DfsrEnabledCollectors: "", +} -// DFSRCollector contains the metric and state data of the DFSR collectors. -type DFSRCollector struct { +// collector contains the metric and state data of the DFSR collectors. +type collector struct { logger log.Logger + dfsrEnabledCollectors *string + // Connection source ConnectionBandwidthSavingsUsingDFSReplicationTotal *prometheus.Desc ConnectionBytesReceivedTotal *prometheus.Desc @@ -71,10 +82,10 @@ type DFSRCollector struct { dfsrChildCollectors []dfsrCollectorFunc } -type dfsrCollectorFunc func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error +type dfsrCollectorFunc func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error // Map Perflib sources to DFSR collector names -// E.G. volume -> DFS Replication Service Volumes +// e.g, volume -> DFS Replication Service Volumes func dfsrGetPerfObjectName(collector string) string { prefix := "DFS " suffix := "" @@ -86,329 +97,348 @@ func dfsrGetPerfObjectName(collector string) string { case "volume": suffix = "Replication Service Volumes" } - return (prefix + suffix) + return prefix + suffix } -// newDFSRCollectorFlags is registered -func newDFSRCollectorFlags(app *kingpin.Application) { - dfsrEnabledCollectors = app.Flag(FlagDfsrEnabledCollectors, "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume").String() -} +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } -// newDFSRCollector is registered -func newDFSRCollector(logger log.Logger) (Collector, error) { - const subsystem = "dfsr" - logger = log.With(logger, "collector", subsystem) - _ = level.Info(logger).Log("msg", "dfsr collector is in an experimental state! Metrics for this collector have not been tested.") + c := &collector{ + dfsrEnabledCollectors: &config.DfsrEnabledCollectors, + } + c.SetLogger(logger) + return c +} - enabled := expandEnabledChildCollectors(*dfsrEnabledCollectors) - perfCounters := make([]string, 0, len(enabled)) - for _, c := range enabled { - perfCounters = append(perfCounters, dfsrGetPerfObjectName(c)) +func NewWithFlags(app *kingpin.Application) types.Collector { + return &collector{ + dfsrEnabledCollectors: app. + Flag(FlagDfsrEnabledCollectors, "Comma-seperated list of DFSR Perflib sources to use.").Default("connection,folder,volume"). + Default(ConfigDefaults.DfsrEnabledCollectors).String(), } - addPerfCounterDependencies(subsystem, perfCounters) - - dfsrCollector := DFSRCollector{ - logger: logger, - - // Connection - ConnectionBandwidthSavingsUsingDFSReplicationTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_bandwidth_savings_using_dfs_replication_bytes_total"), - "Total bytes of bandwidth saved using DFS Replication for this connection", - []string{"name"}, - nil, - ), - - ConnectionBytesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_bytes_received_total"), - "Total bytes received for connection", - []string{"name"}, - nil, - ), - - ConnectionCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_compressed_size_of_files_received_bytes_total"), - "Total compressed size of files received on the connection, in bytes", - []string{"name"}, - nil, - ), - - ConnectionFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_received_files_total"), - "Total number of files received for connection", - []string{"name"}, - nil, - ), - - ConnectionRDCBytesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_received_bytes_total"), - "Total bytes received on the connection while replicating files using Remote Differential Compression", - []string{"name"}, - nil, - ), - - ConnectionRDCCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_compressed_size_of_received_files_bytes_total"), - "Total uncompressed size of files received with Remote Differential Compression for connection", - []string{"name"}, - nil, - ), - - ConnectionRDCNumberofFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_received_files_total"), - "Total number of files received using remote differential compression", - []string{"name"}, - nil, - ), - - ConnectionRDCSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_rdc_size_of_received_files_bytes_total"), - "Total size of received Remote Differential Compression files, in bytes.", - []string{"name"}, - nil, - ), - - ConnectionSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_files_received_bytes_total"), - "Total size of files received, in bytes", - []string{"name"}, - nil, - ), - - // Folder - FolderBandwidthSavingsUsingDFSReplicationTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_bandwidth_savings_using_dfs_replication_bytes_total"), - "Total bytes of bandwidth saved using DFS Replication for this folder", - []string{"name"}, - nil, - ), - - FolderCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_compressed_size_of_received_files_bytes_total"), - "Total compressed size of files received on the folder, in bytes", - []string{"name"}, - nil, - ), - - FolderConflictBytesCleanedupTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_cleaned_up_bytes_total"), - "Total size of conflict loser files and folders deleted from the Conflict and Deleted folder, in bytes", - []string{"name"}, - nil, - ), - - FolderConflictBytesGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_generated_bytes_total"), - "Total size of conflict loser files and folders moved to the Conflict and Deleted folder, in bytes", - []string{"name"}, - nil, - ), - - FolderConflictFilesCleanedUpTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_cleaned_up_files_total"), - "Number of conflict loser files deleted from the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderConflictFilesGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_generated_files_total"), - "Number of files and folders moved to the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderConflictFolderCleanupsCompletedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_folder_cleanups_total"), - "Number of deletions of conflict loser files and folders in the Conflict and Deleted", - []string{"name"}, - nil, - ), - - FolderConflictSpaceInUse: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_conflict_space_in_use_bytes"), - "Total size of the conflict loser files and folders currently in the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderDeletedSpaceInUse: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_space_in_use_bytes"), - "Total size (in bytes) of the deleted files and folders currently in the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderDeletedBytesCleanedUpTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_cleaned_up_bytes_total"), - "Total size (in bytes) of replicating deleted files and folders that were cleaned up from the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderDeletedBytesGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_generated_bytes_total"), - "Total size (in bytes) of replicated deleted files and folders that were moved to the Conflict and Deleted folder after they were deleted from a replicated folder on a sending member", - []string{"name"}, - nil, - ), - - FolderDeletedFilesCleanedUpTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_cleaned_up_files_total"), - "Number of files and folders that were cleaned up from the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderDeletedFilesGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_deleted_generated_files_total"), - "Number of deleted files and folders that were moved to the Conflict and Deleted folder", - []string{"name"}, - nil, - ), - - FolderFileInstallsRetriedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_file_installs_retried_total"), - "Total number of file installs that are being retried due to sharing violations or other errors encountered when installing the files", - []string{"name"}, - nil, - ), - - FolderFileInstallsSucceededTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_file_installs_succeeded_total"), - "Total number of files that were successfully received from sending members and installed locally on this server", - []string{"name"}, - nil, - ), - - FolderFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_received_files_total"), - "Total number of files received", - []string{"name"}, - nil, - ), - - FolderRDCBytesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_received_bytes_total"), - "Total number of bytes received in replicating files using Remote Differential Compression", - []string{"name"}, - nil, - ), - - FolderRDCCompressedSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_compressed_size_of_received_files_bytes_total"), - "Total compressed size (in bytes) of the files received with Remote Differential Compression", - []string{"name"}, - nil, - ), - - FolderRDCNumberofFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_received_files_total"), - "Total number of files received with Remote Differential Compression", - []string{"name"}, - nil, - ), - - FolderRDCSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_rdc_files_received_bytes_total"), - "Total uncompressed size (in bytes) of the files received with Remote Differential Compression", - []string{"name"}, - nil, - ), - - FolderSizeOfFilesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_files_received_bytes_total"), - "Total uncompressed size (in bytes) of the files received", - []string{"name"}, - nil, - ), - - FolderStagingSpaceInUse: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_staging_space_in_use_bytes"), - "Total size of files and folders currently in the staging folder.", - []string{"name"}, - nil, - ), - - FolderStagingBytesCleanedUpTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_staging_cleaned_up_bytes_total"), - "Total size (in bytes) of the files and folders that have been cleaned up from the staging folder", - []string{"name"}, - nil, - ), - - FolderStagingBytesGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_staging_generated_bytes_total"), - "Total size (in bytes) of replicated files and folders in the staging folder created by the DFS Replication service since last restart", - []string{"name"}, - nil, - ), - - FolderStagingFilesCleanedUpTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_staging_cleaned_up_files_total"), - "Total number of files and folders that have been cleaned up from the staging folder", - []string{"name"}, - nil, - ), - - FolderStagingFilesGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_staging_generated_files_total"), - "Total number of times replicated files and folders have been staged by the DFS Replication service", - []string{"name"}, - nil, - ), - - FolderUpdatesDroppedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "folder_dropped_updates_total"), - "Total number of redundant file replication update records that have been ignored by the DFS Replication service because they did not change the replicated file or folder", - []string{"name"}, - nil, - ), - - // Volume - VolumeDatabaseCommitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "volume_database_commits_total"), - "Total number of DFSR Volume database commits", - []string{"name"}, - nil, - ), - - VolumeDatabaseLookupsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "volume_database_lookups_total"), - "Total number of DFSR Volume database lookups", - []string{"name"}, - nil, - ), - - VolumeUSNJournalUnreadPercentage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "volume_usn_journal_unread_percentage"), - "Percentage of DFSR Volume USN journal records that are unread", - []string{"name"}, - nil, - ), - - VolumeUSNJournalRecordsAcceptedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "volume_usn_journal_accepted_records_total"), - "Total number of USN journal records accepted", - []string{"name"}, - nil, - ), - - VolumeUSNJournalRecordsReadTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "volume_usn_journal_read_records_total"), - "Total number of DFSR Volume USN journal records read", - []string{"name"}, - nil, - ), +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + // Perflib sources are dynamic, depending on the enabled child collectors + var perflibDependencies []string + for _, source := range utils.ExpandEnabledChildCollectors(*c.dfsrEnabledCollectors) { + perflibDependencies = append(perflibDependencies, dfsrGetPerfObjectName(source)) } - dfsrCollector.dfsrChildCollectors = dfsrCollector.getDFSRChildCollectors(enabled) + return perflibDependencies, nil +} + +func (c *collector) Build() error { + _ = level.Info(c.logger).Log("msg", "dfsr collector is in an experimental state! Metrics for this collector have not been tested.") + + // Connection + c.ConnectionBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_bandwidth_savings_using_dfs_replication_bytes_total"), + "Total bytes of bandwidth saved using DFS Replication for this connection", + []string{"name"}, + nil, + ) + + c.ConnectionBytesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_bytes_received_total"), + "Total bytes received for connection", + []string{"name"}, + nil, + ) + + c.ConnectionCompressedSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_compressed_size_of_files_received_bytes_total"), + "Total compressed size of files received on the connection, in bytes", + []string{"name"}, + nil, + ) + + c.ConnectionFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_received_files_total"), + "Total number of files received for connection", + []string{"name"}, + nil, + ) + + c.ConnectionRDCBytesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_rdc_received_bytes_total"), + "Total bytes received on the connection while replicating files using Remote Differential Compression", + []string{"name"}, + nil, + ) + + c.ConnectionRDCCompressedSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_rdc_compressed_size_of_received_files_bytes_total"), + "Total uncompressed size of files received with Remote Differential Compression for connection", + []string{"name"}, + nil, + ) + + c.ConnectionRDCNumberofFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_rdc_received_files_total"), + "Total number of files received using remote differential compression", + []string{"name"}, + nil, + ) + + c.ConnectionRDCSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_rdc_size_of_received_files_bytes_total"), + "Total size of received Remote Differential Compression files, in bytes.", + []string{"name"}, + nil, + ) + + c.ConnectionSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_files_received_bytes_total"), + "Total size of files received, in bytes", + []string{"name"}, + nil, + ) + + c. // Folder + FolderBandwidthSavingsUsingDFSReplicationTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_bandwidth_savings_using_dfs_replication_bytes_total"), + "Total bytes of bandwidth saved using DFS Replication for this folder", + []string{"name"}, + nil, + ) + + c.FolderCompressedSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_compressed_size_of_received_files_bytes_total"), + "Total compressed size of files received on the folder, in bytes", + []string{"name"}, + nil, + ) + + c.FolderConflictBytesCleanedupTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_conflict_cleaned_up_bytes_total"), + "Total size of conflict loser files and folders deleted from the Conflict and Deleted folder, in bytes", + []string{"name"}, + nil, + ) + + c.FolderConflictBytesGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_conflict_generated_bytes_total"), + "Total size of conflict loser files and folders moved to the Conflict and Deleted folder, in bytes", + []string{"name"}, + nil, + ) + + c.FolderConflictFilesCleanedUpTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_conflict_cleaned_up_files_total"), + "Number of conflict loser files deleted from the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderConflictFilesGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_conflict_generated_files_total"), + "Number of files and folders moved to the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderConflictFolderCleanupsCompletedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_conflict_folder_cleanups_total"), + "Number of deletions of conflict loser files and folders in the Conflict and Deleted", + []string{"name"}, + nil, + ) + + c.FolderConflictSpaceInUse = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_conflict_space_in_use_bytes"), + "Total size of the conflict loser files and folders currently in the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderDeletedSpaceInUse = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_deleted_space_in_use_bytes"), + "Total size (in bytes) of the deleted files and folders currently in the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderDeletedBytesCleanedUpTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_deleted_cleaned_up_bytes_total"), + "Total size (in bytes) of replicating deleted files and folders that were cleaned up from the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderDeletedBytesGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_deleted_generated_bytes_total"), + "Total size (in bytes) of replicated deleted files and folders that were moved to the Conflict and Deleted folder after they were deleted from a replicated folder on a sending member", + []string{"name"}, + nil, + ) + + c.FolderDeletedFilesCleanedUpTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_deleted_cleaned_up_files_total"), + "Number of files and folders that were cleaned up from the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderDeletedFilesGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_deleted_generated_files_total"), + "Number of deleted files and folders that were moved to the Conflict and Deleted folder", + []string{"name"}, + nil, + ) + + c.FolderFileInstallsRetriedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_file_installs_retried_total"), + "Total number of file installs that are being retried due to sharing violations or other errors encountered when installing the files", + []string{"name"}, + nil, + ) + + c.FolderFileInstallsSucceededTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_file_installs_succeeded_total"), + "Total number of files that were successfully received from sending members and installed locally on this server", + []string{"name"}, + nil, + ) + + c.FolderFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_received_files_total"), + "Total number of files received", + []string{"name"}, + nil, + ) + + c.FolderRDCBytesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_rdc_received_bytes_total"), + "Total number of bytes received in replicating files using Remote Differential Compression", + []string{"name"}, + nil, + ) + + c.FolderRDCCompressedSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_rdc_compressed_size_of_received_files_bytes_total"), + "Total compressed size (in bytes) of the files received with Remote Differential Compression", + []string{"name"}, + nil, + ) + + c.FolderRDCNumberofFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_rdc_received_files_total"), + "Total number of files received with Remote Differential Compression", + []string{"name"}, + nil, + ) + + c.FolderRDCSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_rdc_files_received_bytes_total"), + "Total uncompressed size (in bytes) of the files received with Remote Differential Compression", + []string{"name"}, + nil, + ) + + c.FolderSizeOfFilesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_files_received_bytes_total"), + "Total uncompressed size (in bytes) of the files received", + []string{"name"}, + nil, + ) + + c.FolderStagingSpaceInUse = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_staging_space_in_use_bytes"), + "Total size of files and folders currently in the staging folder.", + []string{"name"}, + nil, + ) + + c.FolderStagingBytesCleanedUpTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_staging_cleaned_up_bytes_total"), + "Total size (in bytes) of the files and folders that have been cleaned up from the staging folder", + []string{"name"}, + nil, + ) + + c.FolderStagingBytesGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_staging_generated_bytes_total"), + "Total size (in bytes) of replicated files and folders in the staging folder created by the DFS Replication service since last restart", + []string{"name"}, + nil, + ) + + c.FolderStagingFilesCleanedUpTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_staging_cleaned_up_files_total"), + "Total number of files and folders that have been cleaned up from the staging folder", + []string{"name"}, + nil, + ) + + c.FolderStagingFilesGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_staging_generated_files_total"), + "Total number of times replicated files and folders have been staged by the DFS Replication service", + []string{"name"}, + nil, + ) + + c.FolderUpdatesDroppedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "folder_dropped_updates_total"), + "Total number of redundant file replication update records that have been ignored by the DFS Replication service because they did not change the replicated file or folder", + []string{"name"}, + nil, + ) + + c. // Volume + VolumeDatabaseCommitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "volume_database_commits_total"), + "Total number of DFSR Volume database commits", + []string{"name"}, + nil, + ) + + c.VolumeDatabaseLookupsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "volume_database_lookups_total"), + "Total number of DFSR Volume database lookups", + []string{"name"}, + nil, + ) + + c.VolumeUSNJournalUnreadPercentage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "volume_usn_journal_unread_percentage"), + "Percentage of DFSR Volume USN journal records that are unread", + []string{"name"}, + nil, + ) + + c.VolumeUSNJournalRecordsAcceptedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "volume_usn_journal_accepted_records_total"), + "Total number of USN journal records accepted", + []string{"name"}, + nil, + ) + + c.VolumeUSNJournalRecordsReadTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "volume_usn_journal_read_records_total"), + "Total number of DFSR Volume USN journal records read", + []string{"name"}, + nil, + ) + + c.dfsrChildCollectors = c.getDFSRChildCollectors(utils.ExpandEnabledChildCollectors(*c.dfsrEnabledCollectors)) - return &dfsrCollector, nil + return nil } // Maps enabled child collectors names to their relevant collection function, -// for use in DFSRCollector.Collect() -func (c *DFSRCollector) getDFSRChildCollectors(enabledCollectors []string) []dfsrCollectorFunc { +// for use in collector.Collect() +func (c *collector) getDFSRChildCollectors(enabledCollectors []string) []dfsrCollectorFunc { var dfsrCollectors []dfsrCollectorFunc for _, collector := range enabledCollectors { switch collector { @@ -426,7 +456,7 @@ func (c *DFSRCollector) getDFSRChildCollectors(enabledCollectors []string) []dfs // Collect implements the Collector interface. // Sends metric values for each metric to the provided prometheus Metric channel. -func (c *DFSRCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { for _, fn := range c.dfsrChildCollectors { err := fn(ctx, ch) if err != nil { @@ -436,7 +466,7 @@ func (c *DFSRCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) return nil } -// Perflib: "DFS Replication Service Connections" +// PerflibDFSRConnection Perflib: "DFS Replication Service Connections" type PerflibDFSRConnection struct { Name string @@ -451,9 +481,9 @@ type PerflibDFSRConnection struct { SizeOfFilesReceivedTotal float64 `perflib:"Size of Files Received"` } -func (c *DFSRCollector) collectConnection(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectConnection(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var dst []PerflibDFSRConnection - if err := unmarshalObject(ctx.perfObjects["DFS Replication Connections"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["DFS Replication Connections"], &dst, c.logger); err != nil { return err } @@ -525,7 +555,7 @@ func (c *DFSRCollector) collectConnection(ctx *ScrapeContext, ch chan<- promethe return nil } -// Perflib: "DFS Replicated Folder" +// PerflibDFSRFolder Perflib: "DFS Replicated Folder" type PerflibDFSRFolder struct { Name string @@ -558,9 +588,9 @@ type PerflibDFSRFolder struct { UpdatesDroppedTotal float64 `perflib:"Updates Dropped"` } -func (c *DFSRCollector) collectFolder(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectFolder(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var dst []PerflibDFSRFolder - if err := unmarshalObject(ctx.perfObjects["DFS Replicated Folders"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["DFS Replicated Folders"], &dst, c.logger); err != nil { return err } @@ -757,7 +787,7 @@ func (c *DFSRCollector) collectFolder(ctx *ScrapeContext, ch chan<- prometheus.M return nil } -// Perflib: "DFS Replication Service Volumes" +// PerflibDFSRVolume Perflib: "DFS Replication Service Volumes" type PerflibDFSRVolume struct { Name string @@ -768,9 +798,9 @@ type PerflibDFSRVolume struct { USNJournalUnreadPercentage float64 `perflib:"USN Journal Records Unread Percentage"` } -func (c *DFSRCollector) collectVolume(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectVolume(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var dst []PerflibDFSRVolume - if err := unmarshalObject(ctx.perfObjects["DFS Replication Service Volumes"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["DFS Replication Service Volumes"], &dst, c.logger); err != nil { return err } diff --git a/pkg/collector/dfsr/dfsr_test.go b/pkg/collector/dfsr/dfsr_test.go new file mode 100644 index 0000000000..9551e6fa12 --- /dev/null +++ b/pkg/collector/dfsr/dfsr_test.go @@ -0,0 +1,12 @@ +package dfsr_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/dfsr" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, dfsr.Name, dfsr.NewWithFlags) +} diff --git a/collector/dhcp.go b/pkg/collector/dhcp/dhcp.go similarity index 50% rename from collector/dhcp.go rename to pkg/collector/dhcp/dhcp.go index 070a284cd6..ddb13572ed 100644 --- a/collector/dhcp.go +++ b/pkg/collector/dhcp/dhcp.go @@ -1,15 +1,23 @@ //go:build windows -// +build windows -package collector +package dhcp import ( + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) -// A DhcpCollector is a Prometheus collector perflib DHCP metrics -type DhcpCollector struct { +const Name = "dhcp" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector perflib DHCP metrics +type collector struct { logger log.Logger PacketsReceivedTotal *prometheus.Desc @@ -39,163 +47,180 @@ type DhcpCollector struct { FailoverBndupdDropped *prometheus.Desc } -func newDhcpCollector(logger log.Logger) (Collector, error) { - const subsystem = "dhcp" - - return &DhcpCollector{ - logger: log.With(logger, "collector", subsystem), - - PacketsReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"), - "Total number of packets received by the DHCP server (PacketsReceivedTotal)", - nil, - nil, - ), - DuplicatesDroppedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "duplicates_dropped_total"), - "Total number of duplicate packets received by the DHCP server (DuplicatesDroppedTotal)", - nil, - nil, - ), - PacketsExpiredTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_expired_total"), - "Total number of packets expired in the DHCP server message queue (PacketsExpiredTotal)", - nil, - nil, - ), - ActiveQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "active_queue_length"), - "Number of packets in the processing queue of the DHCP server (ActiveQueueLength)", - nil, - nil, - ), - ConflictCheckQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "conflict_check_queue_length"), - "Number of packets in the DHCP server queue waiting on conflict detection (ping). (ConflictCheckQueueLength)", - nil, - nil, - ), - DiscoversTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "discovers_total"), - "Total DHCP Discovers received by the DHCP server (DiscoversTotal)", - nil, - nil, - ), - OffersTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "offers_total"), - "Total DHCP Offers sent by the DHCP server (OffersTotal)", - nil, - nil, - ), - RequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "requests_total"), - "Total DHCP Requests received by the DHCP server (RequestsTotal)", - nil, - nil, - ), - InformsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "informs_total"), - "Total DHCP Informs received by the DHCP server (InformsTotal)", - nil, - nil, - ), - AcksTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "acks_total"), - "Total DHCP Acks sent by the DHCP server (AcksTotal)", - nil, - nil, - ), - NacksTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "nacks_total"), - "Total DHCP Nacks sent by the DHCP server (NacksTotal)", - nil, - nil, - ), - DeclinesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "declines_total"), - "Total DHCP Declines received by the DHCP server (DeclinesTotal)", - nil, - nil, - ), - ReleasesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "releases_total"), - "Total DHCP Releases received by the DHCP server (ReleasesTotal)", - nil, - nil, - ), - OfferQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "offer_queue_length"), - "Number of packets in the offer queue of the DHCP server (OfferQueueLength)", - nil, - nil, - ), - DeniedDueToMatch: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_match_total"), - "Total number of DHCP requests denied, based on matches from the Deny list (DeniedDueToMatch)", - nil, - nil, - ), - DeniedDueToNonMatch: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "denied_due_to_nonmatch_total"), - "Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)", - nil, - nil, - ), - FailoverBndupdSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_sent_total"), - "Number of DHCP failover Binding Update messages sent (FailoverBndupdSentTotal)", - nil, - nil, - ), - FailoverBndupdReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_received_total"), - "Number of DHCP failover Binding Update messages received (FailoverBndupdReceivedTotal)", - nil, - nil, - ), - FailoverBndackSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_bndack_sent_total"), - "Number of DHCP failover Binding Ack messages sent (FailoverBndackSentTotal)", - nil, - nil, - ), - FailoverBndackReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_bndack_received_total"), - "Number of DHCP failover Binding Ack messages received (FailoverBndackReceivedTotal)", - nil, - nil, - ), - FailoverBndupdPendingOutboundQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_pending_in_outbound_queue"), - "Number of pending outbound DHCP failover Binding Update messages (FailoverBndupdPendingOutboundQueue)", - nil, - nil, - ), - FailoverTransitionsCommunicationinterruptedState: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_transitions_communicationinterrupted_state_total"), - "Total number of transitions into COMMUNICATION INTERRUPTED state (FailoverTransitionsCommunicationinterruptedState)", - nil, - nil, - ), - FailoverTransitionsPartnerdownState: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_transitions_partnerdown_state_total"), - "Total number of transitions into PARTNER DOWN state (FailoverTransitionsPartnerdownState)", - nil, - nil, - ), - FailoverTransitionsRecoverState: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_transitions_recover_total"), - "Total number of transitions into RECOVER state (FailoverTransitionsRecoverState)", - nil, - nil, - ), - FailoverBndupdDropped: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "failover_bndupd_dropped_total"), - "Total number of DHCP faileover Binding Updates dropped (FailoverBndupdDropped)", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.PacketsReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"), + "Total number of packets received by the DHCP server (PacketsReceivedTotal)", + nil, + nil, + ) + c.DuplicatesDroppedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "duplicates_dropped_total"), + "Total number of duplicate packets received by the DHCP server (DuplicatesDroppedTotal)", + nil, + nil, + ) + c.PacketsExpiredTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_expired_total"), + "Total number of packets expired in the DHCP server message queue (PacketsExpiredTotal)", + nil, + nil, + ) + c.ActiveQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "active_queue_length"), + "Number of packets in the processing queue of the DHCP server (ActiveQueueLength)", + nil, + nil, + ) + c.ConflictCheckQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "conflict_check_queue_length"), + "Number of packets in the DHCP server queue waiting on conflict detection (ping). (ConflictCheckQueueLength)", + nil, + nil, + ) + c.DiscoversTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "discovers_total"), + "Total DHCP Discovers received by the DHCP server (DiscoversTotal)", + nil, + nil, + ) + c.OffersTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "offers_total"), + "Total DHCP Offers sent by the DHCP server (OffersTotal)", + nil, + nil, + ) + c.RequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "requests_total"), + "Total DHCP Requests received by the DHCP server (RequestsTotal)", + nil, + nil, + ) + c.InformsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "informs_total"), + "Total DHCP Informs received by the DHCP server (InformsTotal)", + nil, + nil, + ) + c.AcksTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "acks_total"), + "Total DHCP Acks sent by the DHCP server (AcksTotal)", + nil, + nil, + ) + c.NacksTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "nacks_total"), + "Total DHCP Nacks sent by the DHCP server (NacksTotal)", + nil, + nil, + ) + c.DeclinesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "declines_total"), + "Total DHCP Declines received by the DHCP server (DeclinesTotal)", + nil, + nil, + ) + c.ReleasesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "releases_total"), + "Total DHCP Releases received by the DHCP server (ReleasesTotal)", + nil, + nil, + ) + c.OfferQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "offer_queue_length"), + "Number of packets in the offer queue of the DHCP server (OfferQueueLength)", + nil, + nil, + ) + c.DeniedDueToMatch = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "denied_due_to_match_total"), + "Total number of DHCP requests denied, based on matches from the Deny list (DeniedDueToMatch)", + nil, + nil, + ) + c.DeniedDueToNonMatch = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "denied_due_to_nonmatch_total"), + "Total number of DHCP requests denied, based on non-matches from the Allow list (DeniedDueToNonMatch)", + nil, + nil, + ) + c.FailoverBndupdSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_sent_total"), + "Number of DHCP fail over Binding Update messages sent (FailoverBndupdSentTotal)", + nil, + nil, + ) + c.FailoverBndupdReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_received_total"), + "Number of DHCP fail over Binding Update messages received (FailoverBndupdReceivedTotal)", + nil, + nil, + ) + c.FailoverBndackSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_bndack_sent_total"), + "Number of DHCP fail over Binding Ack messages sent (FailoverBndackSentTotal)", + nil, + nil, + ) + c.FailoverBndackReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_bndack_received_total"), + "Number of DHCP fail over Binding Ack messages received (FailoverBndackReceivedTotal)", + nil, + nil, + ) + c.FailoverBndupdPendingOutboundQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_pending_in_outbound_queue"), + "Number of pending outbound DHCP fail over Binding Update messages (FailoverBndupdPendingOutboundQueue)", + nil, + nil, + ) + c.FailoverTransitionsCommunicationinterruptedState = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_communicationinterrupted_state_total"), + "Total number of transitions into COMMUNICATION INTERRUPTED state (FailoverTransitionsCommunicationinterruptedState)", + nil, + nil, + ) + c.FailoverTransitionsPartnerdownState = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_partnerdown_state_total"), + "Total number of transitions into PARTNER DOWN state (FailoverTransitionsPartnerdownState)", + nil, + nil, + ) + c.FailoverTransitionsRecoverState = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_transitions_recover_total"), + "Total number of transitions into RECOVER state (FailoverTransitionsRecoverState)", + nil, + nil, + ) + c.FailoverBndupdDropped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_bndupd_dropped_total"), + "Total number of DHCP fail over Binding Updates dropped (FailoverBndupdDropped)", + nil, + nil, + ) + return nil } // represents perflib metrics from the DHCP Server class. @@ -229,160 +254,160 @@ type dhcpPerf struct { FailoverBndupdDropped float64 `perflib:"Failover: BndUpd Dropped."` } -func (c *DhcpCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - var perflib []dhcpPerf - if err := unmarshalObject(ctx.perfObjects["DHCP Server"], &perflib, c.logger); err != nil { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + var dhcpPerfs []dhcpPerf + if err := perflib.UnmarshalObject(ctx.PerfObjects["DHCP Server"], &dhcpPerfs, c.logger); err != nil { return err } ch <- prometheus.MustNewConstMetric( c.PacketsReceivedTotal, prometheus.CounterValue, - perflib[0].PacketsReceivedTotal, + dhcpPerfs[0].PacketsReceivedTotal, ) ch <- prometheus.MustNewConstMetric( c.DuplicatesDroppedTotal, prometheus.CounterValue, - perflib[0].DuplicatesDroppedTotal, + dhcpPerfs[0].DuplicatesDroppedTotal, ) ch <- prometheus.MustNewConstMetric( c.PacketsExpiredTotal, prometheus.CounterValue, - perflib[0].PacketsExpiredTotal, + dhcpPerfs[0].PacketsExpiredTotal, ) ch <- prometheus.MustNewConstMetric( c.ActiveQueueLength, prometheus.GaugeValue, - perflib[0].ActiveQueueLength, + dhcpPerfs[0].ActiveQueueLength, ) ch <- prometheus.MustNewConstMetric( c.ConflictCheckQueueLength, prometheus.GaugeValue, - perflib[0].ConflictCheckQueueLength, + dhcpPerfs[0].ConflictCheckQueueLength, ) ch <- prometheus.MustNewConstMetric( c.DiscoversTotal, prometheus.CounterValue, - perflib[0].DiscoversTotal, + dhcpPerfs[0].DiscoversTotal, ) ch <- prometheus.MustNewConstMetric( c.OffersTotal, prometheus.CounterValue, - perflib[0].OffersTotal, + dhcpPerfs[0].OffersTotal, ) ch <- prometheus.MustNewConstMetric( c.RequestsTotal, prometheus.CounterValue, - perflib[0].RequestsTotal, + dhcpPerfs[0].RequestsTotal, ) ch <- prometheus.MustNewConstMetric( c.InformsTotal, prometheus.CounterValue, - perflib[0].InformsTotal, + dhcpPerfs[0].InformsTotal, ) ch <- prometheus.MustNewConstMetric( c.AcksTotal, prometheus.CounterValue, - perflib[0].AcksTotal, + dhcpPerfs[0].AcksTotal, ) ch <- prometheus.MustNewConstMetric( c.NacksTotal, prometheus.CounterValue, - perflib[0].NacksTotal, + dhcpPerfs[0].NacksTotal, ) ch <- prometheus.MustNewConstMetric( c.DeclinesTotal, prometheus.CounterValue, - perflib[0].DeclinesTotal, + dhcpPerfs[0].DeclinesTotal, ) ch <- prometheus.MustNewConstMetric( c.ReleasesTotal, prometheus.CounterValue, - perflib[0].ReleasesTotal, + dhcpPerfs[0].ReleasesTotal, ) ch <- prometheus.MustNewConstMetric( c.OfferQueueLength, prometheus.GaugeValue, - perflib[0].OfferQueueLength, + dhcpPerfs[0].OfferQueueLength, ) ch <- prometheus.MustNewConstMetric( c.DeniedDueToMatch, prometheus.CounterValue, - perflib[0].DeniedDueToMatch, + dhcpPerfs[0].DeniedDueToMatch, ) ch <- prometheus.MustNewConstMetric( c.DeniedDueToNonMatch, prometheus.CounterValue, - perflib[0].DeniedDueToNonMatch, + dhcpPerfs[0].DeniedDueToNonMatch, ) ch <- prometheus.MustNewConstMetric( c.FailoverBndupdSentTotal, prometheus.CounterValue, - perflib[0].FailoverBndupdSentTotal, + dhcpPerfs[0].FailoverBndupdSentTotal, ) ch <- prometheus.MustNewConstMetric( c.FailoverBndupdReceivedTotal, prometheus.CounterValue, - perflib[0].FailoverBndupdReceivedTotal, + dhcpPerfs[0].FailoverBndupdReceivedTotal, ) ch <- prometheus.MustNewConstMetric( c.FailoverBndackSentTotal, prometheus.CounterValue, - perflib[0].FailoverBndackSentTotal, + dhcpPerfs[0].FailoverBndackSentTotal, ) ch <- prometheus.MustNewConstMetric( c.FailoverBndackReceivedTotal, prometheus.CounterValue, - perflib[0].FailoverBndackReceivedTotal, + dhcpPerfs[0].FailoverBndackReceivedTotal, ) ch <- prometheus.MustNewConstMetric( c.FailoverBndupdPendingOutboundQueue, prometheus.GaugeValue, - perflib[0].FailoverBndupdPendingOutboundQueue, + dhcpPerfs[0].FailoverBndupdPendingOutboundQueue, ) ch <- prometheus.MustNewConstMetric( c.FailoverTransitionsCommunicationinterruptedState, prometheus.CounterValue, - perflib[0].FailoverTransitionsCommunicationinterruptedState, + dhcpPerfs[0].FailoverTransitionsCommunicationinterruptedState, ) ch <- prometheus.MustNewConstMetric( c.FailoverTransitionsPartnerdownState, prometheus.CounterValue, - perflib[0].FailoverTransitionsPartnerdownState, + dhcpPerfs[0].FailoverTransitionsPartnerdownState, ) ch <- prometheus.MustNewConstMetric( c.FailoverTransitionsRecoverState, prometheus.CounterValue, - perflib[0].FailoverTransitionsRecoverState, + dhcpPerfs[0].FailoverTransitionsRecoverState, ) ch <- prometheus.MustNewConstMetric( c.FailoverBndupdDropped, prometheus.CounterValue, - perflib[0].FailoverBndupdDropped, + dhcpPerfs[0].FailoverBndupdDropped, ) return nil diff --git a/pkg/collector/dhcp/dhcp_test.go b/pkg/collector/dhcp/dhcp_test.go new file mode 100644 index 0000000000..b7b8dd00af --- /dev/null +++ b/pkg/collector/dhcp/dhcp_test.go @@ -0,0 +1,12 @@ +package dhcp_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/dhcp" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, dhcp.Name, dhcp.NewWithFlags) +} diff --git a/collector/diskdrive.go b/pkg/collector/diskdrive/diskdrive.go similarity index 60% rename from collector/diskdrive.go rename to pkg/collector/diskdrive/diskdrive.go index 40e38fc674..fcf3f43a52 100644 --- a/collector/diskdrive.go +++ b/pkg/collector/diskdrive/diskdrive.go @@ -1,24 +1,30 @@ //go:build windows -// +build windows -package collector +package diskdrive import ( "errors" "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) const ( + Name = "diskdrive" win32DiskQuery = "SELECT DeviceID, Model, Caption, Name, Partitions, Size, Status, Availability FROM WIN32_DiskDrive" ) -// A DiskDriveInfoCollector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive -type DiskDriveInfoCollector struct { +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for a few WMI metrics in Win32_DiskDrive +type collector struct { logger log.Logger DiskInfo *prometheus.Desc @@ -28,54 +34,66 @@ type DiskDriveInfoCollector struct { Availability *prometheus.Desc } -func newDiskDriveInfoCollector(logger log.Logger) (Collector, error) { - const subsystem = "diskdrive" - - return &DiskDriveInfoCollector{ - logger: log.With(logger, "collector", subsystem), - - DiskInfo: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "info"), - "General drive information", - []string{ - "device_id", - "model", - "caption", - "name", - }, - nil, - ), - - Status: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "status"), - "Status of the drive", - []string{ - "name", "status"}, - nil, - ), - - Size: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "size"), - "Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector.", - []string{"name"}, - nil, - ), - - Partitions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "partitions"), - "Number of partitions", - []string{"name"}, - nil, - ), - - Availability: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availability"), - "Availability Status", - []string{ - "name", "availability"}, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.DiskInfo = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "info"), + "General drive information", + []string{ + "device_id", + "model", + "caption", + "name", + }, + nil, + ) + c.Status = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "status"), + "Status of the drive", + []string{"name", "status"}, + nil, + ) + c.Size = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "size"), + "Size of the disk drive. It is calculated by multiplying the total number of cylinders, tracks in each cylinder, sectors in each track, and bytes in each sector.", + []string{"name"}, + nil, + ) + c.Partitions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "partitions"), + "Number of partitions", + []string{"name"}, + nil, + ) + c.Availability = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availability"), + "Availability Status", + []string{"name", "availability"}, + nil, + ) + + return nil } type Win32_DiskDrive struct { @@ -106,7 +124,6 @@ var ( } availMap = map[int]string{ - 1: "Other", 2: "Unknown", 3: "Running / Full Power", @@ -132,7 +149,7 @@ var ( ) // Collect sends the metric values for each metric to the provided prometheus Metric channel. -func (c *DiskDriveInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting disk_drive_info metrics", "desc", desc, "err", err) return err @@ -140,7 +157,7 @@ func (c *DiskDriveInfoCollector) Collect(ctx *ScrapeContext, ch chan<- prometheu return nil } -func (c *DiskDriveInfoCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_DiskDrive if err := wmi.Query(win32DiskQuery, &dst); err != nil { diff --git a/pkg/collector/diskdrive/diskdrive_test.go b/pkg/collector/diskdrive/diskdrive_test.go new file mode 100644 index 0000000000..8eae26974f --- /dev/null +++ b/pkg/collector/diskdrive/diskdrive_test.go @@ -0,0 +1,12 @@ +package diskdrive_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, diskdrive.Name, diskdrive.NewWithFlags) +} diff --git a/collector/dns.go b/pkg/collector/dns/dns.go similarity index 63% rename from collector/dns.go rename to pkg/collector/dns/dns.go index a5b8d8defb..ca37ec7ea4 100644 --- a/collector/dns.go +++ b/pkg/collector/dns/dns.go @@ -1,19 +1,26 @@ //go:build windows -// +build windows -package collector +package dns import ( "errors" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A DNSCollector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics -type DNSCollector struct { +const Name = "dns" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_DNS_DNS metrics +type collector struct { logger log.Logger ZoneTransferRequestsReceived *prometheus.Desc @@ -40,150 +47,167 @@ type DNSCollector struct { UnmatchedResponsesReceived *prometheus.Desc } -// newDNSCollector ... -func newDNSCollector(logger log.Logger) (Collector, error) { - const subsystem = "dns" - return &DNSCollector{ - logger: log.With(logger, "collector", subsystem), - - ZoneTransferRequestsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_received_total"), - "Number of zone transfer requests (AXFR/IXFR) received by the master DNS server", - []string{"qtype"}, - nil, - ), - ZoneTransferRequestsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_requests_sent_total"), - "Number of zone transfer requests (AXFR/IXFR) sent by the secondary DNS server", - []string{"qtype"}, - nil, - ), - ZoneTransferResponsesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_response_received_total"), - "Number of zone transfer responses (AXFR/IXFR) received by the secondary DNS server", - []string{"qtype"}, - nil, - ), - ZoneTransferSuccessReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_success_received_total"), - "Number of successful zone transfers (AXFR/IXFR) received by the secondary DNS server", - []string{"qtype", "protocol"}, - nil, - ), - ZoneTransferSuccessSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_success_sent_total"), - "Number of successful zone transfers (AXFR/IXFR) of the master DNS server", - []string{"qtype"}, - nil, - ), - ZoneTransferFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "zone_transfer_failures_total"), - "Number of failed zone transfers of the master DNS server", - nil, - nil, - ), - MemoryUsedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memory_used_bytes"), - "Current memory used by DNS server", - []string{"area"}, - nil, - ), - DynamicUpdatesQueued: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_queued"), - "Number of dynamic updates queued by the DNS server", - nil, - nil, - ), - DynamicUpdatesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_received_total"), - "Number of secure update requests received by the DNS server", - []string{"operation"}, - nil, - ), - DynamicUpdatesFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dynamic_updates_failures_total"), - "Number of dynamic updates which timed out or were rejected by the DNS server", - []string{"reason"}, - nil, - ), - NotifyReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "notify_received_total"), - "Number of notifies received by the secondary DNS server", - nil, - nil, - ), - NotifySent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "notify_sent_total"), - "Number of notifies sent by the master DNS server", - nil, - nil, - ), - SecureUpdateFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "secure_update_failures_total"), - "Number of secure updates that failed on the DNS server", - nil, - nil, - ), - SecureUpdateReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "secure_update_received_total"), - "Number of secure update requests received by the DNS server", - nil, - nil, - ), - Queries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "queries_total"), - "Number of queries received by DNS server", - []string{"protocol"}, - nil, - ), - Responses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "responses_total"), - "Number of responses sent by DNS server", - []string{"protocol"}, - nil, - ), - RecursiveQueries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "recursive_queries_total"), - "Number of recursive queries received by DNS server", - nil, - nil, - ), - RecursiveQueryFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "recursive_query_failures_total"), - "Number of recursive query failures", - nil, - nil, - ), - RecursiveQuerySendTimeouts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "recursive_query_send_timeouts_total"), - "Number of recursive query sending timeouts", - nil, - nil, - ), - WinsQueries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "wins_queries_total"), - "Number of WINS lookup requests received by the server", - []string{"direction"}, - nil, - ), - WinsResponses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "wins_responses_total"), - "Number of WINS lookup responses sent by the server", - []string{"direction"}, - nil, - ), - UnmatchedResponsesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "unmatched_responses_total"), - "Number of response packets received by the DNS server that do not match any outstanding remote query", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.ZoneTransferRequestsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_received_total"), + "Number of zone transfer requests (AXFR/IXFR) received by the master DNS server", + []string{"qtype"}, + nil, + ) + c.ZoneTransferRequestsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_requests_sent_total"), + "Number of zone transfer requests (AXFR/IXFR) sent by the secondary DNS server", + []string{"qtype"}, + nil, + ) + c.ZoneTransferResponsesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_response_received_total"), + "Number of zone transfer responses (AXFR/IXFR) received by the secondary DNS server", + []string{"qtype"}, + nil, + ) + c.ZoneTransferSuccessReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_success_received_total"), + "Number of successful zone transfers (AXFR/IXFR) received by the secondary DNS server", + []string{"qtype", "protocol"}, + nil, + ) + c.ZoneTransferSuccessSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_success_sent_total"), + "Number of successful zone transfers (AXFR/IXFR) of the master DNS server", + []string{"qtype"}, + nil, + ) + c.ZoneTransferFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "zone_transfer_failures_total"), + "Number of failed zone transfers of the master DNS server", + nil, + nil, + ) + c.MemoryUsedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memory_used_bytes"), + "Current memory used by DNS server", + []string{"area"}, + nil, + ) + c.DynamicUpdatesQueued = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_queued"), + "Number of dynamic updates queued by the DNS server", + nil, + nil, + ) + c.DynamicUpdatesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_received_total"), + "Number of secure update requests received by the DNS server", + []string{"operation"}, + nil, + ) + c.DynamicUpdatesFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_updates_failures_total"), + "Number of dynamic updates which timed out or were rejected by the DNS server", + []string{"reason"}, + nil, + ) + c.NotifyReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "notify_received_total"), + "Number of notifies received by the secondary DNS server", + nil, + nil, + ) + c.NotifySent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "notify_sent_total"), + "Number of notifies sent by the master DNS server", + nil, + nil, + ) + c.SecureUpdateFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "secure_update_failures_total"), + "Number of secure updates that failed on the DNS server", + nil, + nil, + ) + c.SecureUpdateReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "secure_update_received_total"), + "Number of secure update requests received by the DNS server", + nil, + nil, + ) + c.Queries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "queries_total"), + "Number of queries received by DNS server", + []string{"protocol"}, + nil, + ) + c.Responses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "responses_total"), + "Number of responses sent by DNS server", + []string{"protocol"}, + nil, + ) + c.RecursiveQueries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "recursive_queries_total"), + "Number of recursive queries received by DNS server", + nil, + nil, + ) + c.RecursiveQueryFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "recursive_query_failures_total"), + "Number of recursive query failures", + nil, + nil, + ) + c.RecursiveQuerySendTimeouts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "recursive_query_send_timeouts_total"), + "Number of recursive query sending timeouts", + nil, + nil, + ) + c.WinsQueries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "wins_queries_total"), + "Number of WINS lookup requests received by the server", + []string{"direction"}, + nil, + ) + c.WinsResponses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "wins_responses_total"), + "Number of WINS lookup responses sent by the server", + []string{"direction"}, + nil, + ) + c.UnmatchedResponsesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "unmatched_responses_total"), + "Number of response packets received by the DNS server that do not match any outstanding remote query", + nil, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *DNSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting dns metrics", "desc", desc, "err", err) return err @@ -237,9 +261,9 @@ type Win32_PerfRawData_DNS_DNS struct { ZoneTransferSOARequestSent uint32 } -func (c *DNSCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_DNS_DNS - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/dns/dns_test.go b/pkg/collector/dns/dns_test.go new file mode 100644 index 0000000000..e6849df99c --- /dev/null +++ b/pkg/collector/dns/dns_test.go @@ -0,0 +1,12 @@ +package dns_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/dns" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, dns.Name, dns.NewWithFlags) +} diff --git a/collector/exchange.go b/pkg/collector/exchange/exchange.go similarity index 61% rename from collector/exchange.go rename to pkg/collector/exchange/exchange.go index 51048f026c..75841288e3 100644 --- a/collector/exchange.go +++ b/pkg/collector/exchange/exchange.go @@ -1,27 +1,41 @@ //go:build windows -// +build windows -package collector +package exchange import ( "fmt" "os" + "slices" "strings" "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) const ( + Name = "exchange" FlagExchangeListAllCollectors = "collectors.exchange.list" FlagExchangeCollectorsEnabled = "collectors.exchange.enabled" ) -type exchangeCollector struct { +type Config struct { + CollectorsEnabled string `yaml:"collectors_enabled"` +} + +var ConfigDefaults = Config{ + CollectorsEnabled: "", +} + +type collector struct { logger log.Logger + exchangeListAllCollectors *bool + exchangeCollectorsEnabled *string + LDAPReadTime *prometheus.Desc LDAPSearchTime *prometheus.Desc LDAPWriteTime *prometheus.Desc @@ -63,95 +77,119 @@ type exchangeCollector struct { enabledCollectors []string } -var ( - // All available collector functions - exchangeAllCollectorNames = []string{ - "ADAccessProcesses", - "TransportQueues", - "HttpProxy", - "ActiveSync", - "AvailabilityService", - "OutlookWebAccess", - "Autodiscover", - "WorkloadManagement", - "RpcClientAccess", +// All available collector functions +var exchangeAllCollectorNames = []string{ + "ADAccessProcesses", + "TransportQueues", + "HttpProxy", + "ActiveSync", + "AvailabilityService", + "OutlookWebAccess", + "Autodiscover", + "WorkloadManagement", + "RpcClientAccess", +} + +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + exchangeListAllCollectors := false + c := &collector{ + exchangeCollectorsEnabled: &config.CollectorsEnabled, + exchangeListAllCollectors: &exchangeListAllCollectors, } + c.SetLogger(logger) + return c +} - argExchangeListAllCollectors *bool +func NewWithFlags(app *kingpin.Application) types.Collector { + return &collector{ + exchangeListAllCollectors: app.Flag( + FlagExchangeListAllCollectors, + "List the collectors along with their perflib object name/ids", + ).Bool(), + + exchangeCollectorsEnabled: app.Flag( + FlagExchangeCollectorsEnabled, + "Comma-separated list of collectors to use. Defaults to all, if not specified.", + ).Default(ConfigDefaults.CollectorsEnabled).String(), + } +} - argExchangeCollectorsEnabled *string -) +func (c *collector) GetName() string { + return Name +} -// newExchangeCollectorFlags ... -func newExchangeCollectorFlags(app *kingpin.Application) { - argExchangeListAllCollectors = app.Flag( - FlagExchangeListAllCollectors, - "List the collectors along with their perflib object name/ids", - ).Bool() - - argExchangeCollectorsEnabled = app.Flag( - FlagExchangeCollectorsEnabled, - "Comma-separated list of collectors to use. Defaults to all, if not specified.", - ).Default("").String() +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) } -// newExchangeCollector returns a new Collector -func newExchangeCollector(logger log.Logger) (Collector, error) { - const subsystem = "exchange" +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{ + "MSExchange ADAccess Processes", + "MSExchangeTransport Queues", + "MSExchange HttpProxy", + "MSExchange ActiveSync", + "MSExchange Availability Service", + "MSExchange OWA", + "MSExchangeAutodiscover", + "MSExchange WorkloadManagement Workloads", + "MSExchange RpcClientAccess", + }, nil +} +func (c *collector) Build() error { // desc creates a new prometheus description desc := func(metricName string, description string, labels ...string) *prometheus.Desc { return prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "exchange", metricName), + prometheus.BuildFQName(types.Namespace, "exchange", metricName), description, labels, nil, ) } - c := exchangeCollector{ - logger: log.With(logger, "collector", subsystem), - - RPCAveragedLatency: desc("rpc_avg_latency_sec", "The latency (sec), averaged for the past 1024 packets"), - RPCRequests: desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service"), - ActiveUserCount: desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes"), - ConnectionCount: desc("rpc_connection_count", "Total number of client connections maintained"), - RPCOperationsPerSec: desc("rpc_operations_total", "The rate at which RPC operations occur"), - UserCount: desc("rpc_user_count", "Number of users"), - LDAPReadTime: desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name"), - LDAPSearchTime: desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name"), - LDAPWriteTime: desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name"), - LDAPTimeoutErrorsPerSec: desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name"), - LongRunningLDAPOperationsPerMin: desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name"), - ExternalActiveRemoteDeliveryQueueLength: desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name"), - InternalActiveRemoteDeliveryQueueLength: desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name"), - ActiveMailboxDeliveryQueueLength: desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name"), - RetryMailboxDeliveryQueueLength: desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name"), - UnreachableQueueLength: desc("transport_queues_unreachable", "Unreachable Queue length", "name"), - ExternalLargestDeliveryQueueLength: desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name"), - InternalLargestDeliveryQueueLength: desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name"), - PoisonQueueLength: desc("transport_queues_poison", "Poison Queue length", "name"), - MailboxServerLocatorAverageLatency: desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name"), - AverageAuthenticationLatency: desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name"), - OutstandingProxyRequests: desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name"), - ProxyRequestsPerSec: desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name"), - AvailabilityRequestsSec: desc("avail_service_requests_per_sec", "Number of requests serviced per second"), - CurrentUniqueUsers: desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App"), - OWARequestsPerSec: desc("owa_requests_total", "Number of requests handled by Outlook Web App per second"), - AutodiscoverRequestsPerSec: desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second"), - ActiveTasks: desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name"), - CompletedTasks: desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name"), - QueuedTasks: desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name"), - YieldedTasks: desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name"), - IsActive: desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name"), - ActiveSyncRequestsPerSec: desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load"), - AverageCASProcessingLatency: desc("http_proxy_avg_cas_proccessing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name"), - MailboxServerProxyFailureRate: desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name"), - PingCommandsPending: desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue"), - SyncCommandsPerSec: desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder"), - - enabledCollectors: make([]string, 0, len(exchangeAllCollectorNames)), - } + c.RPCAveragedLatency = desc("rpc_avg_latency_sec", "The latency (sec) averaged for the past 1024 packets") + c.RPCRequests = desc("rpc_requests", "Number of client requests currently being processed by the RPC Client Access service") + c.ActiveUserCount = desc("rpc_active_user_count", "Number of unique users that have shown some kind of activity in the last 2 minutes") + c.ConnectionCount = desc("rpc_connection_count", "Total number of client connections maintained") + c.RPCOperationsPerSec = desc("rpc_operations_total", "The rate at which RPC operations occur") + c.UserCount = desc("rpc_user_count", "Number of users") + c.LDAPReadTime = desc("ldap_read_time_sec", "Time (sec) to send an LDAP read request and receive a response", "name") + c.LDAPSearchTime = desc("ldap_search_time_sec", "Time (sec) to send an LDAP search request and receive a response", "name") + c.LDAPWriteTime = desc("ldap_write_time_sec", "Time (sec) to send an LDAP Add/Modify/Delete request and receive a response", "name") + c.LDAPTimeoutErrorsPerSec = desc("ldap_timeout_errors_total", "Total number of LDAP timeout errors", "name") + c.LongRunningLDAPOperationsPerMin = desc("ldap_long_running_ops_per_sec", "Long Running LDAP operations per second", "name") + c.ExternalActiveRemoteDeliveryQueueLength = desc("transport_queues_external_active_remote_delivery", "External Active Remote Delivery Queue length", "name") + c.InternalActiveRemoteDeliveryQueueLength = desc("transport_queues_internal_active_remote_delivery", "Internal Active Remote Delivery Queue length", "name") + c.ActiveMailboxDeliveryQueueLength = desc("transport_queues_active_mailbox_delivery", "Active Mailbox Delivery Queue length", "name") + c.RetryMailboxDeliveryQueueLength = desc("transport_queues_retry_mailbox_delivery", "Retry Mailbox Delivery Queue length", "name") + c.UnreachableQueueLength = desc("transport_queues_unreachable", "Unreachable Queue length", "name") + c.ExternalLargestDeliveryQueueLength = desc("transport_queues_external_largest_delivery", "External Largest Delivery Queue length", "name") + c.InternalLargestDeliveryQueueLength = desc("transport_queues_internal_largest_delivery", "Internal Largest Delivery Queue length", "name") + c.PoisonQueueLength = desc("transport_queues_poison", "Poison Queue length", "name") + c.MailboxServerLocatorAverageLatency = desc("http_proxy_mailbox_server_locator_avg_latency_sec", "Average latency (sec) of MailboxServerLocator web service calls", "name") + c.AverageAuthenticationLatency = desc("http_proxy_avg_auth_latency", "Average time spent authenticating CAS requests over the last 200 samples", "name") + c.OutstandingProxyRequests = desc("http_proxy_outstanding_proxy_requests", "Number of concurrent outstanding proxy requests", "name") + c.ProxyRequestsPerSec = desc("http_proxy_requests_total", "Number of proxy requests processed each second", "name") + c.AvailabilityRequestsSec = desc("avail_service_requests_per_sec", "Number of requests serviced per second") + c.CurrentUniqueUsers = desc("owa_current_unique_users", "Number of unique users currently logged on to Outlook Web App") + c.OWARequestsPerSec = desc("owa_requests_total", "Number of requests handled by Outlook Web App per second") + c.AutodiscoverRequestsPerSec = desc("autodiscover_requests_total", "Number of autodiscover service requests processed each second") + c.ActiveTasks = desc("workload_active_tasks", "Number of active tasks currently running in the background for workload management", "name") + c.CompletedTasks = desc("workload_completed_tasks", "Number of workload management tasks that have been completed", "name") + c.QueuedTasks = desc("workload_queued_tasks", "Number of workload management tasks that are currently queued up waiting to be processed", "name") + c.YieldedTasks = desc("workload_yielded_tasks", "The total number of tasks that have been yielded by a workload", "name") + c.IsActive = desc("workload_is_active", "Active indicates whether the workload is in an active (1) or paused (0) state", "name") + c.ActiveSyncRequestsPerSec = desc("activesync_requests_total", "Num HTTP requests received from the client via ASP.NET per sec. Shows Current user load") + c.AverageCASProcessingLatency = desc("http_proxy_avg_cas_proccessing_latency_sec", "Average latency (sec) of CAS processing time over the last 200 reqs", "name") + c.MailboxServerProxyFailureRate = desc("http_proxy_mailbox_proxy_failure_rate", "% of failures between this CAS and MBX servers over the last 200 samples", "name") + c.PingCommandsPending = desc("activesync_ping_cmds_pending", "Number of ping commands currently pending in the queue") + c.SyncCommandsPerSec = desc("activesync_sync_cmds_total", "Number of sync commands processed per second. Clients use this command to synchronize items within a folder") + + c.enabledCollectors = make([]string, 0, len(exchangeAllCollectorNames)) collectorDesc := map[string]string{ "ADAccessProcesses": "[19108] MSExchange ADAccess Processes", @@ -165,7 +203,7 @@ func newExchangeCollector(logger log.Logger) (Collector, error) { "RpcClientAccess": "[29336] MSExchange RpcClientAccess", } - if *argExchangeListAllCollectors { + if *c.exchangeListAllCollectors { fmt.Printf("%-32s %-32s\n", "Collector Name", "[PerfID] Perflib Object") for _, cname := range exchangeAllCollectorNames { fmt.Printf("%-32s %-32s\n", cname, collectorDesc[cname]) @@ -173,27 +211,26 @@ func newExchangeCollector(logger log.Logger) (Collector, error) { os.Exit(0) } - if *argExchangeCollectorsEnabled == "" { + if *c.exchangeCollectorsEnabled == "" { for _, collectorName := range exchangeAllCollectorNames { c.enabledCollectors = append(c.enabledCollectors, collectorName) } } else { - for _, collectorName := range strings.Split(*argExchangeCollectorsEnabled, ",") { - if find(exchangeAllCollectorNames, collectorName) { + for _, collectorName := range strings.Split(*c.exchangeCollectorsEnabled, ",") { + if slices.Contains(exchangeAllCollectorNames, collectorName) { c.enabledCollectors = append(c.enabledCollectors, collectorName) } else { - return nil, fmt.Errorf("Unknown exchange collector: %s", collectorName) + return fmt.Errorf("unknown exchange collector: %s", collectorName) } } } - return &c, nil + return nil } // Collect collects exchange metrics and sends them to prometheus -func (c *exchangeCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { - - collectorFuncs := map[string]func(ctx *ScrapeContext, ch chan<- prometheus.Metric) error{ +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + collectorFuncs := map[string]func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error{ "ADAccessProcesses": c.collectADAccessProcesses, "TransportQueues": c.collectTransportQueues, "HttpProxy": c.collectHTTPProxy, @@ -225,9 +262,9 @@ type perflibADAccessProcesses struct { LongRunningLDAPOperationsPerMin float64 `perflib:"Long Running LDAP Operations/min"` } -func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectADAccessProcesses(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibADAccessProcesses - if err := unmarshalObject(ctx.perfObjects["MSExchange ADAccess Processes"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange ADAccess Processes"], &data, c.logger); err != nil { return err } @@ -238,8 +275,8 @@ func (c *exchangeCollector) collectADAccessProcesses(ctx *ScrapeContext, ch chan continue } - // since we're not including the PID suffix from the instance names in the label names, - // we get an occasional duplicate. This seems to affect about 4 instances only on this object. + // Since we're not including the PID suffix from the instance names in the label names, we get an occasional duplicate. + // This seems to affect about 4 instances only of this object. labelUseCount[labelName]++ if labelUseCount[labelName] > 1 { labelName = fmt.Sprintf("%s_%d", labelName, labelUseCount[labelName]) @@ -283,9 +320,9 @@ type perflibAvailabilityService struct { RequestsSec float64 `perflib:"Availability Requests (sec)"` } -func (c *exchangeCollector) collectAvailabilityService(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectAvailabilityService(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibAvailabilityService - if err := unmarshalObject(ctx.perfObjects["MSExchange Availability Service"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange Availability Service"], &data, c.logger); err != nil { return err } @@ -311,9 +348,9 @@ type perflibHTTPProxy struct { ProxyRequestsPerSec float64 `perflib:"Proxy Requests/Sec"` } -func (c *exchangeCollector) collectHTTPProxy(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectHTTPProxy(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibHTTPProxy - if err := unmarshalObject(ctx.perfObjects["MSExchange HttpProxy"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange HttpProxy"], &data, c.logger); err != nil { return err } @@ -365,9 +402,9 @@ type perflibOWA struct { RequestsPerSec float64 `perflib:"Requests/sec"` } -func (c *exchangeCollector) collectOWA(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectOWA(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibOWA - if err := unmarshalObject(ctx.perfObjects["MSExchange OWA"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange OWA"], &data, c.logger); err != nil { return err } @@ -393,9 +430,9 @@ type perflibActiveSync struct { SyncCommandsPerSec float64 `perflib:"Sync Commands/sec"` } -func (c *exchangeCollector) collectActiveSync(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectActiveSync(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibActiveSync - if err := unmarshalObject(ctx.perfObjects["MSExchange ActiveSync"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange ActiveSync"], &data, c.logger); err != nil { return err } @@ -429,9 +466,9 @@ type perflibRPCClientAccess struct { UserCount float64 `perflib:"User Count"` } -func (c *exchangeCollector) collectRPC(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectRPC(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibRPCClientAccess - if err := unmarshalObject(ctx.perfObjects["MSExchange RpcClientAccess"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange RpcClientAccess"], &data, c.logger); err != nil { return err } @@ -485,9 +522,9 @@ type perflibTransportQueues struct { PoisonQueueLength float64 `perflib:"Poison Queue Length"` } -func (c *exchangeCollector) collectTransportQueues(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectTransportQueues(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibTransportQueues - if err := unmarshalObject(ctx.perfObjects["MSExchangeTransport Queues"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchangeTransport Queues"], &data, c.logger); err != nil { return err } @@ -559,9 +596,9 @@ type perflibWorkloadManagementWorkloads struct { IsActive float64 `perflib:"Active"` } -func (c *exchangeCollector) collectWorkloadManagementWorkloads(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectWorkloadManagementWorkloads(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibWorkloadManagementWorkloads - if err := unmarshalObject(ctx.perfObjects["MSExchange WorkloadManagement Workloads"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchange WorkloadManagement Workloads"], &data, c.logger); err != nil { return err } @@ -610,9 +647,9 @@ type perflibAutodiscover struct { RequestsPerSec float64 `perflib:"Requests/sec"` } -func (c *exchangeCollector) collectAutoDiscover(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) collectAutoDiscover(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { var data []perflibAutodiscover - if err := unmarshalObject(ctx.perfObjects["MSExchangeAutodiscover"], &data, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["MSExchangeAutodiscover"], &data, c.logger); err != nil { return err } for _, autodisc := range data { @@ -625,14 +662,14 @@ func (c *exchangeCollector) collectAutoDiscover(ctx *ScrapeContext, ch chan<- pr return nil } -// toLabelName converts strings to lowercase and replaces all whitespace and dots with underscores -func (c *exchangeCollector) toLabelName(name string) string { +// toLabelName converts strings to lowercase and replaces all whitespaces and dots with underscores +func (c *collector) toLabelName(name string) string { s := strings.ReplaceAll(strings.Join(strings.Fields(strings.ToLower(name)), "_"), ".", "_") s = strings.ReplaceAll(s, "__", "_") return s } // msToSec converts from ms to seconds -func (c *exchangeCollector) msToSec(t float64) float64 { +func (c *collector) msToSec(t float64) float64 { return t / 1000 } diff --git a/pkg/collector/exchange/exchange_test.go b/pkg/collector/exchange/exchange_test.go new file mode 100644 index 0000000000..e8f1b4eb95 --- /dev/null +++ b/pkg/collector/exchange/exchange_test.go @@ -0,0 +1,12 @@ +package exchange_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/exchange" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, exchange.Name, exchange.NewWithFlags) +} diff --git a/pkg/collector/fsrmquota/fsrmquota.go b/pkg/collector/fsrmquota/fsrmquota.go new file mode 100644 index 0000000000..f431389653 --- /dev/null +++ b/pkg/collector/fsrmquota/fsrmquota.go @@ -0,0 +1,218 @@ +//go:build windows + +package fsrmquota + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "fsrmquota" + +type Config struct{} + +var ConfigDefaults = Config{} + +type collector struct { + logger log.Logger + + QuotasCount *prometheus.Desc + Path *prometheus.Desc + PeakUsage *prometheus.Desc + Size *prometheus.Desc + Usage *prometheus.Desc + + Description *prometheus.Desc + Disabled *prometheus.Desc + MatchesTemplate *prometheus.Desc + SoftLimit *prometheus.Desc + Template *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.QuotasCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "count"), + "Number of Quotas", + nil, + nil, + ) + c.PeakUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "peak_usage_bytes"), + "The highest amount of disk space usage charged to this quota. (PeakUsage)", + []string{"path", "template"}, + nil, + ) + c.Size = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "size_bytes"), + "The size of the quota. (Size)", + []string{"path", "template"}, + nil, + ) + c.Usage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usage_bytes"), + "The current amount of disk space usage charged to this quota. (Usage)", + []string{"path", "template"}, + nil, + ) + c.Description = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "description"), + "Description of the quota (Description)", + []string{"path", "template", "description"}, + nil, + ) + c.Disabled = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "disabled"), + "If 1, the quota is disabled. The default value is 0. (Disabled)", + []string{"path", "template"}, + nil, + ) + c.SoftLimit = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "softlimit"), + "If 1, the quota is a soft limit. If 0, the quota is a hard limit. The default value is 0. Optional (SoftLimit)", + []string{"path", "template"}, + nil, + ) + c.Template = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "template"), + "Quota template name. (Template)", + []string{"path", "template"}, + nil, + ) + c.MatchesTemplate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "matchestemplate"), + "If 1, the property values of this quota match those values of the template from which it was derived. (MatchesTemplate)", + []string{"path", "template"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("msg", "failed collecting fsrmquota metrics", "desc", desc, "err", err) + return err + } + return nil +} + +// MSFT_FSRMQuota docs: +// https://docs.microsoft.com/en-us/previous-versions/windows/desktop/fsrm/msft-fsrmquota +type MSFT_FSRMQuota struct { + Name string + + Path string + PeakUsage uint64 + Size uint64 + Usage uint64 + Description string + Template string + // Threshold string + Disabled bool + MatchesTemplate bool + SoftLimit bool +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []MSFT_FSRMQuota + q := wmi.QueryAll(&dst, c.logger) + + var count int + + if err := wmi.QueryNamespace(q, &dst, "root/microsoft/windows/fsrm"); err != nil { + return nil, err + } + + for _, quota := range dst { + + count++ + path := quota.Path + template := quota.Template + Description := quota.Description + + ch <- prometheus.MustNewConstMetric( + c.PeakUsage, + prometheus.GaugeValue, + float64(quota.PeakUsage), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.Size, + prometheus.GaugeValue, + float64(quota.Size), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.Usage, + prometheus.GaugeValue, + float64(quota.Usage), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.Description, + prometheus.GaugeValue, + 1.0, + path, template, Description, + ) + ch <- prometheus.MustNewConstMetric( + c.Disabled, + prometheus.GaugeValue, + utils.BoolToFloat(quota.Disabled), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.MatchesTemplate, + prometheus.GaugeValue, + utils.BoolToFloat(quota.MatchesTemplate), + path, + template, + ) + ch <- prometheus.MustNewConstMetric( + c.SoftLimit, + prometheus.GaugeValue, + utils.BoolToFloat(quota.SoftLimit), + path, + template, + ) + } + + ch <- prometheus.MustNewConstMetric( + c.QuotasCount, + prometheus.GaugeValue, + float64(count), + ) + return nil, nil +} diff --git a/pkg/collector/fsrmquota/fsrmquota_test.go b/pkg/collector/fsrmquota/fsrmquota_test.go new file mode 100644 index 0000000000..2534a4b08f --- /dev/null +++ b/pkg/collector/fsrmquota/fsrmquota_test.go @@ -0,0 +1,12 @@ +package fsrmquota_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/fsrmquota" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, fsrmquota.Name, fsrmquota.NewWithFlags) +} diff --git a/pkg/collector/handler.go b/pkg/collector/handler.go new file mode 100644 index 0000000000..068532e709 --- /dev/null +++ b/pkg/collector/handler.go @@ -0,0 +1,77 @@ +//go:build windows + +package collector + +import ( + "fmt" + stdlog "log" + "net/http" + "strconv" + "time" + + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" + "github.com/prometheus/client_golang/prometheus/collectors" + "github.com/prometheus/client_golang/prometheus/promhttp" + "github.com/prometheus/common/version" +) + +func (c *Collectors) BuildServeHTTP(disableExporterMetrics bool, timeoutMargin float64) http.HandlerFunc { + collectorFactory := func(timeout time.Duration, requestedCollectors []string) (error, *Prometheus) { + filteredCollectors := make(map[string]types.Collector) + // scrape all enabled collectors if no collector is requested + if len(requestedCollectors) == 0 { + filteredCollectors = c.collectors + } + for _, name := range requestedCollectors { + col, exists := c.collectors[name] + if !exists { + return fmt.Errorf("unavailable collector: %s", name), nil + } + filteredCollectors[name] = col + } + return nil, NewPrometheus(timeout, c, c.logger) + } + + return func(w http.ResponseWriter, r *http.Request) { + const defaultTimeout = 10.0 + + var timeoutSeconds float64 + if v := r.Header.Get("X-Prometheus-Scrape-Timeout-Seconds"); v != "" { + var err error + timeoutSeconds, err = strconv.ParseFloat(v, 64) + if err != nil { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Couldn't parse X-Prometheus-Scrape-Timeout-Seconds: %q. Defaulting timeout to %f", v, defaultTimeout)) + } + } + if timeoutSeconds == 0 { + timeoutSeconds = defaultTimeout + } + timeoutSeconds = timeoutSeconds - timeoutMargin + + reg := prometheus.NewRegistry() + err, wc := collectorFactory(time.Duration(timeoutSeconds*float64(time.Second)), r.URL.Query()["collect[]"]) + if err != nil { + _ = level.Warn(c.logger).Log("msg", "Couldn't create filtered metrics handler", "err", err) + w.WriteHeader(http.StatusBadRequest) + w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err))) //nolint:errcheck + return + } + + reg.MustRegister(wc) + if !disableExporterMetrics { + reg.MustRegister( + collectors.NewProcessCollector(collectors.ProcessCollectorOpts{}), + collectors.NewGoCollector(), + version.NewCollector("windows_exporter"), + ) + } + + h := promhttp.HandlerFor(reg, promhttp.HandlerOpts{ + ErrorLog: stdlog.New(log.NewStdlibAdapter(level.Error(c.logger)), "", stdlog.Lshortfile), + }) + h.ServeHTTP(w, r) + } +} diff --git a/collector/hyperv.go b/pkg/collector/hyperv/hyperv.go similarity index 54% rename from collector/hyperv.go rename to pkg/collector/hyperv/hyperv.go index 39fd0d92e3..a299920b99 100644 --- a/collector/hyperv.go +++ b/pkg/collector/hyperv/hyperv.go @@ -1,20 +1,28 @@ //go:build windows -// +build windows -package collector +package hyperv import ( - fmt "fmt" + "fmt" "strings" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// HyperVCollector is a Prometheus collector for hyper-v -type HyperVCollector struct { +const Name = "hyperv" + +type Config struct{} + +var ConfigDefaults = Config{} + +// collector is a Prometheus collector for hyper-v +type collector struct { logger log.Logger // Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary @@ -132,591 +140,609 @@ type HyperVCollector struct { VMMemoryRemovedMemory *prometheus.Desc } -// newHyperVCollector ... -func newHyperVCollector(logger log.Logger) (Collector, error) { - const subsystem = "hyperv" +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { buildSubsystemName := func(component string) string { return "hyperv_" + component } - return &HyperVCollector{ - logger: log.With(logger, "collector", subsystem), - - HealthCritical: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("health"), "critical"), - "This counter represents the number of virtual machines with critical health", - nil, - nil, - ), - HealthOk: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("health"), "ok"), - "This counter represents the number of virtual machines with ok health", - nil, - nil, - ), - - // - - PhysicalPagesAllocated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vid"), "physical_pages_allocated"), - "The number of physical pages allocated", - []string{"vm"}, - nil, - ), - PreferredNUMANodeIndex: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vid"), "preferred_numa_node_index"), - "The preferred NUMA node index associated with this partition", - []string{"vm"}, - nil, - ), - RemotePhysicalPages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vid"), "remote_physical_pages"), - "The number of physical pages not allocated from the preferred NUMA node", - []string{"vm"}, - nil, - ), - - // - - AddressSpaces: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "address_spaces"), - "The number of address spaces in the virtual TLB of the partition", - nil, - nil, - ), - AttachedDevices: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "attached_devices"), - "The number of devices attached to the partition", - nil, - nil, - ), - DepositedPages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "deposited_pages"), - "The number of pages deposited into the partition", - nil, - nil, - ), - DeviceDMAErrors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_dma_errors"), - "An indicator of illegal DMA requests generated by all devices assigned to the partition", - nil, - nil, - ), - DeviceInterruptErrors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_interrupt_errors"), - "An indicator of illegal interrupt requests generated by all devices assigned to the partition", - nil, - nil, - ), - DeviceInterruptMappings: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_interrupt_mappings"), - "The number of device interrupt mappings used by the partition", - nil, - nil, - ), - DeviceInterruptThrottleEvents: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "device_interrupt_throttle_events"), - "The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts", - nil, - nil, - ), - GPAPages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "preferred_numa_node_index"), - "The number of pages present in the GPA space of the partition (zero for root partition)", - nil, - nil, - ), - GPASpaceModifications: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "gpa_space_modifications"), - "The rate of modifications to the GPA space of the partition", - nil, - nil, - ), - IOTLBFlushCost: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "io_tlb_flush_cost"), - "The average time (in nanoseconds) spent processing an I/O TLB flush", - nil, - nil, - ), - IOTLBFlushes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "io_tlb_flush"), - "The rate of flushes of I/O TLBs of the partition", - nil, - nil, - ), - RecommendedVirtualTLBSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "recommended_virtual_tlb_size"), - "The recommended number of pages to be deposited for the virtual TLB", - nil, - nil, - ), - SkippedTimerTicks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "physical_pages_allocated"), - "The number of timer interrupts skipped for the partition", - nil, - nil, - ), - Value1Gdevicepages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "1G_device_pages"), - "The number of 1G pages present in the device space of the partition", - nil, - nil, - ), - Value1GGPApages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "1G_gpa_pages"), - "The number of 1G pages present in the GPA space of the partition", - nil, - nil, - ), - Value2Mdevicepages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "2M_device_pages"), - "The number of 2M pages present in the device space of the partition", - nil, - nil, - ), - Value2MGPApages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "2M_gpa_pages"), - "The number of 2M pages present in the GPA space of the partition", - nil, - nil, - ), - Value4Kdevicepages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "4K_device_pages"), - "The number of 4K pages present in the device space of the partition", - nil, - nil, - ), - Value4KGPApages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "4K_gpa_pages"), - "The number of 4K pages present in the GPA space of the partition", - nil, - nil, - ), - VirtualTLBFlushEntires: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "virtual_tlb_flush_entires"), - "The rate of flushes of the entire virtual TLB", - nil, - nil, - ), - VirtualTLBPages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("root_partition"), "virtual_tlb_pages"), - "The number of pages used by the virtual TLB of the partition", - nil, - nil, - ), - - // - - VirtualProcessors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("hypervisor"), "virtual_processors"), - "The number of virtual processors present in the system", - nil, - nil, - ), - LogicalProcessors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("hypervisor"), "logical_processors"), - "The number of logical processors present in the system", - nil, - nil, - ), - - // - - HostLPGuestRunTimePercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_lp"), "guest_run_time_percent"), - "The percentage of time spent by the processor in guest code", - []string{"core"}, - nil, - ), - HostLPHypervisorRunTimePercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_lp"), "hypervisor_run_time_percent"), - "The percentage of time spent by the processor in hypervisor code", - []string{"core"}, - nil, - ), - HostLPTotalRunTimePercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_lp"), "total_run_time_percent"), - "The percentage of time spent by the processor in guest and hypervisor code", - []string{"core"}, - nil, - ), - - // - - HostGuestRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "guest_run_time"), - "The time spent by the virtual processor in guest code", - []string{"core"}, - nil, - ), - HostHypervisorRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "hypervisor_run_time"), - "The time spent by the virtual processor in hypervisor code", - []string{"core"}, - nil, - ), - HostRemoteRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "remote_run_time"), - "The time spent by the virtual processor running on a remote node", - []string{"core"}, - nil, - ), - HostTotalRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "total_run_time"), - "The time spent by the virtual processor in guest and hypervisor code", - []string{"core"}, - nil, - ), - HostCPUWaitTimePerDispatch: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("host_cpu"), "wait_time_per_dispatch_total"), - "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", - []string{"core"}, - nil, - ), - - // - - VMGuestRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "guest_run_time"), - "The time spent by the virtual processor in guest code", - []string{"vm", "core"}, - nil, - ), - VMHypervisorRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "hypervisor_run_time"), - "The time spent by the virtual processor in hypervisor code", - []string{"vm", "core"}, - nil, - ), - VMRemoteRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "remote_run_time"), - "The time spent by the virtual processor running on a remote node", - []string{"vm", "core"}, - nil, - ), - VMTotalRunTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "total_run_time"), - "The time spent by the virtual processor in guest and hypervisor code", - []string{"vm", "core"}, - nil, - ), - VMCPUWaitTimePerDispatch: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_cpu"), "wait_time_per_dispatch_total"), - "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", - []string{"vm", "core"}, - nil, - ), - - // - BroadcastPacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "broadcast_packets_received_total"), - "This represents the total number of broadcast packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - BroadcastPacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "broadcast_packets_sent_total"), - "This represents the total number of broadcast packets sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - Bytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "bytes_total"), - "This represents the total number of bytes per second traversing the virtual switch", - []string{"vswitch"}, - nil, - ), - BytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "bytes_received_total"), - "This represents the total number of bytes received per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - BytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "bytes_sent_total"), - "This represents the total number of bytes sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - DirectedPacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "directed_packets_received_total"), - "This represents the total number of directed packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - DirectedPacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "directed_packets_send_total"), - "This represents the total number of directed packets sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - DroppedPacketsIncoming: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "dropped_packets_incoming_total"), - "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", - []string{"vswitch"}, - nil, - ), - DroppedPacketsOutgoing: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "dropped_packets_outcoming_total"), - "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", - []string{"vswitch"}, - nil, - ), - ExtensionsDroppedPacketsIncoming: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_incoming_total"), - "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", - []string{"vswitch"}, - nil, - ), - ExtensionsDroppedPacketsOutgoing: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_outcoming_total"), - "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", - []string{"vswitch"}, - nil, - ), - LearnedMacAddresses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "learned_mac_addresses_total"), - "This counter represents the total number of learned MAC addresses of the virtual switch", - []string{"vswitch"}, - nil, - ), - MulticastPacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "multicast_packets_received_total"), - "This represents the total number of multicast packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - MulticastPacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "multicast_packets_sent_total"), - "This represents the total number of multicast packets sent per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - NumberofSendChannelMoves: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "number_of_send_channel_moves_total"), - "This represents the total number of send channel moves per second on this virtual switch", - []string{"vswitch"}, - nil, - ), - NumberofVMQMoves: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "number_of_vmq_moves_total"), - "This represents the total number of VMQ moves per second on this virtual switch", - []string{"vswitch"}, - nil, - ), - PacketsFlooded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_flooded_total"), - "This counter represents the total number of packets flooded by the virtual switch", - []string{"vswitch"}, - nil, - ), - Packets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_total"), - "This represents the total number of packets per second traversing the virtual switch", - []string{"vswitch"}, - nil, - ), - PacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_received_total"), - "This represents the total number of packets received per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - PacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "packets_sent_total"), - "This represents the total number of packets send per second by the virtual switch", - []string{"vswitch"}, - nil, - ), - PurgedMacAddresses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vswitch"), "purged_mac_addresses_total"), - "This counter represents the total number of purged MAC addresses of the virtual switch", - []string{"vswitch"}, - nil, - ), - - // - - AdapterBytesDropped: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_dropped"), - "Bytes Dropped is the number of bytes dropped on the network adapter", - []string{"adapter"}, - nil, - ), - AdapterBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_received"), - "Bytes received is the number of bytes received on the network adapter", - []string{"adapter"}, - nil, - ), - AdapterBytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "bytes_sent"), - "Bytes sent is the number of bytes sent over the network adapter", - []string{"adapter"}, - nil, - ), - AdapterFramesDropped: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_dropped"), - "Frames Dropped is the number of frames dropped on the network adapter", - []string{"adapter"}, - nil, - ), - AdapterFramesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_received"), - "Frames received is the number of frames received on the network adapter", - []string{"adapter"}, - nil, - ), - AdapterFramesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("ethernet"), "frames_sent"), - "Frames sent is the number of frames sent over the network adapter", - []string{"adapter"}, - nil, - ), - - // - - VMStorageErrorCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "error_count"), - "This counter represents the total number of errors that have occurred on this virtual device", - []string{"vm_device"}, - nil, - ), - VMStorageQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "queue_length"), - "This counter represents the current queue length on this virtual device", - []string{"vm_device"}, - nil, - ), - VMStorageReadBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "bytes_read"), - "This counter represents the total number of bytes that have been read per second on this virtual device", - []string{"vm_device"}, - nil, - ), - VMStorageReadOperations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "operations_read"), - "This counter represents the number of read operations that have occurred per second on this virtual device", - []string{"vm_device"}, - nil, - ), - VMStorageWriteBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "bytes_written"), - "This counter represents the total number of bytes that have been written per second on this virtual device", - []string{"vm_device"}, - nil, - ), - VMStorageWriteOperations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_device"), "operations_written"), - "This counter represents the number of write operations that have occurred per second on this virtual device", - []string{"vm_device"}, - nil, - ), - - // - - VMNetworkBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "bytes_received"), - "This counter represents the total number of bytes received per second by the network adapter", - []string{"vm_interface"}, - nil, - ), - VMNetworkBytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "bytes_sent"), - "This counter represents the total number of bytes sent per second by the network adapter", - []string{"vm_interface"}, - nil, - ), - VMNetworkDroppedPacketsIncoming: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_incoming_dropped"), - "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", - []string{"vm_interface"}, - nil, - ), - VMNetworkDroppedPacketsOutgoing: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_outgoing_dropped"), - "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", - []string{"vm_interface"}, - nil, - ), - VMNetworkPacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_received"), - "This counter represents the total number of packets received per second by the network adapter", - []string{"vm_interface"}, - nil, - ), - VMNetworkPacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_interface"), "packets_sent"), - "This counter represents the total number of packets sent per second by the network adapter", - []string{"vm_interface"}, - nil, - ), - - // - - VMMemoryAddedMemory: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "added_total"), - "This counter represents memory in MB added to the VM", - []string{"vm"}, - nil, - ), - VMMemoryAveragePressure: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_average"), - "This gauge represents the average pressure in the VM.", - []string{"vm"}, - nil, - ), - VMMemoryCurrentPressure: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_current"), - "This gauge represents the current pressure in the VM.", - []string{"vm"}, - nil, - ), - VMMemoryGuestVisiblePhysicalMemory: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "physical_guest_visible"), - "'This gauge represents the amount of memory in MB visible to the VM guest.'", - []string{"vm"}, - nil, - ), - VMMemoryMaximumPressure: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_maximum"), - "This gauge represents the maximum pressure band in the VM.", - []string{"vm"}, - nil, - ), - VMMemoryMemoryAddOperations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "add_operations_total"), - "This counter represents the number of operations adding memory to the VM.", - []string{"vm"}, - nil, - ), - VMMemoryMemoryRemoveOperations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "remove_operations_total"), - "This counter represents the number of operations removing memory from the VM.", - []string{"vm"}, - nil, - ), - VMMemoryMinimumPressure: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "pressure_minimum"), - "This gauge represents the minimum pressure band in the VM.", - []string{"vm"}, - nil, - ), - VMMemoryPhysicalMemory: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "physical"), - "This gauge represents the current amount of memory in MB assigned to the VM.", - []string{"vm"}, - nil, - ), - VMMemoryRemovedMemory: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, buildSubsystemName("vm_memory"), "removed_total"), - "This counter represents memory in MB removed from the VM", - []string{"vm"}, - nil, - ), - }, nil + + c.HealthCritical = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("health"), "critical"), + "This counter represents the number of virtual machines with critical health", + nil, + nil, + ) + c.HealthOk = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("health"), "ok"), + "This counter represents the number of virtual machines with ok health", + nil, + nil, + ) + + // + + c.PhysicalPagesAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vid"), "physical_pages_allocated"), + "The number of physical pages allocated", + []string{"vm"}, + nil, + ) + c.PreferredNUMANodeIndex = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vid"), "preferred_numa_node_index"), + "The preferred NUMA node index associated with this partition", + []string{"vm"}, + nil, + ) + c.RemotePhysicalPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vid"), "remote_physical_pages"), + "The number of physical pages not allocated from the preferred NUMA node", + []string{"vm"}, + nil, + ) + + // + + c.AddressSpaces = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "address_spaces"), + "The number of address spaces in the virtual TLB of the partition", + nil, + nil, + ) + c.AttachedDevices = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "attached_devices"), + "The number of devices attached to the partition", + nil, + nil, + ) + c.DepositedPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "deposited_pages"), + "The number of pages deposited into the partition", + nil, + nil, + ) + c.DeviceDMAErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_dma_errors"), + "An indicator of illegal DMA requests generated by all devices assigned to the partition", + nil, + nil, + ) + c.DeviceInterruptErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_interrupt_errors"), + "An indicator of illegal interrupt requests generated by all devices assigned to the partition", + nil, + nil, + ) + c.DeviceInterruptMappings = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_interrupt_mappings"), + "The number of device interrupt mappings used by the partition", + nil, + nil, + ) + c.DeviceInterruptThrottleEvents = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "device_interrupt_throttle_events"), + "The number of times an interrupt from a device assigned to the partition was temporarily throttled because the device was generating too many interrupts", + nil, + nil, + ) + c.GPAPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "preferred_numa_node_index"), + "The number of pages present in the GPA space of the partition (zero for root partition)", + nil, + nil, + ) + c.GPASpaceModifications = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "gpa_space_modifications"), + "The rate of modifications to the GPA space of the partition", + nil, + nil, + ) + c.IOTLBFlushCost = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "io_tlb_flush_cost"), + "The average time (in nanoseconds) spent processing an I/O TLB flush", + nil, + nil, + ) + c.IOTLBFlushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "io_tlb_flush"), + "The rate of flushes of I/O TLBs of the partition", + nil, + nil, + ) + c.RecommendedVirtualTLBSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "recommended_virtual_tlb_size"), + "The recommended number of pages to be deposited for the virtual TLB", + nil, + nil, + ) + c.SkippedTimerTicks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "physical_pages_allocated"), + "The number of timer interrupts skipped for the partition", + nil, + nil, + ) + c.Value1Gdevicepages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "1G_device_pages"), + "The number of 1G pages present in the device space of the partition", + nil, + nil, + ) + c.Value1GGPApages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "1G_gpa_pages"), + "The number of 1G pages present in the GPA space of the partition", + nil, + nil, + ) + c.Value2Mdevicepages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "2M_device_pages"), + "The number of 2M pages present in the device space of the partition", + nil, + nil, + ) + c.Value2MGPApages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "2M_gpa_pages"), + "The number of 2M pages present in the GPA space of the partition", + nil, + nil, + ) + c.Value4Kdevicepages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "4K_device_pages"), + "The number of 4K pages present in the device space of the partition", + nil, + nil, + ) + c.Value4KGPApages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "4K_gpa_pages"), + "The number of 4K pages present in the GPA space of the partition", + nil, + nil, + ) + c.VirtualTLBFlushEntires = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "virtual_tlb_flush_entires"), + "The rate of flushes of the entire virtual TLB", + nil, + nil, + ) + c.VirtualTLBPages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("root_partition"), "virtual_tlb_pages"), + "The number of pages used by the virtual TLB of the partition", + nil, + nil, + ) + + // + + c.VirtualProcessors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("hypervisor"), "virtual_processors"), + "The number of virtual processors present in the system", + nil, + nil, + ) + c.LogicalProcessors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("hypervisor"), "logical_processors"), + "The number of logical processors present in the system", + nil, + nil, + ) + + // + + c.HostLPGuestRunTimePercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_lp"), "guest_run_time_percent"), + "The percentage of time spent by the processor in guest code", + []string{"core"}, + nil, + ) + c.HostLPHypervisorRunTimePercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_lp"), "hypervisor_run_time_percent"), + "The percentage of time spent by the processor in hypervisor code", + []string{"core"}, + nil, + ) + c.HostLPTotalRunTimePercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_lp"), "total_run_time_percent"), + "The percentage of time spent by the processor in guest and hypervisor code", + []string{"core"}, + nil, + ) + + // + + c.HostGuestRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "guest_run_time"), + "The time spent by the virtual processor in guest code", + []string{"core"}, + nil, + ) + c.HostHypervisorRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "hypervisor_run_time"), + "The time spent by the virtual processor in hypervisor code", + []string{"core"}, + nil, + ) + c.HostRemoteRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "remote_run_time"), + "The time spent by the virtual processor running on a remote node", + []string{"core"}, + nil, + ) + c.HostTotalRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "total_run_time"), + "The time spent by the virtual processor in guest and hypervisor code", + []string{"core"}, + nil, + ) + c.HostCPUWaitTimePerDispatch = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("host_cpu"), "wait_time_per_dispatch_total"), + "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", + []string{"core"}, + nil, + ) + + // + + c.VMGuestRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "guest_run_time"), + "The time spent by the virtual processor in guest code", + []string{"vm", "core"}, + nil, + ) + c.VMHypervisorRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "hypervisor_run_time"), + "The time spent by the virtual processor in hypervisor code", + []string{"vm", "core"}, + nil, + ) + c.VMRemoteRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "remote_run_time"), + "The time spent by the virtual processor running on a remote node", + []string{"vm", "core"}, + nil, + ) + c.VMTotalRunTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "total_run_time"), + "The time spent by the virtual processor in guest and hypervisor code", + []string{"vm", "core"}, + nil, + ) + c.VMCPUWaitTimePerDispatch = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_cpu"), "wait_time_per_dispatch_total"), + "Time in nanoseconds waiting for a virtual processor to be dispatched onto a logical processor", + []string{"vm", "core"}, + nil, + ) + + // + c.BroadcastPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "broadcast_packets_received_total"), + "This represents the total number of broadcast packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.BroadcastPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "broadcast_packets_sent_total"), + "This represents the total number of broadcast packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.Bytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "bytes_total"), + "This represents the total number of bytes per second traversing the virtual switch", + []string{"vswitch"}, + nil, + ) + c.BytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "bytes_received_total"), + "This represents the total number of bytes received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.BytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "bytes_sent_total"), + "This represents the total number of bytes sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.DirectedPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "directed_packets_received_total"), + "This represents the total number of directed packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.DirectedPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "directed_packets_send_total"), + "This represents the total number of directed packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.DroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "dropped_packets_incoming_total"), + "This represents the total number of packet dropped per second by the virtual switch in the incoming direction", + []string{"vswitch"}, + nil, + ) + c.DroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "dropped_packets_outcoming_total"), + "This represents the total number of packet dropped per second by the virtual switch in the outgoing direction", + []string{"vswitch"}, + nil, + ) + c.ExtensionsDroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_incoming_total"), + "This represents the total number of packet dropped per second by the virtual switch extensions in the incoming direction", + []string{"vswitch"}, + nil, + ) + c.ExtensionsDroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "extensions_dropped_packets_outcoming_total"), + "This represents the total number of packet dropped per second by the virtual switch extensions in the outgoing direction", + []string{"vswitch"}, + nil, + ) + c.LearnedMacAddresses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "learned_mac_addresses_total"), + "This counter represents the total number of learned MAC addresses of the virtual switch", + []string{"vswitch"}, + nil, + ) + c.MulticastPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "multicast_packets_received_total"), + "This represents the total number of multicast packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.MulticastPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "multicast_packets_sent_total"), + "This represents the total number of multicast packets sent per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.NumberofSendChannelMoves = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "number_of_send_channel_moves_total"), + "This represents the total number of send channel moves per second on this virtual switch", + []string{"vswitch"}, + nil, + ) + c.NumberofVMQMoves = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "number_of_vmq_moves_total"), + "This represents the total number of VMQ moves per second on this virtual switch", + []string{"vswitch"}, + nil, + ) + c.PacketsFlooded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_flooded_total"), + "This counter represents the total number of packets flooded by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.Packets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_total"), + "This represents the total number of packets per second traversing the virtual switch", + []string{"vswitch"}, + nil, + ) + c.PacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_received_total"), + "This represents the total number of packets received per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.PacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "packets_sent_total"), + "This represents the total number of packets send per second by the virtual switch", + []string{"vswitch"}, + nil, + ) + c.PurgedMacAddresses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vswitch"), "purged_mac_addresses_total"), + "This counter represents the total number of purged MAC addresses of the virtual switch", + []string{"vswitch"}, + nil, + ) + + // + + c.AdapterBytesDropped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "bytes_dropped"), + "Bytes Dropped is the number of bytes dropped on the network adapter", + []string{"adapter"}, + nil, + ) + c.AdapterBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "bytes_received"), + "Bytes received is the number of bytes received on the network adapter", + []string{"adapter"}, + nil, + ) + c.AdapterBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "bytes_sent"), + "Bytes sent is the number of bytes sent over the network adapter", + []string{"adapter"}, + nil, + ) + c.AdapterFramesDropped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "frames_dropped"), + "Frames Dropped is the number of frames dropped on the network adapter", + []string{"adapter"}, + nil, + ) + c.AdapterFramesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "frames_received"), + "Frames received is the number of frames received on the network adapter", + []string{"adapter"}, + nil, + ) + c.AdapterFramesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("ethernet"), "frames_sent"), + "Frames sent is the number of frames sent over the network adapter", + []string{"adapter"}, + nil, + ) + + // + + c.VMStorageErrorCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "error_count"), + "This counter represents the total number of errors that have occurred on this virtual device", + []string{"vm_device"}, + nil, + ) + c.VMStorageQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "queue_length"), + "This counter represents the current queue length on this virtual device", + []string{"vm_device"}, + nil, + ) + c.VMStorageReadBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "bytes_read"), + "This counter represents the total number of bytes that have been read per second on this virtual device", + []string{"vm_device"}, + nil, + ) + c.VMStorageReadOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "operations_read"), + "This counter represents the number of read operations that have occurred per second on this virtual device", + []string{"vm_device"}, + nil, + ) + c.VMStorageWriteBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "bytes_written"), + "This counter represents the total number of bytes that have been written per second on this virtual device", + []string{"vm_device"}, + nil, + ) + c.VMStorageWriteOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_device"), "operations_written"), + "This counter represents the number of write operations that have occurred per second on this virtual device", + []string{"vm_device"}, + nil, + ) + + // + + c.VMNetworkBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "bytes_received"), + "This counter represents the total number of bytes received per second by the network adapter", + []string{"vm_interface"}, + nil, + ) + c.VMNetworkBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "bytes_sent"), + "This counter represents the total number of bytes sent per second by the network adapter", + []string{"vm_interface"}, + nil, + ) + c.VMNetworkDroppedPacketsIncoming = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_incoming_dropped"), + "This counter represents the total number of dropped packets per second in the incoming direction of the network adapter", + []string{"vm_interface"}, + nil, + ) + c.VMNetworkDroppedPacketsOutgoing = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_outgoing_dropped"), + "This counter represents the total number of dropped packets per second in the outgoing direction of the network adapter", + []string{"vm_interface"}, + nil, + ) + c.VMNetworkPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_received"), + "This counter represents the total number of packets received per second by the network adapter", + []string{"vm_interface"}, + nil, + ) + c.VMNetworkPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_interface"), "packets_sent"), + "This counter represents the total number of packets sent per second by the network adapter", + []string{"vm_interface"}, + nil, + ) + + // + + c.VMMemoryAddedMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "added_total"), + "This counter represents memory in MB added to the VM", + []string{"vm"}, + nil, + ) + c.VMMemoryAveragePressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_average"), + "This gauge represents the average pressure in the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryCurrentPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_current"), + "This gauge represents the current pressure in the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryGuestVisiblePhysicalMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "physical_guest_visible"), + "'This gauge represents the amount of memory in MB visible to the VM guest.'", + []string{"vm"}, + nil, + ) + c.VMMemoryMaximumPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_maximum"), + "This gauge represents the maximum pressure band in the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryMemoryAddOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "add_operations_total"), + "This counter represents the number of operations adding memory to the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryMemoryRemoveOperations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "remove_operations_total"), + "This counter represents the number of operations removing memory from the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryMinimumPressure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "pressure_minimum"), + "This gauge represents the minimum pressure band in the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryPhysicalMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "physical"), + "This gauge represents the current amount of memory in MB assigned to the VM.", + []string{"vm"}, + nil, + ) + c.VMMemoryRemovedMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, buildSubsystemName("vm_memory"), "removed_total"), + "This counter represents memory in MB removed from the VM", + []string{"vm"}, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *HyperVCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectVmHealth(ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting hyperV health status metrics", "desc", desc, "err", err) return err @@ -786,9 +812,9 @@ type Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary HealthOk uint32 } -func (c *HyperVCollector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmHealth(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_VmmsVirtualMachineStats_HyperVVirtualMachineHealthSummary - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -819,9 +845,9 @@ type Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition struct { RemotePhysicalPages uint64 } -func (c *HyperVCollector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmVid(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_VidPerfProvider_HyperVVMVidPartition - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -883,9 +909,9 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition struct { VirtualTLBPages uint64 } -func (c *HyperVCollector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmHv(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootPartition - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1021,9 +1047,9 @@ type Win32_PerfRawData_HvStats_HyperVHypervisor struct { VirtualProcessors uint64 } -func (c *HyperVCollector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmProcessor(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisor - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1055,9 +1081,9 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor struct { PercentTotalRunTime uint } -func (c *HyperVCollector) collectHostLPUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectHostLPUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorLogicalProcessor - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1110,9 +1136,9 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor struct { CPUWaitTimePerDispatch uint64 } -func (c *HyperVCollector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectHostCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorRootVirtualProcessor - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1178,9 +1204,9 @@ type Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor struct { CPUWaitTimePerDispatch uint64 } -func (c *HyperVCollector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmCpuUsage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1272,9 +1298,9 @@ type Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch struct { PurgedMacAddressesPersec uint64 } -func (c *HyperVCollector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmSwitch(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NvspSwitchStats_HyperVVirtualSwitch - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1437,9 +1463,9 @@ type Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter struct { FramesSentPersec uint64 } -func (c *HyperVCollector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmEthernet(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_EthernetPerfProvider_HyperVLegacyNetworkAdapter - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1507,9 +1533,9 @@ type Win32_PerfRawData_Counters_HyperVVirtualStorageDevice struct { WriteOperationsPerSec uint64 } -func (c *HyperVCollector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmStorage(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_Counters_HyperVVirtualStorageDevice - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1576,9 +1602,9 @@ type Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter struct { PacketsSentPersec uint64 } -func (c *HyperVCollector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NvspNicStats_HyperVVirtualNetworkAdapter - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1649,9 +1675,9 @@ type Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM struct { RemovedMemory uint64 } -func (c *HyperVCollector) collectVmMemory(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectVmMemory(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_BalancerStats_HyperVDynamicMemoryVM - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/hyperv/hyperv_test.go b/pkg/collector/hyperv/hyperv_test.go new file mode 100644 index 0000000000..94b742f49f --- /dev/null +++ b/pkg/collector/hyperv/hyperv_test.go @@ -0,0 +1,12 @@ +package hyperv_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/hyperv" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, hyperv.Name, hyperv.NewWithFlags) +} diff --git a/collector/iis.go b/pkg/collector/iis/iis.go similarity index 61% rename from collector/iis.go rename to pkg/collector/iis/iis.go index 275297560d..3ae6697c20 100644 --- a/collector/iis.go +++ b/pkg/collector/iis/iis.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package iis import ( "errors" @@ -10,6 +9,9 @@ import ( "sort" "strings" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" @@ -18,6 +20,7 @@ import ( ) const ( + Name = "iis" FlagIISSiteOldExclude = "collector.iis.site-blacklist" FlagIISSiteOldInclude = "collector.iis.site-whitelist" FlagIISAppOldExclude = "collector.iis.app-blacklist" @@ -29,22 +32,19 @@ const ( FlagIISAppInclude = "collector.iis.app-include" ) -var ( - oldSiteInclude *string - oldSiteExclude *string - oldAppInclude *string - oldAppExclude *string - - siteInclude *string - siteExclude *string - appInclude *string - appExclude *string +type Config struct { + SiteInclude string `yaml:"site_include"` + SiteExclude string `yaml:"site_exclude"` + AppInclude string `yaml:"app_include"` + AppExclude string `yaml:"app_exclude"` +} - siteIncludeSet bool - siteExcludeSet bool - appIncludeSet bool - appExcludeSet bool -) +var ConfigDefaults = Config{ + SiteInclude: ".+", + SiteExclude: "", + AppInclude: ".+", + AppExclude: "", +} type simple_version struct { major uint64 @@ -83,9 +83,24 @@ func getIISVersion(logger log.Logger) simple_version { } } -type IISCollector struct { +type collector struct { logger log.Logger + oldSiteInclude *string + oldSiteExclude *string + oldAppInclude *string + oldAppExclude *string + + siteInclude *string + siteExclude *string + appInclude *string + appExclude *string + + siteIncludeSet bool + siteExcludeSet bool + appIncludeSet bool + appExcludeSet bool + // Web Service CurrentAnonymousUsers *prometheus.Desc CurrentBlockedAsyncIORequests *prometheus.Desc @@ -219,706 +234,752 @@ type IISCollector struct { iis_version simple_version } -func newIISCollectorFlags(app *kingpin.Application) { - oldSiteInclude = app.Flag(FlagIISSiteOldInclude, "DEPRECATED: Use --collector.iis.site-include").Hidden().String() - oldSiteExclude = app.Flag(FlagIISSiteOldExclude, "DEPRECATED: Use --collector.iis.site-exclude").Hidden().String() - oldAppInclude = app.Flag(FlagIISAppOldInclude, "DEPRECATED: Use --collector.iis.app-include").Hidden().String() - oldAppExclude = app.Flag(FlagIISAppOldExclude, "DEPRECATED: Use --collector.iis.app-exclude").Hidden().String() +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + appInclude: &config.AppInclude, + appExclude: &config.AppExclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{ + oldSiteInclude: app.Flag(FlagIISSiteOldInclude, "DEPRECATED: Use --collector.iis.site-include").Hidden().String(), + oldSiteExclude: app.Flag(FlagIISSiteOldExclude, "DEPRECATED: Use --collector.iis.site-exclude").Hidden().String(), + oldAppInclude: app.Flag(FlagIISAppOldInclude, "DEPRECATED: Use --collector.iis.app-include").Hidden().String(), + oldAppExclude: app.Flag(FlagIISAppOldExclude, "DEPRECATED: Use --collector.iis.app-exclude").Hidden().String(), + } - siteInclude = app.Flag( + c.siteInclude = app.Flag( FlagIISSiteInclude, "Regexp of sites to include. Site name must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - siteIncludeSet = true + ).Default(".+").PreAction(func(_ *kingpin.ParseContext) error { + c.siteIncludeSet = true return nil }).String() - siteExclude = app.Flag( + c.siteExclude = app.Flag( FlagIISSiteExclude, "Regexp of sites to exclude. Site name must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - siteExcludeSet = true + ).Default("").PreAction(func(_ *kingpin.ParseContext) error { + c.siteExcludeSet = true return nil }).String() - appInclude = app.Flag( + c.appInclude = app.Flag( FlagIISAppInclude, "Regexp of apps to include. App name must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - appIncludeSet = true + ).Default(".+").PreAction(func(_ *kingpin.ParseContext) error { + c.appIncludeSet = true return nil }).String() - appExclude = app.Flag( + c.appExclude = app.Flag( FlagIISAppExclude, "Regexp of apps to include. App name must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - siteExcludeSet = true + ).Default("").PreAction(func(_ *kingpin.ParseContext) error { + c.siteExcludeSet = true return nil }).String() + + return c +} + +func (c *collector) GetName() string { + return Name } -func newIISCollector(logger log.Logger) (Collector, error) { - const subsystem = "iis" - logger = log.With(logger, "collector", subsystem) +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{ + "Web Service", + "APP_POOL_WAS", + "Web Service Cache", + "W3SVC_W3WP", + }, nil +} - if *oldSiteExclude != "" { - if !siteExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.iis.site-blacklist is DEPRECATED and will be removed in a future release, use --collector.iis.site-exclude") - *siteExclude = *oldSiteExclude +func (c *collector) Build() error { + if *c.oldSiteExclude != "" { + if !c.siteExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.iis.site-blacklist is DEPRECATED and will be removed in a future release, use --collector.iis.site-exclude") + *c.siteExclude = *c.oldSiteExclude } else { - return nil, errors.New("--collector.iis.site-blacklist and --collector.iis.site-exclude are mutually exclusive") + return errors.New("--collector.iis.site-blacklist and --collector.iis.site-exclude are mutually exclusive") } } - if *oldSiteInclude != "" { - if !siteIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.iis.site-whitelist is DEPRECATED and will be removed in a future release, use --collector.iis.site-include") - *siteInclude = *oldSiteInclude + if *c.oldSiteInclude != "" { + if !c.siteIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.iis.site-whitelist is DEPRECATED and will be removed in a future release, use --collector.iis.site-include") + *c.siteInclude = *c.oldSiteInclude } else { - return nil, errors.New("--collector.iis.site-whitelist and --collector.iis.site-include are mutually exclusive") + return errors.New("--collector.iis.site-whitelist and --collector.iis.site-include are mutually exclusive") } } - if *oldAppExclude != "" { - if !appExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.iis.app-blacklist is DEPRECATED and will be removed in a future release, use --collector.iis.app-exclude") - *appExclude = *oldAppExclude + if *c.oldAppExclude != "" { + if !c.appExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.iis.app-blacklist is DEPRECATED and will be removed in a future release, use --collector.iis.app-exclude") + *c.appExclude = *c.oldAppExclude } else { - return nil, errors.New("--collector.iis.app-blacklist and --collector.iis.app-exclude are mutually exclusive") + return errors.New("--collector.iis.app-blacklist and --collector.iis.app-exclude are mutually exclusive") } } - if *oldAppInclude != "" { - if !appIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.iis.app-whitelist is DEPRECATED and will be removed in a future release, use --collector.iis.app-include") - *appInclude = *oldAppInclude + if *c.oldAppInclude != "" { + if !c.appIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.iis.app-whitelist is DEPRECATED and will be removed in a future release, use --collector.iis.app-include") + *c.appInclude = *c.oldAppInclude } else { - return nil, errors.New("--collector.iis.app-whitelist and --collector.iis.app-include are mutually exclusive") + return errors.New("--collector.iis.app-whitelist and --collector.iis.app-include are mutually exclusive") } } - return &IISCollector{ - logger: logger, - iis_version: getIISVersion(logger), - - siteIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *siteInclude)), - siteExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *siteExclude)), - appIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *appInclude)), - appExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *appExclude)), - - // Web Service - CurrentAnonymousUsers: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_anonymous_users"), - "Number of users who currently have an anonymous connection using the Web service (WebService.CurrentAnonymousUsers)", - []string{"site"}, - nil, - ), - CurrentBlockedAsyncIORequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_blocked_async_io_requests"), - "Current requests temporarily blocked due to bandwidth throttling settings (WebService.CurrentBlockedAsyncIORequests)", - []string{"site"}, - nil, - ), - CurrentCGIRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_cgi_requests"), - "Current number of CGI requests being simultaneously processed by the Web service (WebService.CurrentCGIRequests)", - []string{"site"}, - nil, - ), - CurrentConnections: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_connections"), - "Current number of connections established with the Web service (WebService.CurrentConnections)", - []string{"site"}, - nil, - ), - CurrentISAPIExtensionRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_isapi_extension_requests"), - "Current number of ISAPI requests being simultaneously processed by the Web service (WebService.CurrentISAPIExtensionRequests)", - []string{"site"}, - nil, - ), - CurrentNonAnonymousUsers: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_non_anonymous_users"), - "Number of users who currently have a non-anonymous connection using the Web service (WebService.CurrentNonAnonymousUsers)", - []string{"site"}, - nil, - ), - ServiceUptime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "service_uptime"), - "Number of seconds the WebService is up (WebService.ServiceUptime)", - []string{"site"}, - nil, - ), - TotalBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "received_bytes_total"), - "Number of data bytes that have been received by the Web service (WebService.TotalBytesReceived)", - []string{"site"}, - nil, - ), - TotalBytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sent_bytes_total"), - "Number of data bytes that have been sent by the Web service (WebService.TotalBytesSent)", - []string{"site"}, - nil, - ), - TotalAnonymousUsers: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "anonymous_users_total"), - "Total number of users who established an anonymous connection with the Web service (WebService.TotalAnonymousUsers)", - []string{"site"}, - nil, - ), - TotalBlockedAsyncIORequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "blocked_async_io_requests_total"), - "Total requests temporarily blocked due to bandwidth throttling settings (WebService.TotalBlockedAsyncIORequests)", - []string{"site"}, - nil, - ), - TotalCGIRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cgi_requests_total"), - "Total CGI requests is the total number of CGI requests (WebService.TotalCGIRequests)", - []string{"site"}, - nil, - ), - TotalConnectionAttemptsAllInstances: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_attempts_all_instances_total"), - "Number of connections that have been attempted using the Web service (WebService.TotalConnectionAttemptsAllInstances)", - []string{"site"}, - nil, - ), - TotalRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "requests_total"), - "Number of HTTP requests (WebService.TotalRequests)", - []string{"site", "method"}, - nil, - ), - TotalFilesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "files_received_total"), - "Number of files received by the Web service (WebService.TotalFilesReceived)", - []string{"site"}, - nil, - ), - TotalFilesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "files_sent_total"), - "Number of files sent by the Web service (WebService.TotalFilesSent)", - []string{"site"}, - nil, - ), - TotalISAPIExtensionRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ipapi_extension_requests_total"), - "ISAPI Extension Requests received (WebService.TotalISAPIExtensionRequests)", - []string{"site"}, - nil, - ), - TotalLockedErrors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locked_errors_total"), - "Number of requests that couldn't be satisfied by the server because the requested resource was locked (WebService.TotalLockedErrors)", - []string{"site"}, - nil, - ), - TotalLogonAttempts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "logon_attempts_total"), - "Number of logons attempts to the Web Service (WebService.TotalLogonAttempts)", - []string{"site"}, - nil, - ), - TotalNonAnonymousUsers: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "non_anonymous_users_total"), - "Number of users who established a non-anonymous connection with the Web service (WebService.TotalNonAnonymousUsers)", - []string{"site"}, - nil, - ), - TotalNotFoundErrors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "not_found_errors_total"), - "Number of requests that couldn't be satisfied by the server because the requested document could not be found (WebService.TotalNotFoundErrors)", - []string{"site"}, - nil, - ), - TotalRejectedAsyncIORequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rejected_async_io_requests_total"), - "Requests rejected due to bandwidth throttling settings (WebService.TotalRejectedAsyncIORequests)", - []string{"site"}, - nil, - ), - - // APP_POOL_WAS - CurrentApplicationPoolState: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_application_pool_state"), - "The current status of the application pool (1 - Uninitialized, 2 - Initialized, 3 - Running, 4 - Disabling, 5 - Disabled, 6 - Shutdown Pending, 7 - Delete Pending) (CurrentApplicationPoolState)", - []string{"app", "state"}, - nil, - ), - CurrentApplicationPoolUptime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_application_pool_start_time"), - "The unix timestamp for the application pool start time (CurrentApplicationPoolUptime)", - []string{"app"}, - nil, - ), - CurrentWorkerProcesses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_worker_processes"), - "The current number of worker processes that are running in the application pool (CurrentWorkerProcesses)", - []string{"app"}, - nil, - ), - MaximumWorkerProcesses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "maximum_worker_processes"), - "The maximum number of worker processes that have been created for the application pool since Windows Process Activation Service (WAS) started (MaximumWorkerProcesses)", - []string{"app"}, - nil, - ), - RecentWorkerProcessFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "recent_worker_process_failures"), - "The number of times that worker processes for the application pool failed during the rapid-fail protection interval (RecentWorkerProcessFailures)", - []string{"app"}, - nil, - ), - TimeSinceLastWorkerProcessFailure: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "time_since_last_worker_process_failure"), - "The length of time, in seconds, since the last worker process failure occurred for the application pool (TimeSinceLastWorkerProcessFailure)", - []string{"app"}, - nil, - ), - TotalApplicationPoolRecycles: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_application_pool_recycles"), - "The number of times that the application pool has been recycled since Windows Process Activation Service (WAS) started (TotalApplicationPoolRecycles)", - []string{"app"}, - nil, - ), - TotalApplicationPoolUptime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_application_pool_start_time"), - "The unix timestamp for the application pool of when the Windows Process Activation Service (WAS) started (TotalApplicationPoolUptime)", - []string{"app"}, - nil, - ), - TotalWorkerProcessesCreated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_worker_processes_created"), - "The number of worker processes created for the application pool since Windows Process Activation Service (WAS) started (TotalWorkerProcessesCreated)", - []string{"app"}, - nil, - ), - TotalWorkerProcessFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_failures"), - "The number of times that worker processes have crashed since the application pool was started (TotalWorkerProcessFailures)", - []string{"app"}, - nil, - ), - TotalWorkerProcessPingFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_ping_failures"), - "The number of times that Windows Process Activation Service (WAS) did not receive a response to ping messages sent to a worker process (TotalWorkerProcessPingFailures)", - []string{"app"}, - nil, - ), - TotalWorkerProcessShutdownFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_shutdown_failures"), - "The number of times that Windows Process Activation Service (WAS) failed to shut down a worker process (TotalWorkerProcessShutdownFailures)", - []string{"app"}, - nil, - ), - TotalWorkerProcessStartupFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "total_worker_process_startup_failures"), - "The number of times that Windows Process Activation Service (WAS) failed to start a worker process (TotalWorkerProcessStartupFailures)", - []string{"app"}, - nil, - ), - - // W3SVC_W3WP - Threads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_threads"), - "Number of threads actively processing requests in the worker process", - []string{"app", "pid", "state"}, - nil, - ), - MaximumThreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_max_threads"), - "Maximum number of threads to which the thread pool can grow as needed", - []string{"app", "pid"}, - nil, - ), - RequestsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_requests_total"), - "Total number of HTTP requests served by the worker process", - []string{"app", "pid"}, - nil, - ), - RequestsActive: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_current_requests"), - "Current number of requests being processed by the worker process", - []string{"app", "pid"}, - nil, - ), - ActiveFlushedEntries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_cache_active_flushed_entries"), - "Number of file handles cached in user-mode that will be closed when all current transfers complete.", - []string{"app", "pid"}, - nil, - ), - CurrentFileCacheMemoryUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_memory_bytes"), - "Current number of bytes used by user-mode file cache", - []string{"app", "pid"}, - nil, - ), - MaximumFileCacheMemoryUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_max_memory_bytes"), - "Maximum number of bytes used by user-mode file cache", - []string{"app", "pid"}, - nil, - ), - FileCacheFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_flushes_total"), - "Total number of files removed from the user-mode cache", - []string{"app", "pid"}, - nil, - ), - FileCacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_queries_total"), - "Total file cache queries (hits + misses)", - []string{"app", "pid"}, - nil, - ), - FileCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_hits_total"), - "Total number of successful lookups in the user-mode file cache", - []string{"app", "pid"}, - nil, - ), - FilesCached: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_items"), - "Current number of files whose contents are present in user-mode cache", - []string{"app", "pid"}, - nil, - ), - FilesCachedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_items_total"), - "Total number of files whose contents were ever added to the user-mode cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - FilesFlushedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_file_cache_items_flushed_total"), - "Total number of file handles that have been removed from the user-mode cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - URICacheFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_flushes_total"), - "Total number of URI cache flushes (since service startup)", - []string{"app", "pid"}, - nil, - ), - URICacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_queries_total"), - "Total number of uri cache queries (hits + misses)", - []string{"app", "pid"}, - nil, - ), - URICacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_hits_total"), - "Total number of successful lookups in the user-mode URI cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - URIsCached: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_items"), - "Number of URI information blocks currently in the user-mode cache", - []string{"app", "pid"}, - nil, - ), - URIsCachedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_items_total"), - "Total number of URI information blocks added to the user-mode cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - URIsFlushedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_uri_cache_items_flushed_total"), - "The number of URI information blocks that have been removed from the user-mode cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - MetadataCached: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_items"), - "Number of metadata information blocks currently present in user-mode cache", - []string{"app", "pid"}, - nil, - ), - MetadataCacheFlushes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_flushes_total"), - "Total number of user-mode metadata cache flushes (since service startup)", - []string{"app", "pid"}, - nil, - ), - MetadataCacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_queries_total"), - "Total metadata cache queries (hits + misses)", - []string{"app", "pid"}, - nil, - ), - MetadataCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_hits_total"), - "Total number of successful lookups in the user-mode metadata cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - MetadataCachedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_items_cached_total"), - "Total number of metadata information blocks added to the user-mode cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - MetadataFlushedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_metadata_cache_items_flushed_total"), - "Total number of metadata information blocks removed from the user-mode cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - OutputCacheActiveFlushedItems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_active_flushed_items"), - "", - []string{"app", "pid"}, - nil, - ), - OutputCacheItems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_items"), - "Number of items current present in output cache", - []string{"app", "pid"}, - nil, - ), - OutputCacheMemoryUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_memory_bytes"), - "Current number of bytes used by output cache", - []string{"app", "pid"}, - nil, - ), - OutputCacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_queries_total"), - "Total number of output cache queries (hits + misses)", - []string{"app", "pid"}, - nil, - ), - OutputCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_hits_total"), - "Total number of successful lookups in output cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - OutputCacheFlushedItemsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_items_flushed_total"), - "Total number of items flushed from output cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - OutputCacheFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_output_cache_flushes_total"), - "Total number of flushes of output cache (since service startup)", - []string{"app", "pid"}, - nil, - ), - // W3SVC_W3WP_IIS8 - RequestErrorsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_request_errors_total"), - "Total number of requests that returned an error", - []string{"app", "pid", "status_code"}, - nil, - ), - WebSocketRequestsActive: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_current_websocket_requests"), - "", - []string{"app", "pid"}, - nil, - ), - WebSocketConnectionAttempts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_websocket_connection_attempts_total"), - "", - []string{"app", "pid"}, - nil, - ), - WebSocketConnectionsAccepted: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_websocket_connection_accepted_total"), - "", - []string{"app", "pid"}, - nil, - ), - WebSocketConnectionsRejected: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "worker_websocket_connection_rejected_total"), - "", - []string{"app", "pid"}, - nil, - ), - - // Web Service Cache - ServiceCache_ActiveFlushedEntries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_cache_active_flushed_entries"), - "Number of file handles cached that will be closed when all current transfers complete.", - nil, - nil, - ), - ServiceCache_CurrentFileCacheMemoryUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_memory_bytes"), - "Current number of bytes used by file cache", - nil, - nil, - ), - ServiceCache_MaximumFileCacheMemoryUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_max_memory_bytes"), - "Maximum number of bytes used by file cache", - nil, - nil, - ), - ServiceCache_FileCacheFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_flushes_total"), - "Total number of file cache flushes (since service startup)", - nil, - nil, - ), - ServiceCache_FileCacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_queries_total"), - "Total number of file cache queries (hits + misses)", - nil, - nil, - ), - ServiceCache_FileCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_hits_total"), - "Total number of successful lookups in the user-mode file cache", - nil, - nil, - ), - ServiceCache_FilesCached: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_items"), - "Current number of files whose contents are present in cache", - nil, - nil, - ), - ServiceCache_FilesCachedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_items_total"), - "Total number of files whose contents were ever added to the cache (since service startup)", - nil, - nil, - ), - ServiceCache_FilesFlushedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_file_cache_items_flushed_total"), - "Total number of file handles that have been removed from the cache (since service startup)", - nil, - nil, - ), - ServiceCache_URICacheFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_flushes_total"), - "Total number of URI cache flushes (since service startup)", - []string{"mode"}, - nil, - ), - ServiceCache_URICacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_queries_total"), - "Total number of uri cache queries (hits + misses)", - []string{"mode"}, - nil, - ), - ServiceCache_URICacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_hits_total"), - "Total number of successful lookups in the URI cache (since service startup)", - []string{"mode"}, - nil, - ), - ServiceCache_URIsCached: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_items"), - "Number of URI information blocks currently in the cache", - []string{"mode"}, - nil, - ), - ServiceCache_URIsCachedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_items_total"), - "Total number of URI information blocks added to the cache (since service startup)", - []string{"mode"}, - nil, - ), - ServiceCache_URIsFlushedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_uri_cache_items_flushed_total"), - "The number of URI information blocks that have been removed from the cache (since service startup)", - []string{"mode"}, - nil, - ), - ServiceCache_MetadataCached: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_items"), - "Number of metadata information blocks currently present in cache", - nil, - nil, - ), - ServiceCache_MetadataCacheFlushes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_flushes_total"), - "Total number of metadata cache flushes (since service startup)", - nil, - nil, - ), - ServiceCache_MetadataCacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_queries_total"), - "Total metadata cache queries (hits + misses)", - nil, - nil, - ), - ServiceCache_MetadataCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_hits_total"), - "Total number of successful lookups in the metadata cache (since service startup)", - nil, - nil, - ), - ServiceCache_MetadataCachedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_items_cached_total"), - "Total number of metadata information blocks added to the cache (since service startup)", - nil, - nil, - ), - ServiceCache_MetadataFlushedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_metadata_cache_items_flushed_total"), - "Total number of metadata information blocks removed from the cache (since service startup)", - nil, - nil, - ), - ServiceCache_OutputCacheActiveFlushedItems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_active_flushed_items"), - "", - nil, - nil, - ), - ServiceCache_OutputCacheItems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_items"), - "Number of items current present in output cache", - nil, - nil, - ), - ServiceCache_OutputCacheMemoryUsage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_memory_bytes"), - "Current number of bytes used by output cache", - nil, - nil, - ), - ServiceCache_OutputCacheQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_queries_total"), - "Total output cache queries (hits + misses)", - nil, - nil, - ), - ServiceCache_OutputCacheHitsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_hits_total"), - "Total number of successful lookups in output cache (since service startup)", - nil, - nil, - ), - ServiceCache_OutputCacheFlushedItemsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_items_flushed_total"), - "Total number of items flushed from output cache (since service startup)", - nil, - nil, - ), - ServiceCache_OutputCacheFlushesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "server_output_cache_flushes_total"), - "Total number of flushes of output cache (since service startup)", - nil, - nil, - ), - }, nil + c.iis_version = getIISVersion(c.logger) + + var err error + c.siteIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.siteInclude)) + if err != nil { + return err + } + + c.siteExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.siteExclude)) + if err != nil { + return err + } + + c.appIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.appInclude)) + if err != nil { + return err + } + + c.appExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.appExclude)) + if err != nil { + return err + } + + // Web Service + c.CurrentAnonymousUsers = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_anonymous_users"), + "Number of users who currently have an anonymous connection using the Web service (WebService.CurrentAnonymousUsers)", + []string{"site"}, + nil, + ) + c.CurrentBlockedAsyncIORequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_blocked_async_io_requests"), + "Current requests temporarily blocked due to bandwidth throttling settings (WebService.CurrentBlockedAsyncIORequests)", + []string{"site"}, + nil, + ) + c.CurrentCGIRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_cgi_requests"), + "Current number of CGI requests being simultaneously processed by the Web service (WebService.CurrentCGIRequests)", + []string{"site"}, + nil, + ) + c.CurrentConnections = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_connections"), + "Current number of connections established with the Web service (WebService.CurrentConnections)", + []string{"site"}, + nil, + ) + c.CurrentISAPIExtensionRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_isapi_extension_requests"), + "Current number of ISAPI requests being simultaneously processed by the Web service (WebService.CurrentISAPIExtensionRequests)", + []string{"site"}, + nil, + ) + c.CurrentNonAnonymousUsers = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_non_anonymous_users"), + "Number of users who currently have a non-anonymous connection using the Web service (WebService.CurrentNonAnonymousUsers)", + []string{"site"}, + nil, + ) + c.ServiceUptime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "service_uptime"), + "Number of seconds the WebService is up (WebService.ServiceUptime)", + []string{"site"}, + nil, + ) + c.TotalBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "received_bytes_total"), + "Number of data bytes that have been received by the Web service (WebService.TotalBytesReceived)", + []string{"site"}, + nil, + ) + c.TotalBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sent_bytes_total"), + "Number of data bytes that have been sent by the Web service (WebService.TotalBytesSent)", + []string{"site"}, + nil, + ) + c.TotalAnonymousUsers = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "anonymous_users_total"), + "Total number of users who established an anonymous connection with the Web service (WebService.TotalAnonymousUsers)", + []string{"site"}, + nil, + ) + c.TotalBlockedAsyncIORequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "blocked_async_io_requests_total"), + "Total requests temporarily blocked due to bandwidth throttling settings (WebService.TotalBlockedAsyncIORequests)", + []string{"site"}, + nil, + ) + c.TotalCGIRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cgi_requests_total"), + "Total CGI requests is the total number of CGI requests (WebService.TotalCGIRequests)", + []string{"site"}, + nil, + ) + c.TotalConnectionAttemptsAllInstances = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_attempts_all_instances_total"), + "Number of connections that have been attempted using the Web service (WebService.TotalConnectionAttemptsAllInstances)", + []string{"site"}, + nil, + ) + c.TotalRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "requests_total"), + "Number of HTTP requests (WebService.TotalRequests)", + []string{"site", "method"}, + nil, + ) + c.TotalFilesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "files_received_total"), + "Number of files received by the Web service (WebService.TotalFilesReceived)", + []string{"site"}, + nil, + ) + c.TotalFilesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "files_sent_total"), + "Number of files sent by the Web service (WebService.TotalFilesSent)", + []string{"site"}, + nil, + ) + c.TotalISAPIExtensionRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ipapi_extension_requests_total"), + "ISAPI Extension Requests received (WebService.TotalISAPIExtensionRequests)", + []string{"site"}, + nil, + ) + c.TotalLockedErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locked_errors_total"), + "Number of requests that couldn't be satisfied by the server because the requested resource was locked (WebService.TotalLockedErrors)", + []string{"site"}, + nil, + ) + c.TotalLogonAttempts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "logon_attempts_total"), + "Number of logons attempts to the Web Service (WebService.TotalLogonAttempts)", + []string{"site"}, + nil, + ) + c.TotalNonAnonymousUsers = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "non_anonymous_users_total"), + "Number of users who established a non-anonymous connection with the Web service (WebService.TotalNonAnonymousUsers)", + []string{"site"}, + nil, + ) + c.TotalNotFoundErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "not_found_errors_total"), + "Number of requests that couldn't be satisfied by the server because the requested document could not be found (WebService.TotalNotFoundErrors)", + []string{"site"}, + nil, + ) + c.TotalRejectedAsyncIORequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rejected_async_io_requests_total"), + "Requests rejected due to bandwidth throttling settings (WebService.TotalRejectedAsyncIORequests)", + []string{"site"}, + nil, + ) + + // APP_POOL_WAS + c.CurrentApplicationPoolState = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_application_pool_state"), + "The current status of the application pool (1 - Uninitialized, 2 - Initialized, 3 - Running, 4 - Disabling, 5 - Disabled, 6 - Shutdown Pending, 7 - Delete Pending) (CurrentApplicationPoolState)", + []string{"app", "state"}, + nil, + ) + c.CurrentApplicationPoolUptime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_application_pool_start_time"), + "The unix timestamp for the application pool start time (CurrentApplicationPoolUptime)", + []string{"app"}, + nil, + ) + c.CurrentWorkerProcesses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_worker_processes"), + "The current number of worker processes that are running in the application pool (CurrentWorkerProcesses)", + []string{"app"}, + nil, + ) + c.MaximumWorkerProcesses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "maximum_worker_processes"), + "The maximum number of worker processes that have been created for the application pool since Windows Process Activation Service (WAS) started (MaximumWorkerProcesses)", + []string{"app"}, + nil, + ) + c.RecentWorkerProcessFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "recent_worker_process_failures"), + "The number of times that worker processes for the application pool failed during the rapid-fail protection interval (RecentWorkerProcessFailures)", + []string{"app"}, + nil, + ) + c.TimeSinceLastWorkerProcessFailure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "time_since_last_worker_process_failure"), + "The length of time, in seconds, since the last worker process failure occurred for the application pool (TimeSinceLastWorkerProcessFailure)", + []string{"app"}, + nil, + ) + c.TotalApplicationPoolRecycles = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_application_pool_recycles"), + "The number of times that the application pool has been recycled since Windows Process Activation Service (WAS) started (TotalApplicationPoolRecycles)", + []string{"app"}, + nil, + ) + c.TotalApplicationPoolUptime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_application_pool_start_time"), + "The unix timestamp for the application pool of when the Windows Process Activation Service (WAS) started (TotalApplicationPoolUptime)", + []string{"app"}, + nil, + ) + c.TotalWorkerProcessesCreated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_worker_processes_created"), + "The number of worker processes created for the application pool since Windows Process Activation Service (WAS) started (TotalWorkerProcessesCreated)", + []string{"app"}, + nil, + ) + c.TotalWorkerProcessFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_failures"), + "The number of times that worker processes have crashed since the application pool was started (TotalWorkerProcessFailures)", + []string{"app"}, + nil, + ) + c.TotalWorkerProcessPingFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_ping_failures"), + "The number of times that Windows Process Activation Service (WAS) did not receive a response to ping messages sent to a worker process (TotalWorkerProcessPingFailures)", + []string{"app"}, + nil, + ) + c.TotalWorkerProcessShutdownFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_shutdown_failures"), + "The number of times that Windows Process Activation Service (WAS) failed to shut down a worker process (TotalWorkerProcessShutdownFailures)", + []string{"app"}, + nil, + ) + c.TotalWorkerProcessStartupFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "total_worker_process_startup_failures"), + "The number of times that Windows Process Activation Service (WAS) failed to start a worker process (TotalWorkerProcessStartupFailures)", + []string{"app"}, + nil, + ) + + // W3SVC_W3WP + c.Threads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_threads"), + "Number of threads actively processing requests in the worker process", + []string{"app", "pid", "state"}, + nil, + ) + c.MaximumThreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_max_threads"), + "Maximum number of threads to which the thread pool can grow as needed", + []string{"app", "pid"}, + nil, + ) + c.RequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_requests_total"), + "Total number of HTTP requests served by the worker process", + []string{"app", "pid"}, + nil, + ) + c.RequestsActive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_current_requests"), + "Current number of requests being processed by the worker process", + []string{"app", "pid"}, + nil, + ) + c.ActiveFlushedEntries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_cache_active_flushed_entries"), + "Number of file handles cached in user-mode that will be closed when all current transfers complete.", + []string{"app", "pid"}, + nil, + ) + c.CurrentFileCacheMemoryUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_memory_bytes"), + "Current number of bytes used by user-mode file cache", + []string{"app", "pid"}, + nil, + ) + c.MaximumFileCacheMemoryUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_max_memory_bytes"), + "Maximum number of bytes used by user-mode file cache", + []string{"app", "pid"}, + nil, + ) + c.FileCacheFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_flushes_total"), + "Total number of files removed from the user-mode cache", + []string{"app", "pid"}, + nil, + ) + c.FileCacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_queries_total"), + "Total file cache queries (hits + misses)", + []string{"app", "pid"}, + nil, + ) + c.FileCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_hits_total"), + "Total number of successful lookups in the user-mode file cache", + []string{"app", "pid"}, + nil, + ) + c.FilesCached = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items"), + "Current number of files whose contents are present in user-mode cache", + []string{"app", "pid"}, + nil, + ) + c.FilesCachedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items_total"), + "Total number of files whose contents were ever added to the user-mode cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.FilesFlushedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_file_cache_items_flushed_total"), + "Total number of file handles that have been removed from the user-mode cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.URICacheFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_flushes_total"), + "Total number of URI cache flushes (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.URICacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_queries_total"), + "Total number of uri cache queries (hits + misses)", + []string{"app", "pid"}, + nil, + ) + c.URICacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_hits_total"), + "Total number of successful lookups in the user-mode URI cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.URIsCached = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items"), + "Number of URI information blocks currently in the user-mode cache", + []string{"app", "pid"}, + nil, + ) + c.URIsCachedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items_total"), + "Total number of URI information blocks added to the user-mode cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.URIsFlushedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_uri_cache_items_flushed_total"), + "The number of URI information blocks that have been removed from the user-mode cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.MetadataCached = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items"), + "Number of metadata information blocks currently present in user-mode cache", + []string{"app", "pid"}, + nil, + ) + c.MetadataCacheFlushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_flushes_total"), + "Total number of user-mode metadata cache flushes (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.MetadataCacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_queries_total"), + "Total metadata cache queries (hits + misses)", + []string{"app", "pid"}, + nil, + ) + c.MetadataCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_hits_total"), + "Total number of successful lookups in the user-mode metadata cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.MetadataCachedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items_cached_total"), + "Total number of metadata information blocks added to the user-mode cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.MetadataFlushedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_metadata_cache_items_flushed_total"), + "Total number of metadata information blocks removed from the user-mode cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheActiveFlushedItems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_active_flushed_items"), + "", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheItems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items"), + "Number of items current present in output cache", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheMemoryUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_memory_bytes"), + "Current number of bytes used by output cache", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_queries_total"), + "Total number of output cache queries (hits + misses)", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_hits_total"), + "Total number of successful lookups in output cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheFlushedItemsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_items_flushed_total"), + "Total number of items flushed from output cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c.OutputCacheFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_output_cache_flushes_total"), + "Total number of flushes of output cache (since service startup)", + []string{"app", "pid"}, + nil, + ) + c. // W3SVC_W3WP_IIS8 + RequestErrorsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_request_errors_total"), + "Total number of requests that returned an error", + []string{"app", "pid", "status_code"}, + nil, + ) + c.WebSocketRequestsActive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_current_websocket_requests"), + "", + []string{"app", "pid"}, + nil, + ) + c.WebSocketConnectionAttempts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_attempts_total"), + "", + []string{"app", "pid"}, + nil, + ) + c.WebSocketConnectionsAccepted = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_accepted_total"), + "", + []string{"app", "pid"}, + nil, + ) + c.WebSocketConnectionsRejected = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "worker_websocket_connection_rejected_total"), + "", + []string{"app", "pid"}, + nil, + ) + + // Web Service Cache + c.ServiceCache_ActiveFlushedEntries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_cache_active_flushed_entries"), + "Number of file handles cached that will be closed when all current transfers complete.", + nil, + nil, + ) + c.ServiceCache_CurrentFileCacheMemoryUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_memory_bytes"), + "Current number of bytes used by file cache", + nil, + nil, + ) + c.ServiceCache_MaximumFileCacheMemoryUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_max_memory_bytes"), + "Maximum number of bytes used by file cache", + nil, + nil, + ) + c.ServiceCache_FileCacheFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_flushes_total"), + "Total number of file cache flushes (since service startup)", + nil, + nil, + ) + c.ServiceCache_FileCacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_queries_total"), + "Total number of file cache queries (hits + misses)", + nil, + nil, + ) + c.ServiceCache_FileCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_hits_total"), + "Total number of successful lookups in the user-mode file cache", + nil, + nil, + ) + c.ServiceCache_FilesCached = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_items"), + "Current number of files whose contents are present in cache", + nil, + nil, + ) + c.ServiceCache_FilesCachedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_items_total"), + "Total number of files whose contents were ever added to the cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_FilesFlushedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_file_cache_items_flushed_total"), + "Total number of file handles that have been removed from the cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_URICacheFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_flushes_total"), + "Total number of URI cache flushes (since service startup)", + []string{"mode"}, + nil, + ) + c.ServiceCache_URICacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_queries_total"), + "Total number of uri cache queries (hits + misses)", + []string{"mode"}, + nil, + ) + c.ServiceCache_URICacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_hits_total"), + "Total number of successful lookups in the URI cache (since service startup)", + []string{"mode"}, + nil, + ) + c.ServiceCache_URIsCached = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_items"), + "Number of URI information blocks currently in the cache", + []string{"mode"}, + nil, + ) + c.ServiceCache_URIsCachedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_items_total"), + "Total number of URI information blocks added to the cache (since service startup)", + []string{"mode"}, + nil, + ) + c.ServiceCache_URIsFlushedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_uri_cache_items_flushed_total"), + "The number of URI information blocks that have been removed from the cache (since service startup)", + []string{"mode"}, + nil, + ) + c.ServiceCache_MetadataCached = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_items"), + "Number of metadata information blocks currently present in cache", + nil, + nil, + ) + c.ServiceCache_MetadataCacheFlushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_flushes_total"), + "Total number of metadata cache flushes (since service startup)", + nil, + nil, + ) + c.ServiceCache_MetadataCacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_queries_total"), + "Total metadata cache queries (hits + misses)", + nil, + nil, + ) + c.ServiceCache_MetadataCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_hits_total"), + "Total number of successful lookups in the metadata cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_MetadataCachedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_items_cached_total"), + "Total number of metadata information blocks added to the cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_MetadataFlushedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_metadata_cache_items_flushed_total"), + "Total number of metadata information blocks removed from the cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_OutputCacheActiveFlushedItems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_active_flushed_items"), + "", + nil, + nil, + ) + c.ServiceCache_OutputCacheItems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_items"), + "Number of items current present in output cache", + nil, + nil, + ) + c.ServiceCache_OutputCacheMemoryUsage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_memory_bytes"), + "Current number of bytes used by output cache", + nil, + nil, + ) + c.ServiceCache_OutputCacheQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_queries_total"), + "Total output cache queries (hits + misses)", + nil, + nil, + ) + c.ServiceCache_OutputCacheHitsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_hits_total"), + "Total number of successful lookups in output cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_OutputCacheFlushedItemsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_items_flushed_total"), + "Total number of items flushed from output cache (since service startup)", + nil, + nil, + ) + c.ServiceCache_OutputCacheFlushesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "server_output_cache_flushes_total"), + "Total number of flushes of output cache (since service startup)", + nil, + nil, + ) + + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *IISCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectWebService(ctx, ch); err != nil { _ = level.Error(c.logger).Log("msg", "failed collecting iis metrics", "desc", desc, "err", err) return err @@ -1022,7 +1083,7 @@ func dedupIISNames[V hasGetIISName](services []V) map[string]V { return services[i].getIISName() < services[j].getIISName() }) - var webServiceDeDuplicated = make(map[string]V) + webServiceDeDuplicated := make(map[string]V) // Use map to deduplicate IIS entries for _, entry := range services { @@ -1032,9 +1093,9 @@ func dedupIISNames[V hasGetIISName](services []V) map[string]V { return webServiceDeDuplicated } -func (c *IISCollector) collectWebService(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectWebService(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var webService []perflibWebService - if err := unmarshalObject(ctx.perfObjects["Web Service"], &webService, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["Web Service"], &webService, c.logger); err != nil { return nil, err } @@ -1318,9 +1379,9 @@ var applicationStates = map[uint32]string{ 7: "Delete Pending", } -func (c *IISCollector) collectAPP_POOL_WAS(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectAPP_POOL_WAS(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var APP_POOL_WAS []perflibAPP_POOL_WAS - if err := unmarshalObject(ctx.perfObjects["APP_POOL_WAS"], &APP_POOL_WAS, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["APP_POOL_WAS"], &APP_POOL_WAS, c.logger); err != nil { return nil, err } @@ -1495,9 +1556,9 @@ type perflibW3SVC_W3WP_IIS8 struct { WebSocketConnectionsRejected float64 `perflib:"WebSocket Connections Rejected / Sec"` } -func (c *IISCollector) collectW3SVC_W3WP(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectW3SVC_W3WP(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var W3SVC_W3WP []perflibW3SVC_W3WP - if err := unmarshalObject(ctx.perfObjects["W3SVC_W3WP"], &W3SVC_W3WP, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["W3SVC_W3WP"], &W3SVC_W3WP, c.logger); err != nil { return nil, err } @@ -1756,7 +1817,7 @@ func (c *IISCollector) collectW3SVC_W3WP(ctx *ScrapeContext, ch chan<- prometheu if c.iis_version.major >= 8 { var W3SVC_W3WP_IIS8 []perflibW3SVC_W3WP_IIS8 - if err := unmarshalObject(ctx.perfObjects["W3SVC_W3WP"], &W3SVC_W3WP_IIS8, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["W3SVC_W3WP"], &W3SVC_W3WP_IIS8, c.logger); err != nil { return nil, err } @@ -1893,9 +1954,9 @@ type perflibWebServiceCache struct { ServiceCache_OutputCacheQueriesTotal float64 } -func (c *IISCollector) collectWebServiceCache(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectWebServiceCache(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var WebServiceCache []perflibWebServiceCache - if err := unmarshalObject(ctx.perfObjects["Web Service Cache"], &WebServiceCache, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["Web Service Cache"], &WebServiceCache, c.logger); err != nil { return nil, err } diff --git a/pkg/collector/iis/iis_bench_test.go b/pkg/collector/iis/iis_bench_test.go new file mode 100644 index 0000000000..6ee05dfd8c --- /dev/null +++ b/pkg/collector/iis/iis_bench_test.go @@ -0,0 +1,12 @@ +package iis_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/iis" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, iis.Name, iis.NewWithFlags) +} diff --git a/collector/iis_test.go b/pkg/collector/iis/iis_test.go similarity index 88% rename from collector/iis_test.go rename to pkg/collector/iis/iis_test.go index 1ad4f2a8f4..7fed2fc195 100644 --- a/collector/iis_test.go +++ b/pkg/collector/iis/iis_test.go @@ -1,14 +1,10 @@ -package collector +package iis import ( "reflect" "testing" ) -func BenchmarkIISCollector(b *testing.B) { - benchmarkCollector(b, "iis", newIISCollector) -} - func TestIISDeduplication(t *testing.T) { start := []perflibAPP_POOL_WAS{ { @@ -32,7 +28,7 @@ func TestIISDeduplication(t *testing.T) { Frequency_Object: 5, }, } - var expected = make(map[string]perflibAPP_POOL_WAS) + expected := make(map[string]perflibAPP_POOL_WAS) // Should be deduplicated from "foo#2" expected["foo"] = perflibAPP_POOL_WAS{Name: "foo#2", Frequency_Object: 3} // Map key should have suffix stripped, but struct name field should be unchanged diff --git a/pkg/collector/logical_disk/logical_disk.go b/pkg/collector/logical_disk/logical_disk.go new file mode 100644 index 0000000000..dea96811e0 --- /dev/null +++ b/pkg/collector/logical_disk/logical_disk.go @@ -0,0 +1,431 @@ +//go:build windows + +package logical_disk + +import ( + "errors" + "fmt" + "regexp" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + Name = "logical_disk" + FlagLogicalDiskVolumeOldExclude = "collector.logical_disk.volume-blacklist" + FlagLogicalDiskVolumeOldInclude = "collector.logical_disk.volume-whitelist" + + FlagLogicalDiskVolumeExclude = "collector.logical_disk.volume-exclude" + FlagLogicalDiskVolumeInclude = "collector.logical_disk.volume-include" +) + +type Config struct { + VolumeInclude string `yaml:"volume_include"` + VolumeExclude string `yaml:"volume_exclude"` +} + +var ConfigDefaults = Config{ + VolumeInclude: ".+", + VolumeExclude: "", +} + +// A collector is a Prometheus collector for perflib logicalDisk metrics +type collector struct { + logger log.Logger + + volumeOldInclude *string + volumeOldExclude *string + + volumeInclude *string + volumeExclude *string + + volumeIncludeSet bool + volumeExcludeSet bool + + RequestsQueued *prometheus.Desc + AvgReadQueue *prometheus.Desc + AvgWriteQueue *prometheus.Desc + ReadBytesTotal *prometheus.Desc + ReadsTotal *prometheus.Desc + WriteBytesTotal *prometheus.Desc + WritesTotal *prometheus.Desc + ReadTime *prometheus.Desc + WriteTime *prometheus.Desc + TotalSpace *prometheus.Desc + FreeSpace *prometheus.Desc + IdleTime *prometheus.Desc + SplitIOs *prometheus.Desc + ReadLatency *prometheus.Desc + WriteLatency *prometheus.Desc + ReadWriteLatency *prometheus.Desc + + volumeIncludePattern *regexp.Regexp + volumeExcludePattern *regexp.Regexp +} + +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + volumeExclude: &config.VolumeExclude, + volumeInclude: &config.VolumeInclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{} + + c.volumeInclude = app.Flag( + FlagLogicalDiskVolumeInclude, + "Regexp of volumes to include. Volume name must both match include and not match exclude to be included.", + ).Default(ConfigDefaults.VolumeInclude).PreAction(func(_ *kingpin.ParseContext) error { + c.volumeIncludeSet = true + return nil + }).String() + + c.volumeExclude = app.Flag( + FlagLogicalDiskVolumeExclude, + "Regexp of volumes to exclude. Volume name must both match include and not match exclude to be included.", + ).Default(ConfigDefaults.VolumeExclude).PreAction(func(_ *kingpin.ParseContext) error { + c.volumeExcludeSet = true + return nil + }).String() + + c.volumeOldInclude = app.Flag( + FlagLogicalDiskVolumeOldInclude, + "DEPRECATED: Use --collector.logical_disk.volume-include", + ).Hidden().String() + c.volumeOldExclude = app.Flag( + FlagLogicalDiskVolumeOldExclude, + "DEPRECATED: Use --collector.logical_disk.volume-exclude", + ).Hidden().String() + + return c +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"LogicalDisk"}, nil +} + +func (c *collector) Build() error { + if *c.volumeOldExclude != "" { + if !c.volumeExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.logical_disk.volume-blacklist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-exclude") + *c.volumeExclude = *c.volumeOldExclude + } else { + return errors.New("--collector.logical_disk.volume-blacklist and --collector.logical_disk.volume-exclude are mutually exclusive") + } + } + if *c.volumeOldInclude != "" { + if !c.volumeIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.logical_disk.volume-whitelist is DEPRECATED and will be removed in a future release, use --collector.logical_disk.volume-include") + *c.volumeInclude = *c.volumeOldInclude + } else { + return errors.New("--collector.logical_disk.volume-whitelist and --collector.logical_disk.volume-include are mutually exclusive") + } + } + + c.RequestsQueued = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "requests_queued"), + "The number of requests queued to the disk (LogicalDisk.CurrentDiskQueueLength)", + []string{"volume"}, + nil, + ) + + c.AvgReadQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "avg_read_requests_queued"), + "Average number of read requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskReadQueueLength)", + []string{"volume"}, + nil, + ) + + c.AvgWriteQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "avg_write_requests_queued"), + "Average number of write requests that were queued for the selected disk during the sample interval (LogicalDisk.AvgDiskWriteQueueLength)", + []string{"volume"}, + nil, + ) + + c.ReadBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_bytes_total"), + "The number of bytes transferred from the disk during read operations (LogicalDisk.DiskReadBytesPerSec)", + []string{"volume"}, + nil, + ) + + c.ReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "reads_total"), + "The number of read operations on the disk (LogicalDisk.DiskReadsPerSec)", + []string{"volume"}, + nil, + ) + + c.WriteBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_bytes_total"), + "The number of bytes transferred to the disk during write operations (LogicalDisk.DiskWriteBytesPerSec)", + []string{"volume"}, + nil, + ) + + c.WritesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "writes_total"), + "The number of write operations on the disk (LogicalDisk.DiskWritesPerSec)", + []string{"volume"}, + nil, + ) + + c.ReadTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_seconds_total"), + "Seconds that the disk was busy servicing read requests (LogicalDisk.PercentDiskReadTime)", + []string{"volume"}, + nil, + ) + + c.WriteTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_seconds_total"), + "Seconds that the disk was busy servicing write requests (LogicalDisk.PercentDiskWriteTime)", + []string{"volume"}, + nil, + ) + + c.FreeSpace = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "free_bytes"), + "Free space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace)", + []string{"volume"}, + nil, + ) + + c.TotalSpace = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "size_bytes"), + "Total space in bytes, updates every 10-15 min (LogicalDisk.PercentFreeSpace_Base)", + []string{"volume"}, + nil, + ) + + c.IdleTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "idle_seconds_total"), + "Seconds that the disk was idle (LogicalDisk.PercentIdleTime)", + []string{"volume"}, + nil, + ) + + c.SplitIOs = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "split_ios_total"), + "The number of I/Os to the disk were split into multiple I/Os (LogicalDisk.SplitIOPerSec)", + []string{"volume"}, + nil, + ) + + c.ReadLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_latency_seconds_total"), + "Shows the average time, in seconds, of a read operation from the disk (LogicalDisk.AvgDiskSecPerRead)", + []string{"volume"}, + nil, + ) + + c.WriteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_latency_seconds_total"), + "Shows the average time, in seconds, of a write operation to the disk (LogicalDisk.AvgDiskSecPerWrite)", + []string{"volume"}, + nil, + ) + + c.ReadWriteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_write_latency_seconds_total"), + "Shows the time, in seconds, of the average disk transfer (LogicalDisk.AvgDiskSecPerTransfer)", + []string{"volume"}, + nil, + ) + + var err error + c.volumeIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeInclude)) + if err != nil { + return err + } + + c.volumeExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.volumeExclude)) + if err != nil { + return err + } + + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting logical_disk metrics", "desc", desc, "err", err) + return err + } + return nil +} + +// Win32_PerfRawData_PerfDisk_LogicalDisk docs: +// - https://msdn.microsoft.com/en-us/windows/hardware/aa394307(v=vs.71) - Win32_PerfRawData_PerfDisk_LogicalDisk class +// - https://msdn.microsoft.com/en-us/library/ms803973.aspx - LogicalDisk object reference +type logicalDisk struct { + Name string + CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` + AvgDiskReadQueueLength float64 `perflib:"Avg. Disk Read Queue Length"` + AvgDiskWriteQueueLength float64 `perflib:"Avg. Disk Write Queue Length"` + DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"` + DiskReadsPerSec float64 `perflib:"Disk Reads/sec"` + DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"` + DiskWritesPerSec float64 `perflib:"Disk Writes/sec"` + PercentDiskReadTime float64 `perflib:"% Disk Read Time"` + PercentDiskWriteTime float64 `perflib:"% Disk Write Time"` + PercentFreeSpace float64 `perflib:"% Free Space_Base"` + PercentFreeSpace_Base float64 `perflib:"Free Megabytes"` + PercentIdleTime float64 `perflib:"% Idle Time"` + SplitIOPerSec float64 `perflib:"Split IO/Sec"` + AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"` + AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"` + AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"` +} + +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []logicalDisk + if err := perflib.UnmarshalObject(ctx.PerfObjects["LogicalDisk"], &dst, c.logger); err != nil { + return nil, err + } + + for _, volume := range dst { + if volume.Name == "_Total" || + c.volumeExcludePattern.MatchString(volume.Name) || + !c.volumeIncludePattern.MatchString(volume.Name) { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.RequestsQueued, + prometheus.GaugeValue, + volume.CurrentDiskQueueLength, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvgReadQueue, + prometheus.GaugeValue, + volume.AvgDiskReadQueueLength*perflib.TicksToSecondScaleFactor, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.AvgWriteQueue, + prometheus.GaugeValue, + volume.AvgDiskWriteQueueLength*perflib.TicksToSecondScaleFactor, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadBytesTotal, + prometheus.CounterValue, + volume.DiskReadBytesPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadsTotal, + prometheus.CounterValue, + volume.DiskReadsPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteBytesTotal, + prometheus.CounterValue, + volume.DiskWriteBytesPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WritesTotal, + prometheus.CounterValue, + volume.DiskWritesPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadTime, + prometheus.CounterValue, + volume.PercentDiskReadTime, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteTime, + prometheus.CounterValue, + volume.PercentDiskWriteTime, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FreeSpace, + prometheus.GaugeValue, + volume.PercentFreeSpace_Base*1024*1024, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalSpace, + prometheus.GaugeValue, + volume.PercentFreeSpace*1024*1024, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.IdleTime, + prometheus.CounterValue, + volume.PercentIdleTime, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.SplitIOs, + prometheus.CounterValue, + volume.SplitIOPerSec, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadLatency, + prometheus.CounterValue, + volume.AvgDiskSecPerRead*perflib.TicksToSecondScaleFactor, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteLatency, + prometheus.CounterValue, + volume.AvgDiskSecPerWrite*perflib.TicksToSecondScaleFactor, + volume.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadWriteLatency, + prometheus.CounterValue, + volume.AvgDiskSecPerTransfer*perflib.TicksToSecondScaleFactor, + volume.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/logical_disk/logical_disk_test.go b/pkg/collector/logical_disk/logical_disk_test.go new file mode 100644 index 0000000000..324cb6ca0d --- /dev/null +++ b/pkg/collector/logical_disk/logical_disk_test.go @@ -0,0 +1,16 @@ +package logical_disk_test + +import ( + "testing" + + "github.com/alecthomas/kingpin/v2" + "github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // Whitelist is not set in testing context (kingpin flags not parsed), causing the collector to skip all disks. + localVolumeInclude := ".+" + kingpin.CommandLine.GetArg(logical_disk.FlagLogicalDiskVolumeInclude).StringVar(&localVolumeInclude) + testutils.FuncBenchmarkCollector(b, "logical_disk", logical_disk.NewWithFlags) +} diff --git a/collector/logon.go b/pkg/collector/logon/logon.go similarity index 71% rename from collector/logon.go rename to pkg/collector/logon/logon.go index f8fe25cea8..0ffb329721 100644 --- a/collector/logon.go +++ b/pkg/collector/logon/logon.go @@ -1,42 +1,67 @@ //go:build windows -// +build windows -package collector +package logon import ( "errors" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A LogonCollector is a Prometheus collector for WMI metrics -type LogonCollector struct { - logger log.Logger +const Name = "logon" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI metrics +type collector struct { + logger log.Logger + LogonType *prometheus.Desc } -// newLogonCollector ... -func newLogonCollector(logger log.Logger) (Collector, error) { - const subsystem = "logon" +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} - return &LogonCollector{ - logger: log.With(logger, "collector", subsystem), +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} - LogonType: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "logon_type"), - "Number of active logon sessions (LogonSession.LogonType)", - []string{"status"}, - nil, - ), - }, nil +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.LogonType = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "logon_type"), + "Number of active logon sessions (LogonSession.LogonType)", + []string{"status"}, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *LogonCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err) return err @@ -50,9 +75,9 @@ type Win32_LogonSession struct { LogonType uint32 } -func (c *LogonCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_LogonSession - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/logon/logon_test.go b/pkg/collector/logon/logon_test.go new file mode 100644 index 0000000000..4bd9441360 --- /dev/null +++ b/pkg/collector/logon/logon_test.go @@ -0,0 +1,13 @@ +package logon_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/logon" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, logon.Name, logon.NewWithFlags) +} diff --git a/pkg/collector/map.go b/pkg/collector/map.go new file mode 100644 index 0000000000..fc5c7e7790 --- /dev/null +++ b/pkg/collector/map.go @@ -0,0 +1,118 @@ +package collector + +import ( + "github.com/prometheus-community/windows_exporter/pkg/collector/ad" + "github.com/prometheus-community/windows_exporter/pkg/collector/adcs" + "github.com/prometheus-community/windows_exporter/pkg/collector/adfs" + "github.com/prometheus-community/windows_exporter/pkg/collector/cache" + "github.com/prometheus-community/windows_exporter/pkg/collector/container" + "github.com/prometheus-community/windows_exporter/pkg/collector/cpu" + "github.com/prometheus-community/windows_exporter/pkg/collector/cpu_info" + "github.com/prometheus-community/windows_exporter/pkg/collector/cs" + "github.com/prometheus-community/windows_exporter/pkg/collector/dfsr" + "github.com/prometheus-community/windows_exporter/pkg/collector/dhcp" + "github.com/prometheus-community/windows_exporter/pkg/collector/diskdrive" + "github.com/prometheus-community/windows_exporter/pkg/collector/dns" + "github.com/prometheus-community/windows_exporter/pkg/collector/exchange" + "github.com/prometheus-community/windows_exporter/pkg/collector/fsrmquota" + "github.com/prometheus-community/windows_exporter/pkg/collector/hyperv" + "github.com/prometheus-community/windows_exporter/pkg/collector/iis" + "github.com/prometheus-community/windows_exporter/pkg/collector/logical_disk" + "github.com/prometheus-community/windows_exporter/pkg/collector/logon" + "github.com/prometheus-community/windows_exporter/pkg/collector/memory" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_cluster" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_network" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_node" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resource" + "github.com/prometheus-community/windows_exporter/pkg/collector/mscluster_resourcegroup" + "github.com/prometheus-community/windows_exporter/pkg/collector/msmq" + "github.com/prometheus-community/windows_exporter/pkg/collector/mssql" + "github.com/prometheus-community/windows_exporter/pkg/collector/net" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrexceptions" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrinterop" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrjit" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrloading" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrlocksandthreads" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrmemory" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrremoting" + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrsecurity" + "github.com/prometheus-community/windows_exporter/pkg/collector/nps" + "github.com/prometheus-community/windows_exporter/pkg/collector/os" + "github.com/prometheus-community/windows_exporter/pkg/collector/physical_disk" + "github.com/prometheus-community/windows_exporter/pkg/collector/process" + "github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx" + "github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task" + "github.com/prometheus-community/windows_exporter/pkg/collector/service" + "github.com/prometheus-community/windows_exporter/pkg/collector/smtp" + "github.com/prometheus-community/windows_exporter/pkg/collector/system" + "github.com/prometheus-community/windows_exporter/pkg/collector/tcp" + "github.com/prometheus-community/windows_exporter/pkg/collector/teradici_pcoip" + "github.com/prometheus-community/windows_exporter/pkg/collector/terminal_services" + "github.com/prometheus-community/windows_exporter/pkg/collector/textfile" + "github.com/prometheus-community/windows_exporter/pkg/collector/thermalzone" + "github.com/prometheus-community/windows_exporter/pkg/collector/time" + "github.com/prometheus-community/windows_exporter/pkg/collector/vmware" + "github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast" + "github.com/prometheus-community/windows_exporter/pkg/types" + + "golang.org/x/exp/maps" +) + +var Map = map[string]types.CollectorBuilderWithFlags{ + ad.Name: ad.NewWithFlags, + adcs.Name: adcs.NewWithFlags, + adfs.Name: adfs.NewWithFlags, + cache.Name: cache.NewWithFlags, + container.Name: container.NewWithFlags, + cpu.Name: cpu.NewWithFlags, + cpu_info.Name: cpu_info.NewWithFlags, + cs.Name: cs.NewWithFlags, + dfsr.Name: dfsr.NewWithFlags, + dhcp.Name: dhcp.NewWithFlags, + diskdrive.Name: diskdrive.NewWithFlags, + dns.Name: dns.NewWithFlags, + exchange.Name: exchange.NewWithFlags, + fsrmquota.Name: fsrmquota.NewWithFlags, + hyperv.Name: hyperv.NewWithFlags, + iis.Name: iis.NewWithFlags, + logical_disk.Name: logical_disk.NewWithFlags, + logon.Name: logon.NewWithFlags, + memory.Name: memory.NewWithFlags, + mscluster_cluster.Name: mscluster_cluster.NewWithFlags, + mscluster_network.Name: mscluster_network.NewWithFlags, + mscluster_node.Name: mscluster_node.NewWithFlags, + mscluster_resource.Name: mscluster_resource.NewWithFlags, + mscluster_resourcegroup.Name: mscluster_resourcegroup.NewWithFlags, + msmq.Name: msmq.NewWithFlags, + mssql.Name: mssql.NewWithFlags, + net.Name: net.NewWithFlags, + netframework_clrexceptions.Name: netframework_clrexceptions.NewWithFlags, + netframework_clrinterop.Name: netframework_clrinterop.NewWithFlags, + netframework_clrjit.Name: netframework_clrjit.NewWithFlags, + netframework_clrloading.Name: netframework_clrloading.NewWithFlags, + netframework_clrlocksandthreads.Name: netframework_clrlocksandthreads.NewWithFlags, + netframework_clrmemory.Name: netframework_clrmemory.NewWithFlags, + netframework_clrremoting.Name: netframework_clrremoting.NewWithFlags, + netframework_clrsecurity.Name: netframework_clrsecurity.NewWithFlags, + nps.Name: nps.NewWithFlags, + os.Name: os.NewWithFlags, + physical_disk.Name: physical_disk.NewWithFlags, + process.Name: process.NewWithFlags, + remote_fx.Name: remote_fx.NewWithFlags, + scheduled_task.Name: scheduled_task.NewWithFlags, + service.Name: service.NewWithFlags, + smtp.Name: smtp.NewWithFlags, + system.Name: system.NewWithFlags, + teradici_pcoip.Name: teradici_pcoip.NewWithFlags, + tcp.Name: tcp.NewWithFlags, + terminal_services.Name: terminal_services.NewWithFlags, + textfile.Name: textfile.NewWithFlags, + thermalzone.Name: thermalzone.NewWithFlags, + time.Name: time.NewWithFlags, + vmware.Name: vmware.NewWithFlags, + vmware_blast.Name: vmware_blast.NewWithFlags, +} + +func Available() []string { + return maps.Keys(Map) +} diff --git a/pkg/collector/memory/memory.go b/pkg/collector/memory/memory.go new file mode 100644 index 0000000000..96098dd799 --- /dev/null +++ b/pkg/collector/memory/memory.go @@ -0,0 +1,537 @@ +// returns data points from Win32_PerfRawData_PerfOS_Memory +// - Win32_PerfRawData_PerfOS_Memory class + +//go:build windows + +package memory + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "memory" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for perflib Memory metrics +type collector struct { + logger log.Logger + + AvailableBytes *prometheus.Desc + CacheBytes *prometheus.Desc + CacheBytesPeak *prometheus.Desc + CacheFaultsTotal *prometheus.Desc + CommitLimit *prometheus.Desc + CommittedBytes *prometheus.Desc + DemandZeroFaultsTotal *prometheus.Desc + FreeAndZeroPageListBytes *prometheus.Desc + FreeSystemPageTableEntries *prometheus.Desc + ModifiedPageListBytes *prometheus.Desc + PageFaultsTotal *prometheus.Desc + SwapPageReadsTotal *prometheus.Desc + SwapPagesReadTotal *prometheus.Desc + SwapPagesWrittenTotal *prometheus.Desc + SwapPageOperationsTotal *prometheus.Desc + SwapPageWritesTotal *prometheus.Desc + PoolNonpagedAllocsTotal *prometheus.Desc + PoolNonpagedBytes *prometheus.Desc + PoolPagedAllocsTotal *prometheus.Desc + PoolPagedBytes *prometheus.Desc + PoolPagedResidentBytes *prometheus.Desc + StandbyCacheCoreBytes *prometheus.Desc + StandbyCacheNormalPriorityBytes *prometheus.Desc + StandbyCacheReserveBytes *prometheus.Desc + SystemCacheResidentBytes *prometheus.Desc + SystemCodeResidentBytes *prometheus.Desc + SystemCodeTotalBytes *prometheus.Desc + SystemDriverResidentBytes *prometheus.Desc + SystemDriverTotalBytes *prometheus.Desc + TransitionFaultsTotal *prometheus.Desc + TransitionPagesRepurposedTotal *prometheus.Desc + WriteCopiesTotal *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Memory"}, nil +} + +func (c *collector) Build() error { + c.AvailableBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "available_bytes"), + "The amount of physical memory immediately available for allocation to a process or for system use. It is equal to the sum of memory assigned to"+ + " the standby (cached), free and zero page lists (AvailableBytes)", + nil, + nil, + ) + c.CacheBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cache_bytes"), + "(CacheBytes)", + nil, + nil, + ) + c.CacheBytesPeak = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cache_bytes_peak"), + "(CacheBytesPeak)", + nil, + nil, + ) + c.CacheFaultsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cache_faults_total"), + "Number of faults which occur when a page sought in the file system cache is not found there and must be retrieved from elsewhere in memory (soft fault) "+ + "or from disk (hard fault) (Cache Faults/sec)", + nil, + nil, + ) + c.CommitLimit = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "commit_limit"), + "(CommitLimit)", + nil, + nil, + ) + c.CommittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "committed_bytes"), + "(CommittedBytes)", + nil, + nil, + ) + c.DemandZeroFaultsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "demand_zero_faults_total"), + "The number of zeroed pages required to satisfy faults. Zeroed pages, pages emptied of previously stored data and filled with zeros, are a security"+ + " feature of Windows that prevent processes from seeing data stored by earlier processes that used the memory space (Demand Zero Faults/sec)", + nil, + nil, + ) + c.FreeAndZeroPageListBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "free_and_zero_page_list_bytes"), + "The amount of physical memory, in bytes, that is assigned to the free and zero page lists. This memory does not contain cached data. It is immediately"+ + " available for allocation to a process or for system use (FreeAndZeroPageListBytes)", + nil, + nil, + ) + c.FreeSystemPageTableEntries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "free_system_page_table_entries"), + "(FreeSystemPageTableEntries)", + nil, + nil, + ) + c.ModifiedPageListBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "modified_page_list_bytes"), + "The amount of physical memory, in bytes, that is assigned to the modified page list. This memory contains cached data and code that is not actively in "+ + "use by processes, the system and the system cache (ModifiedPageListBytes)", + nil, + nil, + ) + c.PageFaultsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "page_faults_total"), + "Overall rate at which faulted pages are handled by the processor (Page Faults/sec)", + nil, + nil, + ) + c.SwapPageReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "swap_page_reads_total"), + "Number of disk page reads (a single read operation reading several pages is still only counted once) (PageReadsPersec)", + nil, + nil, + ) + c.SwapPagesReadTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "swap_pages_read_total"), + "Number of pages read across all page reads (ie counting all pages read even if they are read in a single operation) (PagesInputPersec)", + nil, + nil, + ) + c.SwapPagesWrittenTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "swap_pages_written_total"), + "Number of pages written across all page writes (ie counting all pages written even if they are written in a single operation) (PagesOutputPersec)", + nil, + nil, + ) + c.SwapPageOperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "swap_page_operations_total"), + "Total number of swap page read and writes (PagesPersec)", + nil, + nil, + ) + c.SwapPageWritesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "swap_page_writes_total"), + "Number of disk page writes (a single write operation writing several pages is still only counted once) (PageWritesPersec)", + nil, + nil, + ) + c.PoolNonpagedAllocsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_nonpaged_allocs_total"), + "The number of calls to allocate space in the nonpaged pool. The nonpaged pool is an area of system memory area for objects that cannot be written"+ + " to disk, and must remain in physical memory as long as they are allocated (PoolNonpagedAllocs)", + nil, + nil, + ) + c.PoolNonpagedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_nonpaged_bytes"), + "Number of bytes in the non-paged pool, an area of the system virtual memory that is used for objects that cannot be written to disk, but must "+ + "remain in physical memory as long as they are allocated (PoolNonpagedBytes)", + nil, + nil, + ) + c.PoolPagedAllocsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_paged_allocs_total"), + "Number of calls to allocate space in the paged pool, regardless of the amount of space allocated in each call (PoolPagedAllocs)", + nil, + nil, + ) + c.PoolPagedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_paged_bytes"), + "(PoolPagedBytes)", + nil, + nil, + ) + c.PoolPagedResidentBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_paged_resident_bytes"), + "The size, in bytes, of the portion of the paged pool that is currently resident and active in physical memory. The paged pool is an area of the "+ + "system virtual memory that is used for objects that can be written to disk when they are not being used (PoolPagedResidentBytes)", + nil, + nil, + ) + c.StandbyCacheCoreBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "standby_cache_core_bytes"), + "The amount of physical memory, in bytes, that is assigned to the core standby cache page lists. This memory contains cached data and code that is "+ + "not actively in use by processes, the system and the system cache (StandbyCacheCoreBytes)", + nil, + nil, + ) + c.StandbyCacheNormalPriorityBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "standby_cache_normal_priority_bytes"), + "The amount of physical memory, in bytes, that is assigned to the normal priority standby cache page lists. This memory contains cached data and "+ + "code that is not actively in use by processes, the system and the system cache (StandbyCacheNormalPriorityBytes)", + nil, + nil, + ) + c.StandbyCacheReserveBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "standby_cache_reserve_bytes"), + "The amount of physical memory, in bytes, that is assigned to the reserve standby cache page lists. This memory contains cached data and code "+ + "that is not actively in use by processes, the system and the system cache (StandbyCacheReserveBytes)", + nil, + nil, + ) + c.SystemCacheResidentBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_cache_resident_bytes"), + "The size, in bytes, of the portion of the system file cache which is currently resident and active in physical memory (SystemCacheResidentBytes)", + nil, + nil, + ) + c.SystemCodeResidentBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_code_resident_bytes"), + "The size, in bytes, of the pageable operating system code that is currently resident and active in physical memory (SystemCodeResidentBytes)", + nil, + nil, + ) + c.SystemCodeTotalBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_code_total_bytes"), + "The size, in bytes, of the pageable operating system code currently mapped into the system virtual address space (SystemCodeTotalBytes)", + nil, + nil, + ) + c.SystemDriverResidentBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_driver_resident_bytes"), + "The size, in bytes, of the pageable physical memory being used by device drivers. It is the working set (physical memory area) of the drivers (SystemDriverResidentBytes)", + nil, + nil, + ) + c.SystemDriverTotalBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_driver_total_bytes"), + "The size, in bytes, of the pageable virtual memory currently being used by device drivers. Pageable memory can be written to disk when it is not being used (SystemDriverTotalBytes)", + nil, + nil, + ) + c.TransitionFaultsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transition_faults_total"), + "Number of faults rate at which page faults are resolved by recovering pages that were being used by another process sharing the page, or were on the "+ + "modified page list or the standby list, or were being written to disk at the time of the page fault (TransitionFaultsPersec)", + nil, + nil, + ) + c.TransitionPagesRepurposedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transition_pages_repurposed_total"), + "Transition Pages RePurposed is the rate at which the number of transition cache pages were reused for a different purpose (TransitionPagesRePurposedPersec)", + nil, + nil, + ) + c.WriteCopiesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_copies_total"), + "The number of page faults caused by attempting to write that were satisfied by copying the page from elsewhere in physical memory (WriteCopiesPersec)", + nil, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting memory metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type memory struct { + AvailableBytes float64 `perflib:"Available Bytes"` + AvailableKBytes float64 `perflib:"Available KBytes"` + AvailableMBytes float64 `perflib:"Available MBytes"` + CacheBytes float64 `perflib:"Cache Bytes"` + CacheBytesPeak float64 `perflib:"Cache Bytes Peak"` + CacheFaultsPersec float64 `perflib:"Cache Faults/sec"` + CommitLimit float64 `perflib:"Commit Limit"` + CommittedBytes float64 `perflib:"Committed Bytes"` + DemandZeroFaultsPersec float64 `perflib:"Demand Zero Faults/sec"` + FreeAndZeroPageListBytes float64 `perflib:"Free & Zero Page List Bytes"` + FreeSystemPageTableEntries float64 `perflib:"Free System Page Table Entries"` + ModifiedPageListBytes float64 `perflib:"Modified Page List Bytes"` + PageFaultsPersec float64 `perflib:"Page Faults/sec"` + PageReadsPersec float64 `perflib:"Page Reads/sec"` + PagesInputPersec float64 `perflib:"Pages Input/sec"` + PagesOutputPersec float64 `perflib:"Pages Output/sec"` + PagesPersec float64 `perflib:"Pages/sec"` + PageWritesPersec float64 `perflib:"Page Writes/sec"` + PoolNonpagedAllocs float64 `perflib:"Pool Nonpaged Allocs"` + PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` + PoolPagedAllocs float64 `perflib:"Pool Paged Allocs"` + PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` + PoolPagedResidentBytes float64 `perflib:"Pool Paged Resident Bytes"` + StandbyCacheCoreBytes float64 `perflib:"Standby Cache Core Bytes"` + StandbyCacheNormalPriorityBytes float64 `perflib:"Standby Cache Normal Priority Bytes"` + StandbyCacheReserveBytes float64 `perflib:"Standby Cache Reserve Bytes"` + SystemCacheResidentBytes float64 `perflib:"System Cache Resident Bytes"` + SystemCodeResidentBytes float64 `perflib:"System Code Resident Bytes"` + SystemCodeTotalBytes float64 `perflib:"System Code Total Bytes"` + SystemDriverResidentBytes float64 `perflib:"System Driver Resident Bytes"` + SystemDriverTotalBytes float64 `perflib:"System Driver Total Bytes"` + TransitionFaultsPersec float64 `perflib:"Transition Faults/sec"` + TransitionPagesRePurposedPersec float64 `perflib:"Transition Pages RePurposed/sec"` + WriteCopiesPersec float64 `perflib:"Write Copies/sec"` +} + +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []memory + if err := perflib.UnmarshalObject(ctx.PerfObjects["Memory"], &dst, c.logger); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.AvailableBytes, + prometheus.GaugeValue, + dst[0].AvailableBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.CacheBytes, + prometheus.GaugeValue, + dst[0].CacheBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.CacheBytesPeak, + prometheus.GaugeValue, + dst[0].CacheBytesPeak, + ) + + ch <- prometheus.MustNewConstMetric( + c.CacheFaultsTotal, + prometheus.CounterValue, + dst[0].CacheFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.CommitLimit, + prometheus.GaugeValue, + dst[0].CommitLimit, + ) + + ch <- prometheus.MustNewConstMetric( + c.CommittedBytes, + prometheus.GaugeValue, + dst[0].CommittedBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.DemandZeroFaultsTotal, + prometheus.CounterValue, + dst[0].DemandZeroFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.FreeAndZeroPageListBytes, + prometheus.GaugeValue, + dst[0].FreeAndZeroPageListBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.FreeSystemPageTableEntries, + prometheus.GaugeValue, + dst[0].FreeSystemPageTableEntries, + ) + + ch <- prometheus.MustNewConstMetric( + c.ModifiedPageListBytes, + prometheus.GaugeValue, + dst[0].ModifiedPageListBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.PageFaultsTotal, + prometheus.CounterValue, + dst[0].PageFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPageReadsTotal, + prometheus.CounterValue, + dst[0].PageReadsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPagesReadTotal, + prometheus.CounterValue, + dst[0].PagesInputPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPagesWrittenTotal, + prometheus.CounterValue, + dst[0].PagesOutputPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPageOperationsTotal, + prometheus.CounterValue, + dst[0].PagesPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.SwapPageWritesTotal, + prometheus.CounterValue, + dst[0].PageWritesPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolNonpagedAllocsTotal, + prometheus.GaugeValue, + dst[0].PoolNonpagedAllocs, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolNonpagedBytes, + prometheus.GaugeValue, + dst[0].PoolNonpagedBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolPagedAllocsTotal, + prometheus.CounterValue, + dst[0].PoolPagedAllocs, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolPagedBytes, + prometheus.GaugeValue, + dst[0].PoolPagedBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.PoolPagedResidentBytes, + prometheus.GaugeValue, + dst[0].PoolPagedResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandbyCacheCoreBytes, + prometheus.GaugeValue, + dst[0].StandbyCacheCoreBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandbyCacheNormalPriorityBytes, + prometheus.GaugeValue, + dst[0].StandbyCacheNormalPriorityBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandbyCacheReserveBytes, + prometheus.GaugeValue, + dst[0].StandbyCacheReserveBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemCacheResidentBytes, + prometheus.GaugeValue, + dst[0].SystemCacheResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemCodeResidentBytes, + prometheus.GaugeValue, + dst[0].SystemCodeResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemCodeTotalBytes, + prometheus.GaugeValue, + dst[0].SystemCodeTotalBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemDriverResidentBytes, + prometheus.GaugeValue, + dst[0].SystemDriverResidentBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.SystemDriverTotalBytes, + prometheus.GaugeValue, + dst[0].SystemDriverTotalBytes, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransitionFaultsTotal, + prometheus.CounterValue, + dst[0].TransitionFaultsPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.TransitionPagesRepurposedTotal, + prometheus.CounterValue, + dst[0].TransitionPagesRePurposedPersec, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteCopiesTotal, + prometheus.CounterValue, + dst[0].WriteCopiesPersec, + ) + + return nil, nil +} diff --git a/pkg/collector/memory/memory_test.go b/pkg/collector/memory/memory_test.go new file mode 100644 index 0000000000..757ff3fa5f --- /dev/null +++ b/pkg/collector/memory/memory_test.go @@ -0,0 +1,12 @@ +package memory_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/memory" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, memory.Name, memory.NewWithFlags) +} diff --git a/collector/mscluster_cluster.go b/pkg/collector/mscluster_cluster/mscluster_cluster.go similarity index 53% rename from collector/mscluster_cluster.go rename to pkg/collector/mscluster_cluster/mscluster_cluster.go index 7ec068d804..34be4bfc32 100644 --- a/collector/mscluster_cluster.go +++ b/pkg/collector/mscluster_cluster/mscluster_cluster.go @@ -1,13 +1,22 @@ -package collector +package mscluster_cluster //nolint:revive import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A MSCluster_ClusterCollector is a Prometheus collector for WMI MSCluster_Cluster metrics -type MSCluster_ClusterCollector struct { +const Name = "mscluster_cluster" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI MSCluster_Cluster metrics +type collector struct { logger log.Logger AddEvictDelay *prometheus.Desc @@ -89,474 +98,492 @@ type MSCluster_ClusterCollector struct { WitnessRestartInterval *prometheus.Desc } -func newMSCluster_ClusterCollector(logger log.Logger) (Collector, error) { - const subsystem = "mscluster_cluster" - return &MSCluster_ClusterCollector{ - logger: log.With(logger, "collector", subsystem), - - AddEvictDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "add_evict_delay"), - "Provides access to the cluster's AddEvictDelay property, which is the number a seconds that a new node is delayed after an eviction of another node.", - []string{"name"}, - nil, - ), - AdminAccessPoint: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "admin_access_point"), - "The type of the cluster administrative access point.", - []string{"name"}, - nil, - ), - AutoAssignNodeSite: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "auto_assign_node_site"), - "Determines whether or not the cluster will attempt to automatically assign nodes to sites based on networks and Active Directory Site information.", - []string{"name"}, - nil, - ), - AutoBalancerLevel: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "auto_balancer_level"), - "Determines the level of aggressiveness of AutoBalancer.", - []string{"name"}, - nil, - ), - AutoBalancerMode: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "auto_balancer_mode"), - "Determines whether or not the auto balancer is enabled.", - []string{"name"}, - nil, - ), - BackupInProgress: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "backup_in_progress"), - "Indicates whether a backup is in progress.", - []string{"name"}, - nil, - ), - BlockCacheSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "block_cache_size"), - "CSV BlockCache Size in MB.", - []string{"name"}, - nil, - ), - ClusSvcHangTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clus_svc_hang_timeout"), - "Controls how long the cluster network driver waits between Failover Cluster Service heartbeats before it determines that the Failover Cluster Service has stopped responding.", - []string{"name"}, - nil, - ), - ClusSvcRegroupOpeningTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clus_svc_regroup_opening_timeout"), - "Controls how long a node will wait on other nodes in the opening stage before deciding that they failed.", - []string{"name"}, - nil, - ), - ClusSvcRegroupPruningTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clus_svc_regroup_pruning_timeout"), - "Controls how long the membership leader will wait to reach full connectivity between cluster nodes.", - []string{"name"}, - nil, - ), - ClusSvcRegroupStageTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clus_svc_regroup_stage_timeout"), - "Controls how long a node will wait on other nodes in a membership stage before deciding that they failed.", - []string{"name"}, - nil, - ), - ClusSvcRegroupTickInMilliseconds: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clus_svc_regroup_tick_in_milliseconds"), - "Controls how frequently the membership algorithm is sending periodic membership messages.", - []string{"name"}, - nil, - ), - ClusterEnforcedAntiAffinity: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cluster_enforced_anti_affinity"), - "Enables or disables hard enforcement of group anti-affinity classes.", - []string{"name"}, - nil, - ), - ClusterFunctionalLevel: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cluster_functional_level"), - "The functional level the cluster is currently running in.", - []string{"name"}, - nil, - ), - ClusterGroupWaitDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cluster_group_wait_delay"), - "Maximum time in seconds that a group waits for its preferred node to come online during cluster startup before coming online on a different node.", - []string{"name"}, - nil, - ), - ClusterLogLevel: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cluster_log_level"), - "Controls the level of cluster logging.", - []string{"name"}, - nil, - ), - ClusterLogSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cluster_log_size"), - "Controls the maximum size of the cluster log files on each of the nodes.", - []string{"name"}, - nil, - ), - ClusterUpgradeVersion: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cluster_upgrade_version"), - "Specifies the upgrade version the cluster is currently running in.", - []string{"name"}, - nil, - ), - CrossSiteDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cross_site_delay"), - "Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across sites.", - []string{"name"}, - nil, - ), - CrossSiteThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cross_site_threshold"), - "Controls how many Cluster Service heartbeats can be missed across sites before it determines that Cluster Service has stopped responding.", - []string{"name"}, - nil, - ), - CrossSubnetDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cross_subnet_delay"), - "Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across subnets.", - []string{"name"}, - nil, - ), - CrossSubnetThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cross_subnet_threshold"), - "Controls how many Cluster Service heartbeats can be missed across subnets before it determines that Cluster Service has stopped responding.", - []string{"name"}, - nil, - ), - CsvBalancer: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "csv_balancer"), - "Whether automatic balancing for CSV is enabled.", - []string{"name"}, - nil, - ), - DatabaseReadWriteMode: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "database_read_write_mode"), - "Sets the database read and write mode.", - []string{"name"}, - nil, - ), - DefaultNetworkRole: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "default_network_role"), - "Provides access to the cluster's DefaultNetworkRole property.", - []string{"name"}, - nil, - ), - DetectedCloudPlatform: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "detected_cloud_platform"), - "(DetectedCloudPlatform)", - []string{"name"}, - nil, - ), - DetectManagedEvents: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "detect_managed_events"), - "(DetectManagedEvents)", - []string{"name"}, - nil, - ), - DetectManagedEventsThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "detect_managed_events_threshold"), - "(DetectManagedEventsThreshold)", - []string{"name"}, - nil, - ), - DisableGroupPreferredOwnerRandomization: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "disable_group_preferred_owner_randomization"), - "(DisableGroupPreferredOwnerRandomization)", - []string{"name"}, - nil, - ), - DrainOnShutdown: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "drain_on_shutdown"), - "Whether to drain the node when cluster service is being stopped.", - []string{"name"}, - nil, - ), - DynamicQuorumEnabled: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dynamic_quorum_enabled"), - "Allows cluster service to adjust node weights as needed to increase availability.", - []string{"name"}, - nil, - ), - EnableSharedVolumes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "enable_shared_volumes"), - "Enables or disables cluster shared volumes on this cluster.", - []string{"name"}, - nil, - ), - FixQuorum: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "fix_quorum"), - "Provides access to the cluster's FixQuorum property, which specifies if the cluster is in a fix quorum state.", - []string{"name"}, - nil, - ), - GracePeriodEnabled: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "grace_period_enabled"), - "Whether the node grace period feature of this cluster is enabled.", - []string{"name"}, - nil, - ), - GracePeriodTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "grace_period_timeout"), - "The grace period timeout in milliseconds.", - []string{"name"}, - nil, - ), - GroupDependencyTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "group_dependency_timeout"), - "The timeout after which a group will be brought online despite unsatisfied dependencies", - []string{"name"}, - nil, - ), - HangRecoveryAction: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "hang_recovery_action"), - "Controls the action to take if the user-mode processes have stopped responding.", - []string{"name"}, - nil, - ), - IgnorePersistentStateOnStartup: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ignore_persistent_state_on_startup"), - "Provides access to the cluster's IgnorePersistentStateOnStartup property, which specifies whether the cluster will bring online groups that were online when the cluster was shut down.", - []string{"name"}, - nil, - ), - LogResourceControls: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "log_resource_controls"), - "Controls the logging of resource controls.", - []string{"name"}, - nil, - ), - LowerQuorumPriorityNodeId: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "lower_quorum_priority_node_id"), - "Specifies the Node ID that has a lower priority when voting for quorum is performed. If the quorum vote is split 50/50%, the specified node's vote would be ignored to break the tie. If this is not set then the cluster will pick a node at random to break the tie.", - []string{"name"}, - nil, - ), - MaxNumberOfNodes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "max_number_of_nodes"), - "Indicates the maximum number of nodes that may participate in the Cluster.", - []string{"name"}, - nil, - ), - MessageBufferLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "message_buffer_length"), - "The maximum unacknowledged message count for GEM.", - []string{"name"}, - nil, - ), - MinimumNeverPreemptPriority: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "minimum_never_preempt_priority"), - "Groups with this priority or higher cannot be preempted.", - []string{"name"}, - nil, - ), - MinimumPreemptorPriority: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "minimum_preemptor_priority"), - "Minimum priority a cluster group must have to be able to preempt another group.", - []string{"name"}, - nil, - ), - NetftIPSecEnabled: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "netft_ip_sec_enabled"), - "Whether IPSec is enabled for cluster internal traffic.", - []string{"name"}, - nil, - ), - PlacementOptions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "placement_options"), - "Various option flags to modify default placement behavior.", - []string{"name"}, - nil, - ), - PlumbAllCrossSubnetRoutes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "plumb_all_cross_subnet_routes"), - "Plumbs all possible cross subnet routes to all nodes.", - []string{"name"}, - nil, - ), - PreventQuorum: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "prevent_quorum"), - "Whether the cluster will ignore group persistent state on startup.", - []string{"name"}, - nil, - ), - QuarantineDuration: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "quarantine_duration"), - "The quarantine period timeout in milliseconds.", - []string{"name"}, - nil, - ), - QuarantineThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "quarantine_threshold"), - "Number of node failures before it will be quarantined.", - []string{"name"}, - nil, - ), - QuorumArbitrationTimeMax: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "quorum_arbitration_time_max"), - "Controls the maximum time necessary to decide the Quorum owner node.", - []string{"name"}, - nil, - ), - QuorumArbitrationTimeMin: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "quorum_arbitration_time_min"), - "Controls the minimum time necessary to decide the Quorum owner node.", - []string{"name"}, - nil, - ), - QuorumLogFileSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "quorum_log_file_size"), - "This property is obsolete.", - []string{"name"}, - nil, - ), - QuorumTypeValue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "quorum_type_value"), - "Get the current quorum type value. -1: Unknown; 1: Node; 2: FileShareWitness; 3: Storage; 4: None", - []string{"name"}, - nil, - ), - RequestReplyTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "request_reply_timeout"), - "Controls the request reply time-out period.", - []string{"name"}, - nil, - ), - ResiliencyDefaultPeriod: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "resiliency_default_period"), - "The default resiliency period, in seconds, for the cluster.", - []string{"name"}, - nil, - ), - ResiliencyLevel: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "resiliency_level"), - "The resiliency level for the cluster.", - []string{"name"}, - nil, - ), - ResourceDllDeadlockPeriod: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "resource_dll_deadlock_period"), - "This property is obsolete.", - []string{"name"}, - nil, - ), - RootMemoryReserved: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "root_memory_reserved"), - "Controls the amount of memory reserved for the parent partition on all cluster nodes.", - []string{"name"}, - nil, - ), - RouteHistoryLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "route_history_length"), - "The history length for routes to help finding network issues.", - []string{"name"}, - nil, - ), - S2DBusTypes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2d_bus_types"), - "Bus types for storage spaces direct.", - []string{"name"}, - nil, - ), - S2DCacheDesiredState: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2d_cache_desired_state"), - "Desired state of the storage spaces direct cache.", - []string{"name"}, - nil, - ), - S2DCacheFlashReservePercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2d_cache_flash_reserve_percent"), - "Percentage of allocated flash space to utilize when caching.", - []string{"name"}, - nil, - ), - S2DCachePageSizeKBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2d_cache_page_size_k_bytes"), - "Page size in KB used by S2D cache.", - []string{"name"}, - nil, - ), - S2DEnabled: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2d_enabled"), - "Whether direct attached storage (DAS) is enabled.", - []string{"name"}, - nil, - ), - S2DIOLatencyThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2dio_latency_threshold"), - "The I/O latency threshold for storage spaces direct.", - []string{"name"}, - nil, - ), - S2DOptimizations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "s2d_optimizations"), - "Optimization flags for storage spaces direct.", - []string{"name"}, - nil, - ), - SameSubnetDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "same_subnet_delay"), - "Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats on the same subnet.", - []string{"name"}, - nil, - ), - SameSubnetThreshold: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "same_subnet_threshold"), - "Controls how many Cluster Service heartbeats can be missed on the same subnet before it determines that Cluster Service has stopped responding.", - []string{"name"}, - nil, - ), - SecurityLevel: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "security_level"), - "Controls the level of security that should apply to intracluster messages. 0: Clear Text; 1: Sign; 2: Encrypt ", - []string{"name"}, - nil, - ), - SecurityLevelForStorage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "security_level_for_storage"), - "(SecurityLevelForStorage)", - []string{"name"}, - nil, - ), - SharedVolumeVssWriterOperationTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "shared_volume_vss_writer_operation_timeout"), - "CSV VSS Writer operation timeout in seconds.", - []string{"name"}, - nil, - ), - ShutdownTimeoutInMinutes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "shutdown_timeout_in_minutes"), - "The maximum time in minutes allowed for cluster resources to come offline during cluster service shutdown.", - []string{"name"}, - nil, - ), - UseClientAccessNetworksForSharedVolumes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "use_client_access_networks_for_shared_volumes"), - "Whether the use of client access networks for cluster shared volumes feature of this cluster is enabled. 0: Disabled; 1: Enabled; 2: Auto", - []string{"name"}, - nil, - ), - WitnessDatabaseWriteTimeout: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "witness_database_write_timeout"), - "Controls the maximum time in seconds that a cluster database write to a witness can take before the write is abandoned.", - []string{"name"}, - nil, - ), - WitnessDynamicWeight: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "witness_dynamic_weight"), - "The weight of the configured witness.", - []string{"name"}, - nil, - ), - WitnessRestartInterval: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "witness_restart_interval"), - "Controls the witness restart interval.", - []string{"name"}, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Memory"}, nil +} + +func (c *collector) Build() error { + c.AddEvictDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "add_evict_delay"), + "Provides access to the cluster's AddEvictDelay property, which is the number a seconds that a new node is delayed after an eviction of another node.", + []string{"name"}, + nil, + ) + c.AdminAccessPoint = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "admin_access_point"), + "The type of the cluster administrative access point.", + []string{"name"}, + nil, + ) + c.AutoAssignNodeSite = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "auto_assign_node_site"), + "Determines whether or not the cluster will attempt to automatically assign nodes to sites based on networks and Active Directory Site information.", + []string{"name"}, + nil, + ) + c.AutoBalancerLevel = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "auto_balancer_level"), + "Determines the level of aggressiveness of AutoBalancer.", + []string{"name"}, + nil, + ) + c.AutoBalancerMode = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "auto_balancer_mode"), + "Determines whether or not the auto balancer is enabled.", + []string{"name"}, + nil, + ) + c.BackupInProgress = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "backup_in_progress"), + "Indicates whether a backup is in progress.", + []string{"name"}, + nil, + ) + c.BlockCacheSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "block_cache_size"), + "CSV BlockCache Size in MB.", + []string{"name"}, + nil, + ) + c.ClusSvcHangTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clus_svc_hang_timeout"), + "Controls how long the cluster network driver waits between Failover Cluster Service heartbeats before it determines that the Failover Cluster Service has stopped responding.", + []string{"name"}, + nil, + ) + c.ClusSvcRegroupOpeningTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clus_svc_regroup_opening_timeout"), + "Controls how long a node will wait on other nodes in the opening stage before deciding that they failed.", + []string{"name"}, + nil, + ) + c.ClusSvcRegroupPruningTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clus_svc_regroup_pruning_timeout"), + "Controls how long the membership leader will wait to reach full connectivity between cluster nodes.", + []string{"name"}, + nil, + ) + c.ClusSvcRegroupStageTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clus_svc_regroup_stage_timeout"), + "Controls how long a node will wait on other nodes in a membership stage before deciding that they failed.", + []string{"name"}, + nil, + ) + c.ClusSvcRegroupTickInMilliseconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clus_svc_regroup_tick_in_milliseconds"), + "Controls how frequently the membership algorithm is sending periodic membership messages.", + []string{"name"}, + nil, + ) + c.ClusterEnforcedAntiAffinity = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cluster_enforced_anti_affinity"), + "Enables or disables hard enforcement of group anti-affinity classes.", + []string{"name"}, + nil, + ) + c.ClusterFunctionalLevel = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cluster_functional_level"), + "The functional level the cluster is currently running in.", + []string{"name"}, + nil, + ) + c.ClusterGroupWaitDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cluster_group_wait_delay"), + "Maximum time in seconds that a group waits for its preferred node to come online during cluster startup before coming online on a different node.", + []string{"name"}, + nil, + ) + c.ClusterLogLevel = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cluster_log_level"), + "Controls the level of cluster logging.", + []string{"name"}, + nil, + ) + c.ClusterLogSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cluster_log_size"), + "Controls the maximum size of the cluster log files on each of the nodes.", + []string{"name"}, + nil, + ) + c.ClusterUpgradeVersion = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cluster_upgrade_version"), + "Specifies the upgrade version the cluster is currently running in.", + []string{"name"}, + nil, + ) + c.CrossSiteDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cross_site_delay"), + "Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across sites.", + []string{"name"}, + nil, + ) + c.CrossSiteThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cross_site_threshold"), + "Controls how many Cluster Service heartbeats can be missed across sites before it determines that Cluster Service has stopped responding.", + []string{"name"}, + nil, + ) + c.CrossSubnetDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cross_subnet_delay"), + "Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats across subnets.", + []string{"name"}, + nil, + ) + c.CrossSubnetThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cross_subnet_threshold"), + "Controls how many Cluster Service heartbeats can be missed across subnets before it determines that Cluster Service has stopped responding.", + []string{"name"}, + nil, + ) + c.CsvBalancer = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "csv_balancer"), + "Whether automatic balancing for CSV is enabled.", + []string{"name"}, + nil, + ) + c.DatabaseReadWriteMode = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "database_read_write_mode"), + "Sets the database read and write mode.", + []string{"name"}, + nil, + ) + c.DefaultNetworkRole = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "default_network_role"), + "Provides access to the cluster's DefaultNetworkRole property.", + []string{"name"}, + nil, + ) + c.DetectedCloudPlatform = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "detected_cloud_platform"), + "(DetectedCloudPlatform)", + []string{"name"}, + nil, + ) + c.DetectManagedEvents = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "detect_managed_events"), + "(DetectManagedEvents)", + []string{"name"}, + nil, + ) + c.DetectManagedEventsThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "detect_managed_events_threshold"), + "(DetectManagedEventsThreshold)", + []string{"name"}, + nil, + ) + c.DisableGroupPreferredOwnerRandomization = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "disable_group_preferred_owner_randomization"), + "(DisableGroupPreferredOwnerRandomization)", + []string{"name"}, + nil, + ) + c.DrainOnShutdown = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "drain_on_shutdown"), + "Whether to drain the node when cluster service is being stopped.", + []string{"name"}, + nil, + ) + c.DynamicQuorumEnabled = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_quorum_enabled"), + "Allows cluster service to adjust node weights as needed to increase availability.", + []string{"name"}, + nil, + ) + c.EnableSharedVolumes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "enable_shared_volumes"), + "Enables or disables cluster shared volumes on this cluster.", + []string{"name"}, + nil, + ) + c.FixQuorum = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "fix_quorum"), + "Provides access to the cluster's FixQuorum property, which specifies if the cluster is in a fix quorum state.", + []string{"name"}, + nil, + ) + c.GracePeriodEnabled = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "grace_period_enabled"), + "Whether the node grace period feature of this cluster is enabled.", + []string{"name"}, + nil, + ) + c.GracePeriodTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "grace_period_timeout"), + "The grace period timeout in milliseconds.", + []string{"name"}, + nil, + ) + c.GroupDependencyTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "group_dependency_timeout"), + "The timeout after which a group will be brought online despite unsatisfied dependencies", + []string{"name"}, + nil, + ) + c.HangRecoveryAction = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "hang_recovery_action"), + "Controls the action to take if the user-mode processes have stopped responding.", + []string{"name"}, + nil, + ) + c.IgnorePersistentStateOnStartup = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ignore_persistent_state_on_startup"), + "Provides access to the cluster's IgnorePersistentStateOnStartup property, which specifies whether the cluster will bring online groups that were online when the cluster was shut down.", + []string{"name"}, + nil, + ) + c.LogResourceControls = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "log_resource_controls"), + "Controls the logging of resource controls.", + []string{"name"}, + nil, + ) + c.LowerQuorumPriorityNodeId = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "lower_quorum_priority_node_id"), + "Specifies the Node ID that has a lower priority when voting for quorum is performed. If the quorum vote is split 50/50%, the specified node's vote would be ignored to break the tie. If this is not set then the cluster will pick a node at random to break the tie.", + []string{"name"}, + nil, + ) + c.MaxNumberOfNodes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "max_number_of_nodes"), + "Indicates the maximum number of nodes that may participate in the Cluster.", + []string{"name"}, + nil, + ) + c.MessageBufferLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "message_buffer_length"), + "The maximum unacknowledged message count for GEM.", + []string{"name"}, + nil, + ) + c.MinimumNeverPreemptPriority = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "minimum_never_preempt_priority"), + "Groups with this priority or higher cannot be preempted.", + []string{"name"}, + nil, + ) + c.MinimumPreemptorPriority = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "minimum_preemptor_priority"), + "Minimum priority a cluster group must have to be able to preempt another group.", + []string{"name"}, + nil, + ) + c.NetftIPSecEnabled = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "netft_ip_sec_enabled"), + "Whether IPSec is enabled for cluster internal traffic.", + []string{"name"}, + nil, + ) + c.PlacementOptions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "placement_options"), + "Various option flags to modify default placement behavior.", + []string{"name"}, + nil, + ) + c.PlumbAllCrossSubnetRoutes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "plumb_all_cross_subnet_routes"), + "Plumbs all possible cross subnet routes to all nodes.", + []string{"name"}, + nil, + ) + c.PreventQuorum = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "prevent_quorum"), + "Whether the cluster will ignore group persistent state on startup.", + []string{"name"}, + nil, + ) + c.QuarantineDuration = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "quarantine_duration"), + "The quarantine period timeout in milliseconds.", + []string{"name"}, + nil, + ) + c.QuarantineThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "quarantine_threshold"), + "Number of node failures before it will be quarantined.", + []string{"name"}, + nil, + ) + c.QuorumArbitrationTimeMax = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "quorum_arbitration_time_max"), + "Controls the maximum time necessary to decide the Quorum owner node.", + []string{"name"}, + nil, + ) + c.QuorumArbitrationTimeMin = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "quorum_arbitration_time_min"), + "Controls the minimum time necessary to decide the Quorum owner node.", + []string{"name"}, + nil, + ) + c.QuorumLogFileSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "quorum_log_file_size"), + "This property is obsolete.", + []string{"name"}, + nil, + ) + c.QuorumTypeValue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "quorum_type_value"), + "Get the current quorum type value. -1: Unknown; 1: Node; 2: FileShareWitness; 3: Storage; 4: None", + []string{"name"}, + nil, + ) + c.RequestReplyTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "request_reply_timeout"), + "Controls the request reply time-out period.", + []string{"name"}, + nil, + ) + c.ResiliencyDefaultPeriod = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "resiliency_default_period"), + "The default resiliency period, in seconds, for the cluster.", + []string{"name"}, + nil, + ) + c.ResiliencyLevel = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "resiliency_level"), + "The resiliency level for the cluster.", + []string{"name"}, + nil, + ) + c.ResourceDllDeadlockPeriod = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "resource_dll_deadlock_period"), + "This property is obsolete.", + []string{"name"}, + nil, + ) + c.RootMemoryReserved = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "root_memory_reserved"), + "Controls the amount of memory reserved for the parent partition on all cluster nodes.", + []string{"name"}, + nil, + ) + c.RouteHistoryLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "route_history_length"), + "The history length for routes to help finding network issues.", + []string{"name"}, + nil, + ) + c.S2DBusTypes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2d_bus_types"), + "Bus types for storage spaces direct.", + []string{"name"}, + nil, + ) + c.S2DCacheDesiredState = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2d_cache_desired_state"), + "Desired state of the storage spaces direct cache.", + []string{"name"}, + nil, + ) + c.S2DCacheFlashReservePercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2d_cache_flash_reserve_percent"), + "Percentage of allocated flash space to utilize when caching.", + []string{"name"}, + nil, + ) + c.S2DCachePageSizeKBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2d_cache_page_size_k_bytes"), + "Page size in KB used by S2D cache.", + []string{"name"}, + nil, + ) + c.S2DEnabled = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2d_enabled"), + "Whether direct attached storage (DAS) is enabled.", + []string{"name"}, + nil, + ) + c.S2DIOLatencyThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2dio_latency_threshold"), + "The I/O latency threshold for storage spaces direct.", + []string{"name"}, + nil, + ) + c.S2DOptimizations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "s2d_optimizations"), + "Optimization flags for storage spaces direct.", + []string{"name"}, + nil, + ) + c.SameSubnetDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "same_subnet_delay"), + "Controls how long the cluster network driver waits in milliseconds between sending Cluster Service heartbeats on the same subnet.", + []string{"name"}, + nil, + ) + c.SameSubnetThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "same_subnet_threshold"), + "Controls how many Cluster Service heartbeats can be missed on the same subnet before it determines that Cluster Service has stopped responding.", + []string{"name"}, + nil, + ) + c.SecurityLevel = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "security_level"), + "Controls the level of security that should apply to intracluster messages. 0: Clear Text; 1: Sign; 2: Encrypt ", + []string{"name"}, + nil, + ) + c.SecurityLevelForStorage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "security_level_for_storage"), + "(SecurityLevelForStorage)", + []string{"name"}, + nil, + ) + c.SharedVolumeVssWriterOperationTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "shared_volume_vss_writer_operation_timeout"), + "CSV VSS Writer operation timeout in seconds.", + []string{"name"}, + nil, + ) + c.ShutdownTimeoutInMinutes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "shutdown_timeout_in_minutes"), + "The maximum time in minutes allowed for cluster resources to come offline during cluster service shutdown.", + []string{"name"}, + nil, + ) + c.UseClientAccessNetworksForSharedVolumes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "use_client_access_networks_for_shared_volumes"), + "Whether the use of client access networks for cluster shared volumes feature of this cluster is enabled. 0: Disabled; 1: Enabled; 2: Auto", + []string{"name"}, + nil, + ) + c.WitnessDatabaseWriteTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "witness_database_write_timeout"), + "Controls the maximum time in seconds that a cluster database write to a witness can take before the write is abandoned.", + []string{"name"}, + nil, + ) + c.WitnessDynamicWeight = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "witness_dynamic_weight"), + "The weight of the configured witness.", + []string{"name"}, + nil, + ) + c.WitnessRestartInterval = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "witness_restart_interval"), + "Controls the witness restart interval.", + []string{"name"}, + nil, + ) + return nil } // MSCluster_Cluster docs: @@ -645,9 +672,9 @@ type MSCluster_Cluster struct { // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *MSCluster_ClusterCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { var dst []MSCluster_Cluster - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { return err } diff --git a/pkg/collector/mscluster_network/mscluster_network.go b/pkg/collector/mscluster_network/mscluster_network.go new file mode 100644 index 0000000000..c6f747be87 --- /dev/null +++ b/pkg/collector/mscluster_network/mscluster_network.go @@ -0,0 +1,144 @@ +package mscluster_network //nolint:revive + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "mscluster_network" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI MSCluster_Network metrics +type collector struct { + logger log.Logger + + Characteristics *prometheus.Desc + Flags *prometheus.Desc + Metric *prometheus.Desc + Role *prometheus.Desc + State *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Memory"}, nil +} + +func (c *collector) Build() error { + c.Characteristics = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "characteristics"), + "Provides the characteristics of the network.", + []string{"name"}, + nil, + ) + c.Flags = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "flags"), + "Provides access to the flags set for the node. ", + []string{"name"}, + nil, + ) + c.Metric = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "metric"), + "The metric of a cluster network (networks with lower values are used first). If this value is set, then the AutoMetric property is set to false.", + []string{"name"}, + nil, + ) + c.Role = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "role"), + "Provides access to the network's Role property. The Role property describes the role of the network in the cluster. 0: None; 1: Cluster; 2: Client; 3: Both ", + []string{"name"}, + nil, + ) + c.State = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "state"), + "Provides the current state of the network. 1-1: Unknown; 0: Unavailable; 1: Down; 2: Partitioned; 3: Up", + []string{"name"}, + nil, + ) + return nil +} + +// MSCluster_Network docs: +// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-network +type MSCluster_Network struct { + Name string + + Characteristics uint + Flags uint + Metric uint + Role uint + State uint +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + var dst []MSCluster_Network + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { + return err + } + + for _, v := range dst { + ch <- prometheus.MustNewConstMetric( + c.Characteristics, + prometheus.GaugeValue, + float64(v.Characteristics), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Flags, + prometheus.GaugeValue, + float64(v.Flags), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Metric, + prometheus.GaugeValue, + float64(v.Metric), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Role, + prometheus.GaugeValue, + float64(v.Role), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + float64(v.State), + v.Name, + ) + } + + return nil +} diff --git a/pkg/collector/mscluster_node/mscluster_node.go b/pkg/collector/mscluster_node/mscluster_node.go new file mode 100644 index 0000000000..85d8602257 --- /dev/null +++ b/pkg/collector/mscluster_node/mscluster_node.go @@ -0,0 +1,280 @@ +package mscluster_node //nolint:revive + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "mscluster_node" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI MSCluster_Node metrics +type collector struct { + logger log.Logger + + BuildNumber *prometheus.Desc + Characteristics *prometheus.Desc + DetectedCloudPlatform *prometheus.Desc + DynamicWeight *prometheus.Desc + Flags *prometheus.Desc + MajorVersion *prometheus.Desc + MinorVersion *prometheus.Desc + NeedsPreventQuorum *prometheus.Desc + NodeDrainStatus *prometheus.Desc + NodeHighestVersion *prometheus.Desc + NodeLowestVersion *prometheus.Desc + NodeWeight *prometheus.Desc + State *prometheus.Desc + StatusInformation *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Memory"}, nil +} + +func (c *collector) Build() error { + c.BuildNumber = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "build_number"), + "Provides access to the node's BuildNumber property.", + []string{"name"}, + nil, + ) + c.Characteristics = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "characteristics"), + "Provides access to the characteristics set for the node.", + []string{"name"}, + nil, + ) + c.DetectedCloudPlatform = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "detected_cloud_platform"), + "(DetectedCloudPlatform)", + []string{"name"}, + nil, + ) + c.DynamicWeight = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dynamic_weight"), + "The dynamic vote weight of the node adjusted by dynamic quorum feature.", + []string{"name"}, + nil, + ) + c.Flags = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "flags"), + "Provides access to the flags set for the node.", + []string{"name"}, + nil, + ) + c.MajorVersion = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "major_version"), + "Provides access to the node's MajorVersion property, which specifies the major portion of the Windows version installed.", + []string{"name"}, + nil, + ) + c.MinorVersion = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "minor_version"), + "Provides access to the node's MinorVersion property, which specifies the minor portion of the Windows version installed.", + []string{"name"}, + nil, + ) + c.NeedsPreventQuorum = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "needs_prevent_quorum"), + "Whether the cluster service on that node should be started with prevent quorum flag.", + []string{"name"}, + nil, + ) + c.NodeDrainStatus = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "node_drain_status"), + "The current node drain status of a node. 0: Not Initiated; 1: In Progress; 2: Completed; 3: Failed", + []string{"name"}, + nil, + ) + c.NodeHighestVersion = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "node_highest_version"), + "Provides access to the node's NodeHighestVersion property, which specifies the highest possible version of the cluster service with which the node can join or communicate.", + []string{"name"}, + nil, + ) + c.NodeLowestVersion = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "node_lowest_version"), + "Provides access to the node's NodeLowestVersion property, which specifies the lowest possible version of the cluster service with which the node can join or communicate.", + []string{"name"}, + nil, + ) + c.NodeWeight = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "node_weight"), + "The vote weight of the node.", + []string{"name"}, + nil, + ) + c.State = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "state"), + "Returns the current state of a node. -1: Unknown; 0: Up; 1: Down; 2: Paused; 3: Joining", + []string{"name"}, + nil, + ) + c.StatusInformation = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "status_information"), + "The isolation or quarantine status of the node.", + []string{"name"}, + nil, + ) + return nil +} + +// MSCluster_Node docs: +// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-node +type MSCluster_Node struct { + Name string + + BuildNumber uint + Characteristics uint + DetectedCloudPlatform uint + DynamicWeight uint + Flags uint + MajorVersion uint + MinorVersion uint + NeedsPreventQuorum uint + NodeDrainStatus uint + NodeHighestVersion uint + NodeLowestVersion uint + NodeWeight uint + State uint + StatusInformation uint +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + var dst []MSCluster_Node + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { + return err + } + + for _, v := range dst { + + ch <- prometheus.MustNewConstMetric( + c.BuildNumber, + prometheus.GaugeValue, + float64(v.BuildNumber), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Characteristics, + prometheus.GaugeValue, + float64(v.Characteristics), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DetectedCloudPlatform, + prometheus.GaugeValue, + float64(v.DetectedCloudPlatform), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DynamicWeight, + prometheus.GaugeValue, + float64(v.DynamicWeight), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Flags, + prometheus.GaugeValue, + float64(v.Flags), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MajorVersion, + prometheus.GaugeValue, + float64(v.MajorVersion), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MinorVersion, + prometheus.GaugeValue, + float64(v.MinorVersion), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NeedsPreventQuorum, + prometheus.GaugeValue, + float64(v.NeedsPreventQuorum), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NodeDrainStatus, + prometheus.GaugeValue, + float64(v.NodeDrainStatus), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NodeHighestVersion, + prometheus.GaugeValue, + float64(v.NodeHighestVersion), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NodeLowestVersion, + prometheus.GaugeValue, + float64(v.NodeLowestVersion), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NodeWeight, + prometheus.GaugeValue, + float64(v.NodeWeight), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + float64(v.State), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.StatusInformation, + prometheus.GaugeValue, + float64(v.StatusInformation), + v.Name, + ) + } + + return nil +} diff --git a/pkg/collector/mscluster_resource/mscluster_resource.go b/pkg/collector/mscluster_resource/mscluster_resource.go new file mode 100644 index 0000000000..130bfc0ddc --- /dev/null +++ b/pkg/collector/mscluster_resource/mscluster_resource.go @@ -0,0 +1,312 @@ +package mscluster_resource //nolint:revive + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "mscluster_resource" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI MSCluster_Resource metrics +type collector struct { + logger log.Logger + + Characteristics *prometheus.Desc + DeadlockTimeout *prometheus.Desc + EmbeddedFailureAction *prometheus.Desc + Flags *prometheus.Desc + IsAlivePollInterval *prometheus.Desc + LooksAlivePollInterval *prometheus.Desc + MonitorProcessId *prometheus.Desc + PendingTimeout *prometheus.Desc + ResourceClass *prometheus.Desc + RestartAction *prometheus.Desc + RestartDelay *prometheus.Desc + RestartPeriod *prometheus.Desc + RestartThreshold *prometheus.Desc + RetryPeriodOnFailure *prometheus.Desc + State *prometheus.Desc + Subclass *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Memory"}, nil +} + +func (c *collector) Build() error { + c.Characteristics = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "characteristics"), + "Provides the characteristics of the object.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.DeadlockTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "deadlock_timeout"), + "Indicates the length of time to wait, in milliseconds, before declaring a deadlock in any call into a resource.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.EmbeddedFailureAction = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "embedded_failure_action"), + "The time, in milliseconds, that a resource should remain in a failed state before the Cluster service attempts to restart it.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.Flags = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "flags"), + "Provides access to the flags set for the object.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.IsAlivePollInterval = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "is_alive_poll_interval"), + "Provides access to the resource's IsAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it is operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the IsAlivePollInterval property for the resource type associated with the resource.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.LooksAlivePollInterval = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "looks_alive_poll_interval"), + "Provides access to the resource's LooksAlivePollInterval property, which is the recommended interval in milliseconds at which the Cluster Service should poll the resource to determine whether it appears operational. If the property is set to 0xFFFFFFFF, the Cluster Service uses the LooksAlivePollInterval property for the resource type associated with the resource.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.MonitorProcessId = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "monitor_process_id"), + "Provides the process ID of the resource host service that is currently hosting the resource.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.PendingTimeout = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pending_timeout"), + "Provides access to the resource's PendingTimeout property. If a resource cannot be brought online or taken offline in the number of milliseconds specified by the PendingTimeout property, the resource is forcibly terminated.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.ResourceClass = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "resource_class"), + "Gets or sets the resource class of a resource. 0: Unknown; 1: Storage; 2: Network; 32768: Unknown ", + []string{"type", "owner_group", "name"}, + nil, + ) + c.RestartAction = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "restart_action"), + "Provides access to the resource's RestartAction property, which is the action to be taken by the Cluster Service if the resource fails.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.RestartDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "restart_delay"), + "Indicates the time delay before a failed resource is restarted.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.RestartPeriod = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "restart_period"), + "Provides access to the resource's RestartPeriod property, which is interval of time, in milliseconds, during which a specified number of restart attempts can be made on a nonresponsive resource.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.RestartThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "restart_threshold"), + "Provides access to the resource's RestartThreshold property which is the maximum number of restart attempts that can be made on a resource within an interval defined by the RestartPeriod property before the Cluster Service initiates the action specified by the RestartAction property.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.RetryPeriodOnFailure = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "retry_period_on_failure"), + "Provides access to the resource's RetryPeriodOnFailure property, which is the interval of time (in milliseconds) that a resource should remain in a failed state before the Cluster service attempts to restart it.", + []string{"type", "owner_group", "name"}, + nil, + ) + c.State = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "state"), + "The current state of the resource. -1: Unknown; 0: Inherited; 1: Initializing; 2: Online; 3: Offline; 4: Failed; 128: Pending; 129: Online Pending; 130: Offline Pending ", + []string{"type", "owner_group", "name"}, + nil, + ) + c.Subclass = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "subclass"), + "Provides the list of references to nodes that can be the owner of this resource.", + []string{"type", "owner_group", "name"}, + nil, + ) + return nil +} + +// MSCluster_Resource docs: +// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resource +type MSCluster_Resource struct { + Name string + Type string + OwnerGroup string + + Characteristics uint + DeadlockTimeout uint + EmbeddedFailureAction uint + Flags uint + IsAlivePollInterval uint + LooksAlivePollInterval uint + MonitorProcessId uint + PendingTimeout uint + ResourceClass uint + RestartAction uint + RestartDelay uint + RestartPeriod uint + RestartThreshold uint + RetryPeriodOnFailure uint + State uint + Subclass uint +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + var dst []MSCluster_Resource + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { + return err + } + + for _, v := range dst { + + ch <- prometheus.MustNewConstMetric( + c.Characteristics, + prometheus.GaugeValue, + float64(v.Characteristics), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DeadlockTimeout, + prometheus.GaugeValue, + float64(v.DeadlockTimeout), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.EmbeddedFailureAction, + prometheus.GaugeValue, + float64(v.EmbeddedFailureAction), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Flags, + prometheus.GaugeValue, + float64(v.Flags), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.IsAlivePollInterval, + prometheus.GaugeValue, + float64(v.IsAlivePollInterval), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.LooksAlivePollInterval, + prometheus.GaugeValue, + float64(v.LooksAlivePollInterval), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.MonitorProcessId, + prometheus.GaugeValue, + float64(v.MonitorProcessId), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.PendingTimeout, + prometheus.GaugeValue, + float64(v.PendingTimeout), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ResourceClass, + prometheus.GaugeValue, + float64(v.ResourceClass), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RestartAction, + prometheus.GaugeValue, + float64(v.RestartAction), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RestartDelay, + prometheus.GaugeValue, + float64(v.RestartDelay), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RestartPeriod, + prometheus.GaugeValue, + float64(v.RestartPeriod), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RestartThreshold, + prometheus.GaugeValue, + float64(v.RestartThreshold), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.RetryPeriodOnFailure, + prometheus.GaugeValue, + float64(v.RetryPeriodOnFailure), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + float64(v.State), + v.Type, v.OwnerGroup, v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Subclass, + prometheus.GaugeValue, + float64(v.Subclass), + v.Type, v.OwnerGroup, v.Name, + ) + } + + return nil +} diff --git a/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go b/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go new file mode 100644 index 0000000000..d564d73dd0 --- /dev/null +++ b/pkg/collector/mscluster_resourcegroup/mscluster_resourcegroup.go @@ -0,0 +1,268 @@ +package mscluster_resourcegroup //nolint:revive + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "mscluster_resourcegroup" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI MSCluster_ResourceGroup metrics +type collector struct { + logger log.Logger + + AutoFailbackType *prometheus.Desc + Characteristics *prometheus.Desc + ColdStartSetting *prometheus.Desc + DefaultOwner *prometheus.Desc + FailbackWindowEnd *prometheus.Desc + FailbackWindowStart *prometheus.Desc + FailoverPeriod *prometheus.Desc + FailoverThreshold *prometheus.Desc + FaultDomain *prometheus.Desc + Flags *prometheus.Desc + GroupType *prometheus.Desc + PlacementOptions *prometheus.Desc + Priority *prometheus.Desc + ResiliencyPeriod *prometheus.Desc + State *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Memory"}, nil +} + +func (c *collector) Build() error { + c.AutoFailbackType = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "auto_failback_type"), + "Provides access to the group's AutoFailbackType property.", + []string{"name"}, + nil, + ) + c.Characteristics = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "characteristics"), + "Provides the characteristics of the group.", + []string{"name"}, + nil, + ) + c.ColdStartSetting = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cold_start_setting"), + "Indicates whether a group can start after a cluster cold start.", + []string{"name"}, + nil, + ) + c.DefaultOwner = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "default_owner"), + "Number of the last node the resource group was activated on or explicitly moved to.", + []string{"name"}, + nil, + ) + c.FailbackWindowEnd = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failback_window_end"), + "The FailbackWindowEnd property provides the latest time that the group can be moved back to the node identified as its preferred node.", + []string{"name"}, + nil, + ) + c.FailbackWindowStart = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failback_window_start"), + "The FailbackWindowStart property provides the earliest time (that is, local time as kept by the cluster) that the group can be moved back to the node identified as its preferred node.", + []string{"name"}, + nil, + ) + c.FailoverPeriod = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_period"), + "The FailoverPeriod property specifies a number of hours during which a maximum number of failover attempts, specified by the FailoverThreshold property, can occur.", + []string{"name"}, + nil, + ) + c.FailoverThreshold = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "failover_threshold"), + "The FailoverThreshold property specifies the maximum number of failover attempts.", + []string{"name"}, + nil, + ) + c.Flags = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "flags"), + "Provides access to the flags set for the group. ", + []string{"name"}, + nil, + ) + c.GroupType = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "group_type"), + "The Type of the resource group.", + []string{"name"}, + nil, + ) + c.Priority = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "priority"), + "Priority value of the resource group", + []string{"name"}, + nil, + ) + c.ResiliencyPeriod = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "resiliency_period"), + "The resiliency period for this group, in seconds.", + []string{"name"}, + nil, + ) + c.State = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "state"), + "The current state of the resource group. -1: Unknown; 0: Online; 1: Offline; 2: Failed; 3: Partial Online; 4: Pending", + []string{"name"}, + nil, + ) + return nil +} + +// MSCluster_ResourceGroup docs: +// - https://docs.microsoft.com/en-us/previous-versions/windows/desktop/cluswmi/mscluster-resourcegroup +type MSCluster_ResourceGroup struct { + Name string + + AutoFailbackType uint + Characteristics uint + ColdStartSetting uint + DefaultOwner uint + FailbackWindowEnd int + FailbackWindowStart int + FailoverPeriod uint + FailoverThreshold uint + Flags uint + GroupType uint + Priority uint + ResiliencyPeriod uint + State uint +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + var dst []MSCluster_ResourceGroup + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.QueryNamespace(q, &dst, "root/MSCluster"); err != nil { + return err + } + + for _, v := range dst { + + ch <- prometheus.MustNewConstMetric( + c.AutoFailbackType, + prometheus.GaugeValue, + float64(v.AutoFailbackType), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Characteristics, + prometheus.GaugeValue, + float64(v.Characteristics), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ColdStartSetting, + prometheus.GaugeValue, + float64(v.ColdStartSetting), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.DefaultOwner, + prometheus.GaugeValue, + float64(v.DefaultOwner), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailbackWindowEnd, + prometheus.GaugeValue, + float64(v.FailbackWindowEnd), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailbackWindowStart, + prometheus.GaugeValue, + float64(v.FailbackWindowStart), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverPeriod, + prometheus.GaugeValue, + float64(v.FailoverPeriod), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.FailoverThreshold, + prometheus.GaugeValue, + float64(v.FailoverThreshold), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Flags, + prometheus.GaugeValue, + float64(v.Flags), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.GroupType, + prometheus.GaugeValue, + float64(v.GroupType), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Priority, + prometheus.GaugeValue, + float64(v.Priority), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ResiliencyPeriod, + prometheus.GaugeValue, + float64(v.ResiliencyPeriod), + v.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + float64(v.State), + v.Name, + ) + + } + + return nil +} diff --git a/pkg/collector/msmq/msmq.go b/pkg/collector/msmq/msmq.go new file mode 100644 index 0000000000..dacd46e716 --- /dev/null +++ b/pkg/collector/msmq/msmq.go @@ -0,0 +1,162 @@ +//go:build windows + +package msmq + +import ( + "strings" + + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + Name = "msmq" + FlagMsmqWhereClause = "collector.msmq.msmq-where" +) + +type Config struct { + QueryWhereClause string `yaml:"query_where_clause"` +} + +var ConfigDefaults = Config{ + QueryWhereClause: "", +} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_MSMQ_MSMQQueue metrics +type collector struct { + logger log.Logger + + queryWhereClause *string + + BytesinJournalQueue *prometheus.Desc + BytesinQueue *prometheus.Desc + MessagesinJournalQueue *prometheus.Desc + MessagesinQueue *prometheus.Desc +} + +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + queryWhereClause: &config.QueryWhereClause, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + return &collector{ + queryWhereClause: app. + Flag(FlagMsmqWhereClause, "WQL 'where' clause to use in WMI metrics query. Limits the response to the msmqs you specify and reduces the size of the response."). + Default(ConfigDefaults.QueryWhereClause).String(), + } +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + if *c.queryWhereClause == "" { + _ = level.Warn(c.logger).Log("msg", "No where-clause specified for msmq collector. This will generate a very large number of metrics!") + } + + c.BytesinJournalQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_in_journal_queue"), + "Size of queue journal in bytes", + []string{"name"}, + nil, + ) + c.BytesinQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_in_queue"), + "Size of queue in bytes", + []string{"name"}, + nil, + ) + c.MessagesinJournalQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_in_journal_queue"), + "Count messages in queue journal", + []string{"name"}, + nil, + ) + c.MessagesinQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_in_queue"), + "Count messages in queue", + []string{"name"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting msmq metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_MSMQ_MSMQQueue struct { + Name string + + BytesinJournalQueue uint64 + BytesinQueue uint64 + MessagesinJournalQueue uint64 + MessagesinQueue uint64 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_MSMQ_MSMQQueue + q := wmi.QueryAllWhere(&dst, *c.queryWhereClause, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, msmq := range dst { + ch <- prometheus.MustNewConstMetric( + c.BytesinJournalQueue, + prometheus.GaugeValue, + float64(msmq.BytesinJournalQueue), + strings.ToLower(msmq.Name), + ) + + ch <- prometheus.MustNewConstMetric( + c.BytesinQueue, + prometheus.GaugeValue, + float64(msmq.BytesinQueue), + strings.ToLower(msmq.Name), + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesinJournalQueue, + prometheus.GaugeValue, + float64(msmq.MessagesinJournalQueue), + strings.ToLower(msmq.Name), + ) + + ch <- prometheus.MustNewConstMetric( + c.MessagesinQueue, + prometheus.GaugeValue, + float64(msmq.MessagesinQueue), + strings.ToLower(msmq.Name), + ) + } + return nil, nil +} diff --git a/pkg/collector/msmq/msmq_test.go b/pkg/collector/msmq/msmq_test.go new file mode 100644 index 0000000000..0f7601ff02 --- /dev/null +++ b/pkg/collector/msmq/msmq_test.go @@ -0,0 +1,13 @@ +package msmq_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/msmq" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, msmq.Name, msmq.NewWithFlags) +} diff --git a/collector/mssql.go b/pkg/collector/mssql/mssql.go similarity index 60% rename from collector/mssql.go rename to pkg/collector/mssql/mssql.go index dd2a543936..62fa31286b 100644 --- a/collector/mssql.go +++ b/pkg/collector/mssql/mssql.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package mssql import ( "errors" @@ -14,20 +13,26 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/windows/registry" ) const ( + Name = "mssql" FlagMssqlEnabledCollectors = "collectors.mssql.classes-enabled" FlagMssqlPrintCollectors = "collectors.mssql.class-print" ) -var ( - mssqlEnabledCollectors *string +type Config struct { + EnabledCollectors string `yaml:"collectors_enabled"` +} - mssqlPrintCollectors *bool -) +var ConfigDefaults = Config{ + EnabledCollectors: "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions,waitstats", +} type mssqlInstancesType map[string]string @@ -70,11 +75,7 @@ func getMSSQLInstances(logger log.Logger) mssqlInstancesType { type mssqlCollectorsMap map[string]mssqlCollectorFunc -func mssqlAvailableClassCollectors() string { - return "accessmethods,availreplica,bufman,databases,dbreplica,genstats,locks,memmgr,sqlstats,sqlerrors,transactions,waitstats" -} - -func (c *MSSQLCollector) getMSSQLCollectors() mssqlCollectorsMap { +func (c *collector) getMSSQLCollectors() mssqlCollectorsMap { mssqlCollectors := make(mssqlCollectorsMap) mssqlCollectors["accessmethods"] = c.collectAccessMethods mssqlCollectors["availreplica"] = c.collectAvailabilityReplica @@ -126,13 +127,16 @@ func mssqlGetPerfObjectName(sqlInstance string, collector string) string { case "waitstats": suffix = "Wait Statistics" } - return (prefix + suffix) + return prefix + suffix } -// A MSSQLCollector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics -type MSSQLCollector struct { +// A collector is a Prometheus collector for various WMI Win32_PerfRawData_MSSQLSERVER_* metrics +type collector struct { logger log.Logger + mssqlEnabledCollectors *string + mssqlPrintCollectors *bool + // meta mssqlScrapeDurationDesc *prometheus.Desc mssqlScrapeSuccessDesc *prometheus.Desc @@ -403,1526 +407,1534 @@ type MSSQLCollector struct { mssqlChildCollectorFailure int } -// newMSSQLCollectorFlags ... -func newMSSQLCollectorFlags(app *kingpin.Application) { - mssqlEnabledCollectors = app.Flag( - FlagMssqlEnabledCollectors, - "Comma-separated list of mssql WMI classes to use."). - Default(mssqlAvailableClassCollectors()).String() - - mssqlPrintCollectors = app.Flag( - FlagMssqlPrintCollectors, - "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", - ).Bool() +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + printCollectors := false + + c := &collector{ + mssqlEnabledCollectors: &config.EnabledCollectors, + mssqlPrintCollectors: &printCollectors, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + return &collector{ + mssqlEnabledCollectors: app.Flag( + FlagMssqlEnabledCollectors, + "Comma-separated list of mssql WMI classes to use."). + Default(ConfigDefaults.EnabledCollectors).String(), + + mssqlPrintCollectors: app.Flag( + FlagMssqlPrintCollectors, + "If true, print available mssql WMI classes and exit. Only displays if the mssql collector is enabled.", + ).Bool(), + } +} + +func (c *collector) GetName() string { + return Name } -// newMSSQLCollector ... -func newMSSQLCollector(logger log.Logger) (Collector, error) { - const subsystem = "mssql" - logger = log.With(logger, "collector", subsystem) +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} - enabled := expandEnabledChildCollectors(*mssqlEnabledCollectors) - mssqlInstances := getMSSQLInstances(logger) - perfCounters := make([]string, 0, len(mssqlInstances)*len(enabled)) - for instance := range mssqlInstances { +func (c *collector) GetPerfCounter() ([]string, error) { + enabled := utils.ExpandEnabledChildCollectors(*c.mssqlEnabledCollectors) + c.mssqlInstances = getMSSQLInstances(c.logger) + perfCounters := make([]string, 0, len(c.mssqlInstances)*len(enabled)) + for instance := range c.mssqlInstances { for _, c := range enabled { perfCounters = append(perfCounters, mssqlGetPerfObjectName(instance, c)) } } - addPerfCounterDependencies(subsystem, perfCounters) - - mssqlCollector := MSSQLCollector{ - logger: logger, - // meta - mssqlScrapeDurationDesc: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "collector_duration_seconds"), - "windows_exporter: Duration of an mssql child collection.", - []string{"collector", "mssql_instance"}, - nil, - ), - mssqlScrapeSuccessDesc: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "collector_success"), - "windows_exporter: Whether a mssql child collector was successful.", - []string{"collector", "mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerAccessMethods - AccessMethodsAUcleanupbatches: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_au_batch_cleanups"), - "(AccessMethods.AUcleanupbatches)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsAUcleanups: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_au_cleanups"), - "(AccessMethods.AUcleanups)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsByreferenceLobCreateCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_by_reference_lob_creates"), - "(AccessMethods.ByreferenceLobCreateCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsByreferenceLobUseCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_by_reference_lob_uses"), - "(AccessMethods.ByreferenceLobUseCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsCountLobReadahead: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_read_aheads"), - "(AccessMethods.CountLobReadahead)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsCountPullInRow: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_column_value_pulls"), - "(AccessMethods.CountPullInRow)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsCountPushOffRow: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_column_value_pushes"), - "(AccessMethods.CountPushOffRow)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsDeferreddroppedAUs: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_deferred_dropped_aus"), - "(AccessMethods.DeferreddroppedAUs)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsDeferredDroppedrowsets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_deferred_dropped_rowsets"), - "(AccessMethods.DeferredDroppedrowsets)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsDroppedrowsetcleanups: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_dropped_rowset_cleanups"), - "(AccessMethods.Droppedrowsetcleanups)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsDroppedrowsetsskipped: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_dropped_rowset_skips"), - "(AccessMethods.Droppedrowsetsskipped)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsExtentDeallocations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_extent_deallocations"), - "(AccessMethods.ExtentDeallocations)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsExtentsAllocated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_extent_allocations"), - "(AccessMethods.ExtentsAllocated)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsFailedAUcleanupbatches: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_au_batch_cleanup_failures"), - "(AccessMethods.FailedAUcleanupbatches)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsFailedleafpagecookie: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_leaf_page_cookie_failures"), - "(AccessMethods.Failedleafpagecookie)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsFailedtreepagecookie: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_tree_page_cookie_failures"), - "(AccessMethods.Failedtreepagecookie)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsForwardedRecords: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_forwarded_records"), - "(AccessMethods.ForwardedRecords)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsFreeSpacePageFetches: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_free_space_page_fetches"), - "(AccessMethods.FreeSpacePageFetches)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsFreeSpaceScans: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_free_space_scans"), - "(AccessMethods.FreeSpaceScans)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsFullScans: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_full_scans"), - "(AccessMethods.FullScans)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsIndexSearches: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_index_searches"), - "(AccessMethods.IndexSearches)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsInSysXactwaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_insysxact_waits"), - "(AccessMethods.InSysXactwaits)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsLobHandleCreateCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_handle_creates"), - "(AccessMethods.LobHandleCreateCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsLobHandleDestroyCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_handle_destroys"), - "(AccessMethods.LobHandleDestroyCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsLobSSProviderCreateCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_ss_provider_creates"), - "(AccessMethods.LobSSProviderCreateCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsLobSSProviderDestroyCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_ss_provider_destroys"), - "(AccessMethods.LobSSProviderDestroyCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsLobSSProviderTruncationCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_lob_ss_provider_truncations"), - "(AccessMethods.LobSSProviderTruncationCount)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsMixedpageallocations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_mixed_page_allocations"), - "(AccessMethods.MixedpageallocationsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsPagecompressionattempts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_compression_attempts"), - "(AccessMethods.PagecompressionattemptsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsPageDeallocations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_deallocations"), - "(AccessMethods.PageDeallocationsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsPagesAllocated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_allocations"), - "(AccessMethods.PagesAllocatedPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsPagescompressed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_compressions"), - "(AccessMethods.PagescompressedPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsPageSplits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_page_splits"), - "(AccessMethods.PageSplitsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsProbeScans: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_probe_scans"), - "(AccessMethods.ProbeScansPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsRangeScans: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_range_scans"), - "(AccessMethods.RangeScansPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsScanPointRevalidations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_scan_point_revalidations"), - "(AccessMethods.ScanPointRevalidationsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsSkippedGhostedRecords: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_ghost_record_skips"), - "(AccessMethods.SkippedGhostedRecordsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsTableLockEscalations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_table_lock_escalations"), - "(AccessMethods.TableLockEscalationsPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsUsedleafpagecookie: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_leaf_page_cookie_uses"), - "(AccessMethods.Usedleafpagecookie)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsUsedtreepagecookie: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_tree_page_cookie_uses"), - "(AccessMethods.Usedtreepagecookie)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsWorkfilesCreated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_workfile_creates"), - "(AccessMethods.WorkfilesCreatedPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsWorktablesCreated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_worktables_creates"), - "(AccessMethods.WorktablesCreatedPersec)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsWorktablesFromCacheHits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_worktables_from_cache_hits"), - "(AccessMethods.WorktablesFromCacheRatio)", - []string{"mssql_instance"}, - nil, - ), - AccessMethodsWorktablesFromCacheLookups: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accessmethods_worktables_from_cache_lookups"), - "(AccessMethods.WorktablesFromCacheRatio_Base)", - []string{"mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerAvailabilityReplica - AvailReplicaBytesReceivedfromReplica: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_received_from_replica_bytes"), - "(AvailabilityReplica.BytesReceivedfromReplica)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaBytesSenttoReplica: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_sent_to_replica_bytes"), - "(AvailabilityReplica.BytesSenttoReplica)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaBytesSenttoTransport: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_sent_to_transport_bytes"), - "(AvailabilityReplica.BytesSenttoTransport)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaFlowControl: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_initiated_flow_controls"), - "(AvailabilityReplica.FlowControl)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaFlowControlTimems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_flow_control_wait_seconds"), - "(AvailabilityReplica.FlowControlTimems)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaReceivesfromReplica: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_receives_from_replica"), - "(AvailabilityReplica.ReceivesfromReplica)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaResentMessages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_resent_messages"), - "(AvailabilityReplica.ResentMessages)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaSendstoReplica: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_sends_to_replica"), - "(AvailabilityReplica.SendstoReplica)", - []string{"mssql_instance", "replica"}, - nil, - ), - AvailReplicaSendstoTransport: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "availreplica_sends_to_transport"), - "(AvailabilityReplica.SendstoTransport)", - []string{"mssql_instance", "replica"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerBufferManager - BufManBackgroundwriterpages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_background_writer_pages"), - "(BufferManager.Backgroundwriterpages)", - []string{"mssql_instance"}, - nil, - ), - BufManBuffercachehits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_buffer_cache_hits"), - "(BufferManager.Buffercachehitratio)", - []string{"mssql_instance"}, - nil, - ), - BufManBuffercachelookups: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_buffer_cache_lookups"), - "(BufferManager.Buffercachehitratio_Base)", - []string{"mssql_instance"}, - nil, - ), - BufManCheckpointpages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_checkpoint_pages"), - "(BufferManager.Checkpointpages)", - []string{"mssql_instance"}, - nil, - ), - BufManDatabasepages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_database_pages"), - "(BufferManager.Databasepages)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionallocatedpages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_allocated_pages"), - "(BufferManager.Extensionallocatedpages)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionfreepages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_free_pages"), - "(BufferManager.Extensionfreepages)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensioninuseaspercentage: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_in_use_as_percentage"), - "(BufferManager.Extensioninuseaspercentage)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionoutstandingIOcounter: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_outstanding_io"), - "(BufferManager.ExtensionoutstandingIOcounter)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionpageevictions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_evictions"), - "(BufferManager.Extensionpageevictions)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionpagereads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_reads"), - "(BufferManager.Extensionpagereads)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionpageunreferencedtime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_unreferenced_seconds"), - "(BufferManager.Extensionpageunreferencedtime)", - []string{"mssql_instance"}, - nil, - ), - BufManExtensionpagewrites: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_extension_page_writes"), - "(BufferManager.Extensionpagewrites)", - []string{"mssql_instance"}, - nil, - ), - BufManFreeliststalls: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_free_list_stalls"), - "(BufferManager.Freeliststalls)", - []string{"mssql_instance"}, - nil, - ), - BufManIntegralControllerSlope: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_integral_controller_slope"), - "(BufferManager.IntegralControllerSlope)", - []string{"mssql_instance"}, - nil, - ), - BufManLazywrites: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_lazywrites"), - "(BufferManager.Lazywrites)", - []string{"mssql_instance"}, - nil, - ), - BufManPagelifeexpectancy: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_page_life_expectancy_seconds"), - "(BufferManager.Pagelifeexpectancy)", - []string{"mssql_instance"}, - nil, - ), - BufManPagelookups: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_page_lookups"), - "(BufferManager.Pagelookups)", - []string{"mssql_instance"}, - nil, - ), - BufManPagereads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_page_reads"), - "(BufferManager.Pagereads)", - []string{"mssql_instance"}, - nil, - ), - BufManPagewrites: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_page_writes"), - "(BufferManager.Pagewrites)", - []string{"mssql_instance"}, - nil, - ), - BufManReadaheadpages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_read_ahead_pages"), - "(BufferManager.Readaheadpages)", - []string{"mssql_instance"}, - nil, - ), - BufManReadaheadtime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_read_ahead_issuing_seconds"), - "(BufferManager.Readaheadtime)", - []string{"mssql_instance"}, - nil, - ), - BufManTargetpages: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bufman_target_pages"), - "(BufferManager.Targetpages)", - []string{"mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerDatabaseReplica - DBReplicaDatabaseFlowControlDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_database_flow_control_wait_seconds"), - "(DatabaseReplica.DatabaseFlowControlDelay)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaDatabaseFlowControls: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_database_initiated_flow_controls"), - "(DatabaseReplica.DatabaseFlowControls)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaFileBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_received_file_bytes"), - "(DatabaseReplica.FileBytesReceived)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaGroupCommits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_group_commits"), - "(DatabaseReplica.GroupCommits)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaGroupCommitTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_group_commit_stall_seconds"), - "(DatabaseReplica.GroupCommitTime)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogApplyPendingQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_apply_pending_queue"), - "(DatabaseReplica.LogApplyPendingQueue)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogApplyReadyQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_apply_ready_queue"), - "(DatabaseReplica.LogApplyReadyQueue)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogBytesCompressed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compressed_bytes"), - "(DatabaseReplica.LogBytesCompressed)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogBytesDecompressed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_decompressed_bytes"), - "(DatabaseReplica.LogBytesDecompressed)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_received_bytes"), - "(DatabaseReplica.LogBytesReceived)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogCompressionCachehits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compression_cachehits"), - "(DatabaseReplica.LogCompressionCachehits)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogCompressionCachemisses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compression_cachemisses"), - "(DatabaseReplica.LogCompressionCachemisses)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogCompressions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_compressions"), - "(DatabaseReplica.LogCompressions)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogDecompressions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_decompressions"), - "(DatabaseReplica.LogDecompressions)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogremainingforundo: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_remaining_for_undo"), - "(DatabaseReplica.Logremainingforundo)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaLogSendQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_log_send_queue"), - "(DatabaseReplica.LogSendQueue)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaMirroredWriteTransactions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_mirrored_write_transactions"), - "(DatabaseReplica.MirroredWriteTransactions)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaRecoveryQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_recovery_queue_records"), - "(DatabaseReplica.RecoveryQueue)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaRedoblocked: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redo_blocks"), - "(DatabaseReplica.Redoblocked)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaRedoBytesRemaining: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redo_remaining_bytes"), - "(DatabaseReplica.RedoBytesRemaining)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaRedoneBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redone_bytes"), - "(DatabaseReplica.RedoneBytes)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaRedones: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_redones"), - "(DatabaseReplica.Redones)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaTotalLogrequiringundo: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_total_log_requiring_undo"), - "(DatabaseReplica.TotalLogrequiringundo)", - []string{"mssql_instance", "replica"}, - nil, - ), - DBReplicaTransactionDelay: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dbreplica_transaction_delay_seconds"), - "(DatabaseReplica.TransactionDelay)", - []string{"mssql_instance", "replica"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerDatabases - DatabasesActiveParallelredothreads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_active_parallel_redo_threads"), - "(Databases.ActiveParallelredothreads)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesActiveTransactions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_active_transactions"), - "(Databases.ActiveTransactions)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesBackupPerRestoreThroughput: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_backup_restore_operations"), - "(Databases.BackupPerRestoreThroughput)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesBulkCopyRows: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_bulk_copy_rows"), - "(Databases.BulkCopyRows)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesBulkCopyThroughput: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_bulk_copy_bytes"), - "(Databases.BulkCopyThroughput)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesCommittableentries: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_commit_table_entries"), - "(Databases.Committableentries)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesDataFilesSizeKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_data_files_size_bytes"), - "(Databases.DataFilesSizeKB)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesDBCCLogicalScanBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_dbcc_logical_scan_bytes"), - "(Databases.DBCCLogicalScanBytes)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesGroupCommitTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_group_commit_stall_seconds"), - "(Databases.GroupCommitTime)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogBytesFlushed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_flushed_bytes"), - "(Databases.LogBytesFlushed)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogCacheHits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_cache_hits"), - "(Databases.LogCacheHitRatio)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogCacheLookups: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_cache_lookups"), - "(Databases.LogCacheHitRatio_Base)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogCacheReads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_cache_reads"), - "(Databases.LogCacheReads)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogFilesSizeKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_files_size_bytes"), - "(Databases.LogFilesSizeKB)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogFilesUsedSizeKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_files_used_size_bytes"), - "(Databases.LogFilesUsedSizeKB)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogFlushes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_flushes"), - "(Databases.LogFlushes)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogFlushWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_flush_waits"), - "(Databases.LogFlushWaits)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogFlushWaitTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_flush_wait_seconds"), - "(Databases.LogFlushWaitTime)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogFlushWriteTimems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_flush_write_seconds"), - "(Databases.LogFlushWriteTimems)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogGrowths: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_growths"), - "(Databases.LogGrowths)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolCacheMisses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_cache_misses"), - "(Databases.LogPoolCacheMisses)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolDiskReads: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_disk_reads"), - "(Databases.LogPoolDiskReads)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolHashDeletes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_hash_deletes"), - "(Databases.LogPoolHashDeletes)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolHashInserts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_hash_inserts"), - "(Databases.LogPoolHashInserts)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolInvalidHashEntry: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_invalid_hash_entries"), - "(Databases.LogPoolInvalidHashEntry)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolLogScanPushes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_log_scan_pushes"), - "(Databases.LogPoolLogScanPushes)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolLogWriterPushes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_log_writer_pushes"), - "(Databases.LogPoolLogWriterPushes)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolPushEmptyFreePool: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_empty_free_pool_pushes"), - "(Databases.LogPoolPushEmptyFreePool)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolPushLowMemory: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_low_memory_pushes"), - "(Databases.LogPoolPushLowMemory)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolPushNoFreeBuffer: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_no_free_buffer_pushes"), - "(Databases.LogPoolPushNoFreeBuffer)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolReqBehindTrunc: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_req_behind_trunc"), - "(Databases.LogPoolReqBehindTrunc)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolRequestsOldVLF: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_requests_old_vlf"), - "(Databases.LogPoolRequestsOldVLF)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_requests"), - "(Databases.LogPoolRequests)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolTotalActiveLogSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_total_active_log_bytes"), - "(Databases.LogPoolTotalActiveLogSize)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogPoolTotalSharedPoolSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_pool_total_shared_pool_bytes"), - "(Databases.LogPoolTotalSharedPoolSize)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogShrinks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_shrinks"), - "(Databases.LogShrinks)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesLogTruncations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_truncations"), - "(Databases.LogTruncations)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesPercentLogUsed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_log_used_percent"), - "(Databases.PercentLogUsed)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesReplPendingXacts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_pending_repl_transactions"), - "(Databases.ReplPendingTransactions)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesReplTransRate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_repl_transactions"), - "(Databases.ReplTranactions)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesShrinkDataMovementBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_shrink_data_movement_bytes"), - "(Databases.ShrinkDataMovementBytes)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesTrackedtransactions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_tracked_transactions"), - "(Databases.Trackedtransactions)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesTransactions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_transactions"), - "(Databases.Transactions)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesWriteTransactions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_write_transactions"), - "(Databases.WriteTransactions)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesXTPControllerDLCLatencyPerFetch: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_controller_dlc_fetch_latency_seconds"), - "(Databases.XTPControllerDLCLatencyPerFetch)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesXTPControllerDLCPeakLatency: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_controller_dlc_peak_latency_seconds"), - "(Databases.XTPControllerDLCPeakLatency)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesXTPControllerLogProcessed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_controller_log_processed_bytes"), - "(Databases.XTPControllerLogProcessed)", - []string{"mssql_instance", "database"}, - nil, - ), - DatabasesXTPMemoryUsedKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "databases_xtp_memory_used_bytes"), - "(Databases.XTPMemoryUsedKB)", - []string{"mssql_instance", "database"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerGeneralStatistics - GenStatsActiveTempTables: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_active_temp_tables"), - "(GeneralStatistics.ActiveTempTables)", - []string{"mssql_instance"}, - nil, - ), - GenStatsConnectionReset: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_connection_resets"), - "(GeneralStatistics.ConnectionReset)", - []string{"mssql_instance"}, - nil, - ), - GenStatsEventNotificationsDelayedDrop: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_event_notifications_delayed_drop"), - "(GeneralStatistics.EventNotificationsDelayedDrop)", - []string{"mssql_instance"}, - nil, - ), - GenStatsHTTPAuthenticatedRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_http_authenticated_requests"), - "(GeneralStatistics.HTTPAuthenticatedRequests)", - []string{"mssql_instance"}, - nil, - ), - GenStatsLogicalConnections: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_logical_connections"), - "(GeneralStatistics.LogicalConnections)", - []string{"mssql_instance"}, - nil, - ), - GenStatsLogins: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_logins"), - "(GeneralStatistics.Logins)", - []string{"mssql_instance"}, - nil, - ), - GenStatsLogouts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_logouts"), - "(GeneralStatistics.Logouts)", - []string{"mssql_instance"}, - nil, - ), - GenStatsMarsDeadlocks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_mars_deadlocks"), - "(GeneralStatistics.MarsDeadlocks)", - []string{"mssql_instance"}, - nil, - ), - GenStatsNonatomicyieldrate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_non_atomic_yields"), - "(GeneralStatistics.Nonatomicyields)", - []string{"mssql_instance"}, - nil, - ), - GenStatsProcessesblocked: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_blocked_processes"), - "(GeneralStatistics.Processesblocked)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSOAPEmptyRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_empty_requests"), - "(GeneralStatistics.SOAPEmptyRequests)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSOAPMethodInvocations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_method_invocations"), - "(GeneralStatistics.SOAPMethodInvocations)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSOAPSessionInitiateRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_session_initiate_requests"), - "(GeneralStatistics.SOAPSessionInitiateRequests)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSOAPSessionTerminateRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_soap_session_terminate_requests"), - "(GeneralStatistics.SOAPSessionTerminateRequests)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSOAPSQLRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_soapsql_requests"), - "(GeneralStatistics.SOAPSQLRequests)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSOAPWSDLRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_soapwsdl_requests"), - "(GeneralStatistics.SOAPWSDLRequests)", - []string{"mssql_instance"}, - nil, - ), - GenStatsSQLTraceIOProviderLockWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_sql_trace_io_provider_lock_waits"), - "(GeneralStatistics.SQLTraceIOProviderLockWaits)", - []string{"mssql_instance"}, - nil, - ), - GenStatsTempdbrecoveryunitid: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_tempdb_recovery_unit_ids_generated"), - "(GeneralStatistics.Tempdbrecoveryunitid)", - []string{"mssql_instance"}, - nil, - ), - GenStatsTempdbrowsetid: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_tempdb_rowset_ids_generated"), - "(GeneralStatistics.Tempdbrowsetid)", - []string{"mssql_instance"}, - nil, - ), - GenStatsTempTablesCreationRate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_temp_tables_creations"), - "(GeneralStatistics.TempTablesCreations)", - []string{"mssql_instance"}, - nil, - ), - GenStatsTempTablesForDestruction: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_temp_tables_awaiting_destruction"), - "(GeneralStatistics.TempTablesForDestruction)", - []string{"mssql_instance"}, - nil, - ), - GenStatsTraceEventNotificationQueue: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_trace_event_notification_queue_size"), - "(GeneralStatistics.TraceEventNotificationQueue)", - []string{"mssql_instance"}, - nil, - ), - GenStatsTransactions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_transactions"), - "(GeneralStatistics.Transactions)", - []string{"mssql_instance"}, - nil, - ), - GenStatsUserConnections: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "genstats_user_connections"), - "(GeneralStatistics.UserConnections)", - []string{"mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerLocks - LocksWaitTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_wait_time_seconds"), - "(Locks.AverageWaitTimems Total time in seconds which locks have been holding resources)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_count"), - "(Locks.AverageWaitTimems_Base count of how often requests have run into locks)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksLockRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_lock_requests"), - "(Locks.LockRequests)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksLockTimeouts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_lock_timeouts"), - "(Locks.LockTimeouts)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksLockTimeoutstimeout0: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_lock_timeouts_excluding_NOWAIT"), - "(Locks.LockTimeoutstimeout0)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksLockWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_lock_waits"), - "(Locks.LockWaits)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksLockWaitTimems: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_lock_wait_seconds"), - "(Locks.LockWaitTimems)", - []string{"mssql_instance", "resource"}, - nil, - ), - LocksNumberofDeadlocks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "locks_deadlocks"), - "(Locks.NumberofDeadlocks)", - []string{"mssql_instance", "resource"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerMemoryManager - MemMgrConnectionMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_connection_memory_bytes"), - "(MemoryManager.ConnectionMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrDatabaseCacheMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_database_cache_memory_bytes"), - "(MemoryManager.DatabaseCacheMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrExternalbenefitofmemory: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_external_benefit_of_memory"), - "(MemoryManager.Externalbenefitofmemory)", - []string{"mssql_instance"}, - nil, - ), - MemMgrFreeMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_free_memory_bytes"), - "(MemoryManager.FreeMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrGrantedWorkspaceMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_granted_workspace_memory_bytes"), - "(MemoryManager.GrantedWorkspaceMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrLockBlocks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_lock_blocks"), - "(MemoryManager.LockBlocks)", - []string{"mssql_instance"}, - nil, - ), - MemMgrLockBlocksAllocated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_allocated_lock_blocks"), - "(MemoryManager.LockBlocksAllocated)", - []string{"mssql_instance"}, - nil, - ), - MemMgrLockMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_lock_memory_bytes"), - "(MemoryManager.LockMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrLockOwnerBlocks: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_lock_owner_blocks"), - "(MemoryManager.LockOwnerBlocks)", - []string{"mssql_instance"}, - nil, - ), - MemMgrLockOwnerBlocksAllocated: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_allocated_lock_owner_blocks"), - "(MemoryManager.LockOwnerBlocksAllocated)", - []string{"mssql_instance"}, - nil, - ), - MemMgrLogPoolMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_log_pool_memory_bytes"), - "(MemoryManager.LogPoolMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrMaximumWorkspaceMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_maximum_workspace_memory_bytes"), - "(MemoryManager.MaximumWorkspaceMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrMemoryGrantsOutstanding: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_outstanding_memory_grants"), - "(MemoryManager.MemoryGrantsOutstanding)", - []string{"mssql_instance"}, - nil, - ), - MemMgrMemoryGrantsPending: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_pending_memory_grants"), - "(MemoryManager.MemoryGrantsPending)", - []string{"mssql_instance"}, - nil, - ), - MemMgrOptimizerMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_optimizer_memory_bytes"), - "(MemoryManager.OptimizerMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrReservedServerMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_reserved_server_memory_bytes"), - "(MemoryManager.ReservedServerMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrSQLCacheMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_sql_cache_memory_bytes"), - "(MemoryManager.SQLCacheMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrStolenServerMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_stolen_server_memory_bytes"), - "(MemoryManager.StolenServerMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrTargetServerMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_target_server_memory_bytes"), - "(MemoryManager.TargetServerMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - MemMgrTotalServerMemoryKB: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "memmgr_total_server_memory_bytes"), - "(MemoryManager.TotalServerMemoryKB)", - []string{"mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerSQLStatistics - SQLStatsAutoParamAttempts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_auto_parameterization_attempts"), - "(SQLStatistics.AutoParamAttempts)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsBatchRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_batch_requests"), - "(SQLStatistics.BatchRequests)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsFailedAutoParams: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_failed_auto_parameterization_attempts"), - "(SQLStatistics.FailedAutoParams)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsForcedParameterizations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_forced_parameterizations"), - "(SQLStatistics.ForcedParameterizations)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsGuidedplanexecutions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_guided_plan_executions"), - "(SQLStatistics.Guidedplanexecutions)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsMisguidedplanexecutions: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_misguided_plan_executions"), - "(SQLStatistics.Misguidedplanexecutions)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsSafeAutoParams: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_safe_auto_parameterization_attempts"), - "(SQLStatistics.SafeAutoParams)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsSQLAttentionrate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_sql_attentions"), - "(SQLStatistics.SQLAttentions)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsSQLCompilations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_sql_compilations"), - "(SQLStatistics.SQLCompilations)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsSQLReCompilations: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_sql_recompilations"), - "(SQLStatistics.SQLReCompilations)", - []string{"mssql_instance"}, - nil, - ), - SQLStatsUnsafeAutoParams: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sqlstats_unsafe_auto_parameterization_attempts"), - "(SQLStatistics.UnsafeAutoParams)", - []string{"mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerSQLErrors - SQLErrorsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "sql_errors_total"), - "(SQLErrors.Total)", - []string{"mssql_instance", "resource"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerTransactions - TransactionsTempDbFreeSpaceBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_tempdb_free_space_bytes"), - "(Transactions.FreeSpaceInTempDbKB)", - []string{"mssql_instance"}, - nil, - ), - TransactionsLongestTransactionRunningSeconds: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_longest_transaction_running_seconds"), - "(Transactions.LongestTransactionRunningTime)", - []string{"mssql_instance"}, - nil, - ), - TransactionsNonSnapshotVersionActiveTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_nonsnapshot_version_active_total"), - "(Transactions.NonSnapshotVersionTransactions)", - []string{"mssql_instance"}, - nil, - ), - TransactionsSnapshotActiveTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_snapshot_active_total"), - "(Transactions.SnapshotTransactions)", - []string{"mssql_instance"}, - nil, - ), - TransactionsActive: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_active"), - "(Transactions.Transactions)", - []string{"mssql_instance"}, - nil, - ), - TransactionsUpdateConflictsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_update_conflicts_total"), - "(Transactions.UpdateConflictRatio)", - []string{"mssql_instance"}, - nil, - ), - TransactionsUpdateSnapshotActiveTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_update_snapshot_active_total"), - "(Transactions.UpdateSnapshotTransactions)", - []string{"mssql_instance"}, - nil, - ), - TransactionsVersionCleanupRateBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_version_cleanup_rate_bytes"), - "(Transactions.VersionCleanupRateKBs)", - []string{"mssql_instance"}, - nil, - ), - TransactionsVersionGenerationRateBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_version_generation_rate_bytes"), - "(Transactions.VersionGenerationRateKBs)", - []string{"mssql_instance"}, - nil, - ), - TransactionsVersionStoreSizeBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_size_bytes"), - "(Transactions.VersionStoreSizeKB)", - []string{"mssql_instance"}, - nil, - ), - TransactionsVersionStoreUnits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_units"), - "(Transactions.VersionStoreUnitCount)", - []string{"mssql_instance"}, - nil, - ), - TransactionsVersionStoreCreationUnits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_creation_units"), - "(Transactions.VersionStoreUnitCreation)", - []string{"mssql_instance"}, - nil, - ), - TransactionsVersionStoreTruncationUnits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "transactions_version_store_truncation_units"), - "(Transactions.VersionStoreUnitTruncation)", - []string{"mssql_instance"}, - nil, - ), - - // Win32_PerfRawData_{instance}_SQLServerWaitStatistics - WaitStatsLockWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_lock_waits"), - "(WaitStats.LockWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsMemoryGrantQueueWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_memory_grant_queue_waits"), - "(WaitStats.MemoryGrantQueueWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsThreadSafeMemoryObjectsWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_thread_safe_memory_objects_waits"), - "(WaitStats.ThreadSafeMemoryObjectsWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsLogWriteWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_log_write_waits"), - "(WaitStats.LogWriteWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsLogBufferWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_log_buffer_waits"), - "(WaitStats.LogBufferWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsNetworkIOWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_network_io_waits"), - "(WaitStats.NetworkIOWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsPageIOLatchWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_page_io_latch_waits"), - "(WaitStats.PageIOLatchWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsPageLatchWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_page_latch_waits"), - "(WaitStats.PageLatchWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsNonpageLatchWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_nonpage_latch_waits"), - "(WaitStats.NonpageLatchWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsWaitForTheWorkerWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_wait_for_the_worker_waits"), - "(WaitStats.WaitForTheWorkerWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsWorkspaceSynchronizationWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_workspace_synchronization_waits"), - "(WaitStats.WorkspaceSynchronizationWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - WaitStatsTransactionOwnershipWaits: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "waitstats_transaction_ownership_waits"), - "(WaitStats.TransactionOwnershipWaits)", - []string{"mssql_instance", "item"}, - nil, - ), - - mssqlInstances: mssqlInstances, - } - mssqlCollector.mssqlCollectors = mssqlCollector.getMSSQLCollectors() + return perfCounters, nil +} + +func (c *collector) Build() error { + // meta + c.mssqlScrapeDurationDesc = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "collector_duration_seconds"), + "windows_exporter: Duration of an mssql child collection.", + []string{"collector", "mssql_instance"}, + nil, + ) + c.mssqlScrapeSuccessDesc = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "collector_success"), + "windows_exporter: Whether a mssql child collector was successful.", + []string{"collector", "mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerAccessMethods + c.AccessMethodsAUcleanupbatches = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_au_batch_cleanups"), + "(AccessMethods.AUcleanupbatches)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsAUcleanups = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_au_cleanups"), + "(AccessMethods.AUcleanups)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsByreferenceLobCreateCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_by_reference_lob_creates"), + "(AccessMethods.ByreferenceLobCreateCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsByreferenceLobUseCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_by_reference_lob_uses"), + "(AccessMethods.ByreferenceLobUseCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsCountLobReadahead = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_read_aheads"), + "(AccessMethods.CountLobReadahead)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsCountPullInRow = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_column_value_pulls"), + "(AccessMethods.CountPullInRow)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsCountPushOffRow = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_column_value_pushes"), + "(AccessMethods.CountPushOffRow)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsDeferreddroppedAUs = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_deferred_dropped_aus"), + "(AccessMethods.DeferreddroppedAUs)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsDeferredDroppedrowsets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_deferred_dropped_rowsets"), + "(AccessMethods.DeferredDroppedrowsets)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsDroppedrowsetcleanups = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_dropped_rowset_cleanups"), + "(AccessMethods.Droppedrowsetcleanups)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsDroppedrowsetsskipped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_dropped_rowset_skips"), + "(AccessMethods.Droppedrowsetsskipped)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsExtentDeallocations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_extent_deallocations"), + "(AccessMethods.ExtentDeallocations)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsExtentsAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_extent_allocations"), + "(AccessMethods.ExtentsAllocated)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsFailedAUcleanupbatches = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_au_batch_cleanup_failures"), + "(AccessMethods.FailedAUcleanupbatches)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsFailedleafpagecookie = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_leaf_page_cookie_failures"), + "(AccessMethods.Failedleafpagecookie)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsFailedtreepagecookie = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_tree_page_cookie_failures"), + "(AccessMethods.Failedtreepagecookie)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsForwardedRecords = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_forwarded_records"), + "(AccessMethods.ForwardedRecords)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsFreeSpacePageFetches = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_free_space_page_fetches"), + "(AccessMethods.FreeSpacePageFetches)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsFreeSpaceScans = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_free_space_scans"), + "(AccessMethods.FreeSpaceScans)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsFullScans = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_full_scans"), + "(AccessMethods.FullScans)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsIndexSearches = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_index_searches"), + "(AccessMethods.IndexSearches)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsInSysXactwaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_insysxact_waits"), + "(AccessMethods.InSysXactwaits)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsLobHandleCreateCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_handle_creates"), + "(AccessMethods.LobHandleCreateCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsLobHandleDestroyCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_handle_destroys"), + "(AccessMethods.LobHandleDestroyCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsLobSSProviderCreateCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_ss_provider_creates"), + "(AccessMethods.LobSSProviderCreateCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsLobSSProviderDestroyCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_ss_provider_destroys"), + "(AccessMethods.LobSSProviderDestroyCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsLobSSProviderTruncationCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_lob_ss_provider_truncations"), + "(AccessMethods.LobSSProviderTruncationCount)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsMixedpageallocations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_mixed_page_allocations"), + "(AccessMethods.MixedpageallocationsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsPagecompressionattempts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_compression_attempts"), + "(AccessMethods.PagecompressionattemptsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsPageDeallocations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_deallocations"), + "(AccessMethods.PageDeallocationsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsPagesAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_allocations"), + "(AccessMethods.PagesAllocatedPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsPagescompressed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_compressions"), + "(AccessMethods.PagescompressedPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsPageSplits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_page_splits"), + "(AccessMethods.PageSplitsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsProbeScans = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_probe_scans"), + "(AccessMethods.ProbeScansPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsRangeScans = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_range_scans"), + "(AccessMethods.RangeScansPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsScanPointRevalidations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_scan_point_revalidations"), + "(AccessMethods.ScanPointRevalidationsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsSkippedGhostedRecords = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_ghost_record_skips"), + "(AccessMethods.SkippedGhostedRecordsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsTableLockEscalations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_table_lock_escalations"), + "(AccessMethods.TableLockEscalationsPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsUsedleafpagecookie = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_leaf_page_cookie_uses"), + "(AccessMethods.Usedleafpagecookie)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsUsedtreepagecookie = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_tree_page_cookie_uses"), + "(AccessMethods.Usedtreepagecookie)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsWorkfilesCreated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_workfile_creates"), + "(AccessMethods.WorkfilesCreatedPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsWorktablesCreated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_worktables_creates"), + "(AccessMethods.WorktablesCreatedPersec)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsWorktablesFromCacheHits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_worktables_from_cache_hits"), + "(AccessMethods.WorktablesFromCacheRatio)", + []string{"mssql_instance"}, + nil, + ) + c.AccessMethodsWorktablesFromCacheLookups = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accessmethods_worktables_from_cache_lookups"), + "(AccessMethods.WorktablesFromCacheRatio_Base)", + []string{"mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerAvailabilityReplica + c.AvailReplicaBytesReceivedfromReplica = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_received_from_replica_bytes"), + "(AvailabilityReplica.BytesReceivedfromReplica)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaBytesSenttoReplica = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_sent_to_replica_bytes"), + "(AvailabilityReplica.BytesSenttoReplica)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaBytesSenttoTransport = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_sent_to_transport_bytes"), + "(AvailabilityReplica.BytesSenttoTransport)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaFlowControl = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_initiated_flow_controls"), + "(AvailabilityReplica.FlowControl)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaFlowControlTimems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_flow_control_wait_seconds"), + "(AvailabilityReplica.FlowControlTimems)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaReceivesfromReplica = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_receives_from_replica"), + "(AvailabilityReplica.ReceivesfromReplica)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaResentMessages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_resent_messages"), + "(AvailabilityReplica.ResentMessages)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaSendstoReplica = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_sends_to_replica"), + "(AvailabilityReplica.SendstoReplica)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.AvailReplicaSendstoTransport = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "availreplica_sends_to_transport"), + "(AvailabilityReplica.SendstoTransport)", + []string{"mssql_instance", "replica"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerBufferManager + c.BufManBackgroundwriterpages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_background_writer_pages"), + "(BufferManager.Backgroundwriterpages)", + []string{"mssql_instance"}, + nil, + ) + c.BufManBuffercachehits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_buffer_cache_hits"), + "(BufferManager.Buffercachehitratio)", + []string{"mssql_instance"}, + nil, + ) + c.BufManBuffercachelookups = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_buffer_cache_lookups"), + "(BufferManager.Buffercachehitratio_Base)", + []string{"mssql_instance"}, + nil, + ) + c.BufManCheckpointpages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_checkpoint_pages"), + "(BufferManager.Checkpointpages)", + []string{"mssql_instance"}, + nil, + ) + c.BufManDatabasepages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_database_pages"), + "(BufferManager.Databasepages)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionallocatedpages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_allocated_pages"), + "(BufferManager.Extensionallocatedpages)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionfreepages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_free_pages"), + "(BufferManager.Extensionfreepages)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensioninuseaspercentage = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_in_use_as_percentage"), + "(BufferManager.Extensioninuseaspercentage)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionoutstandingIOcounter = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_outstanding_io"), + "(BufferManager.ExtensionoutstandingIOcounter)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionpageevictions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_page_evictions"), + "(BufferManager.Extensionpageevictions)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionpagereads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_page_reads"), + "(BufferManager.Extensionpagereads)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionpageunreferencedtime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_page_unreferenced_seconds"), + "(BufferManager.Extensionpageunreferencedtime)", + []string{"mssql_instance"}, + nil, + ) + c.BufManExtensionpagewrites = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_extension_page_writes"), + "(BufferManager.Extensionpagewrites)", + []string{"mssql_instance"}, + nil, + ) + c.BufManFreeliststalls = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_free_list_stalls"), + "(BufferManager.Freeliststalls)", + []string{"mssql_instance"}, + nil, + ) + c.BufManIntegralControllerSlope = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_integral_controller_slope"), + "(BufferManager.IntegralControllerSlope)", + []string{"mssql_instance"}, + nil, + ) + c.BufManLazywrites = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_lazywrites"), + "(BufferManager.Lazywrites)", + []string{"mssql_instance"}, + nil, + ) + c.BufManPagelifeexpectancy = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_page_life_expectancy_seconds"), + "(BufferManager.Pagelifeexpectancy)", + []string{"mssql_instance"}, + nil, + ) + c.BufManPagelookups = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_page_lookups"), + "(BufferManager.Pagelookups)", + []string{"mssql_instance"}, + nil, + ) + c.BufManPagereads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_page_reads"), + "(BufferManager.Pagereads)", + []string{"mssql_instance"}, + nil, + ) + c.BufManPagewrites = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_page_writes"), + "(BufferManager.Pagewrites)", + []string{"mssql_instance"}, + nil, + ) + c.BufManReadaheadpages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_read_ahead_pages"), + "(BufferManager.Readaheadpages)", + []string{"mssql_instance"}, + nil, + ) + c.BufManReadaheadtime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_read_ahead_issuing_seconds"), + "(BufferManager.Readaheadtime)", + []string{"mssql_instance"}, + nil, + ) + c.BufManTargetpages = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bufman_target_pages"), + "(BufferManager.Targetpages)", + []string{"mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerDatabaseReplica + c.DBReplicaDatabaseFlowControlDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_database_flow_control_wait_seconds"), + "(DatabaseReplica.DatabaseFlowControlDelay)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaDatabaseFlowControls = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_database_initiated_flow_controls"), + "(DatabaseReplica.DatabaseFlowControls)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaFileBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_received_file_bytes"), + "(DatabaseReplica.FileBytesReceived)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaGroupCommits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_group_commits"), + "(DatabaseReplica.GroupCommits)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaGroupCommitTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_group_commit_stall_seconds"), + "(DatabaseReplica.GroupCommitTime)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogApplyPendingQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_apply_pending_queue"), + "(DatabaseReplica.LogApplyPendingQueue)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogApplyReadyQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_apply_ready_queue"), + "(DatabaseReplica.LogApplyReadyQueue)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogBytesCompressed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_compressed_bytes"), + "(DatabaseReplica.LogBytesCompressed)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogBytesDecompressed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_decompressed_bytes"), + "(DatabaseReplica.LogBytesDecompressed)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_received_bytes"), + "(DatabaseReplica.LogBytesReceived)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogCompressionCachehits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_compression_cachehits"), + "(DatabaseReplica.LogCompressionCachehits)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogCompressionCachemisses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_compression_cachemisses"), + "(DatabaseReplica.LogCompressionCachemisses)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogCompressions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_compressions"), + "(DatabaseReplica.LogCompressions)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogDecompressions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_decompressions"), + "(DatabaseReplica.LogDecompressions)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogremainingforundo = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_remaining_for_undo"), + "(DatabaseReplica.Logremainingforundo)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaLogSendQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_log_send_queue"), + "(DatabaseReplica.LogSendQueue)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaMirroredWriteTransactions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_mirrored_write_transactions"), + "(DatabaseReplica.MirroredWriteTransactions)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaRecoveryQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_recovery_queue_records"), + "(DatabaseReplica.RecoveryQueue)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaRedoblocked = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_redo_blocks"), + "(DatabaseReplica.Redoblocked)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaRedoBytesRemaining = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_redo_remaining_bytes"), + "(DatabaseReplica.RedoBytesRemaining)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaRedoneBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_redone_bytes"), + "(DatabaseReplica.RedoneBytes)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaRedones = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_redones"), + "(DatabaseReplica.Redones)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaTotalLogrequiringundo = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_total_log_requiring_undo"), + "(DatabaseReplica.TotalLogrequiringundo)", + []string{"mssql_instance", "replica"}, + nil, + ) + c.DBReplicaTransactionDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dbreplica_transaction_delay_seconds"), + "(DatabaseReplica.TransactionDelay)", + []string{"mssql_instance", "replica"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerDatabases + c.DatabasesActiveParallelredothreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_active_parallel_redo_threads"), + "(Databases.ActiveParallelredothreads)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesActiveTransactions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_active_transactions"), + "(Databases.ActiveTransactions)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesBackupPerRestoreThroughput = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_backup_restore_operations"), + "(Databases.BackupPerRestoreThroughput)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesBulkCopyRows = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_bulk_copy_rows"), + "(Databases.BulkCopyRows)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesBulkCopyThroughput = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_bulk_copy_bytes"), + "(Databases.BulkCopyThroughput)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesCommittableentries = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_commit_table_entries"), + "(Databases.Committableentries)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesDataFilesSizeKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_data_files_size_bytes"), + "(Databases.DataFilesSizeKB)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesDBCCLogicalScanBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_dbcc_logical_scan_bytes"), + "(Databases.DBCCLogicalScanBytes)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesGroupCommitTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_group_commit_stall_seconds"), + "(Databases.GroupCommitTime)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogBytesFlushed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_flushed_bytes"), + "(Databases.LogBytesFlushed)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogCacheHits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_cache_hits"), + "(Databases.LogCacheHitRatio)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogCacheLookups = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_cache_lookups"), + "(Databases.LogCacheHitRatio_Base)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogCacheReads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_cache_reads"), + "(Databases.LogCacheReads)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogFilesSizeKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_files_size_bytes"), + "(Databases.LogFilesSizeKB)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogFilesUsedSizeKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_files_used_size_bytes"), + "(Databases.LogFilesUsedSizeKB)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogFlushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_flushes"), + "(Databases.LogFlushes)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogFlushWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_waits"), + "(Databases.LogFlushWaits)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogFlushWaitTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_wait_seconds"), + "(Databases.LogFlushWaitTime)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogFlushWriteTimems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_flush_write_seconds"), + "(Databases.LogFlushWriteTimems)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogGrowths = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_growths"), + "(Databases.LogGrowths)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolCacheMisses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_cache_misses"), + "(Databases.LogPoolCacheMisses)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolDiskReads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_disk_reads"), + "(Databases.LogPoolDiskReads)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolHashDeletes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_hash_deletes"), + "(Databases.LogPoolHashDeletes)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolHashInserts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_hash_inserts"), + "(Databases.LogPoolHashInserts)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolInvalidHashEntry = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_invalid_hash_entries"), + "(Databases.LogPoolInvalidHashEntry)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolLogScanPushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_log_scan_pushes"), + "(Databases.LogPoolLogScanPushes)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolLogWriterPushes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_log_writer_pushes"), + "(Databases.LogPoolLogWriterPushes)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolPushEmptyFreePool = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_empty_free_pool_pushes"), + "(Databases.LogPoolPushEmptyFreePool)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolPushLowMemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_low_memory_pushes"), + "(Databases.LogPoolPushLowMemory)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolPushNoFreeBuffer = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_no_free_buffer_pushes"), + "(Databases.LogPoolPushNoFreeBuffer)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolReqBehindTrunc = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_req_behind_trunc"), + "(Databases.LogPoolReqBehindTrunc)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolRequestsOldVLF = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_requests_old_vlf"), + "(Databases.LogPoolRequestsOldVLF)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_requests"), + "(Databases.LogPoolRequests)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolTotalActiveLogSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_total_active_log_bytes"), + "(Databases.LogPoolTotalActiveLogSize)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogPoolTotalSharedPoolSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_pool_total_shared_pool_bytes"), + "(Databases.LogPoolTotalSharedPoolSize)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogShrinks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_shrinks"), + "(Databases.LogShrinks)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesLogTruncations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_truncations"), + "(Databases.LogTruncations)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesPercentLogUsed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_log_used_percent"), + "(Databases.PercentLogUsed)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesReplPendingXacts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_pending_repl_transactions"), + "(Databases.ReplPendingTransactions)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesReplTransRate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_repl_transactions"), + "(Databases.ReplTranactions)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesShrinkDataMovementBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_shrink_data_movement_bytes"), + "(Databases.ShrinkDataMovementBytes)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesTrackedtransactions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_tracked_transactions"), + "(Databases.Trackedtransactions)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesTransactions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_transactions"), + "(Databases.Transactions)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesWriteTransactions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_write_transactions"), + "(Databases.WriteTransactions)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesXTPControllerDLCLatencyPerFetch = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_controller_dlc_fetch_latency_seconds"), + "(Databases.XTPControllerDLCLatencyPerFetch)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesXTPControllerDLCPeakLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_controller_dlc_peak_latency_seconds"), + "(Databases.XTPControllerDLCPeakLatency)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesXTPControllerLogProcessed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_controller_log_processed_bytes"), + "(Databases.XTPControllerLogProcessed)", + []string{"mssql_instance", "database"}, + nil, + ) + c.DatabasesXTPMemoryUsedKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "databases_xtp_memory_used_bytes"), + "(Databases.XTPMemoryUsedKB)", + []string{"mssql_instance", "database"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerGeneralStatistics + c.GenStatsActiveTempTables = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_active_temp_tables"), + "(GeneralStatistics.ActiveTempTables)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsConnectionReset = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_connection_resets"), + "(GeneralStatistics.ConnectionReset)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsEventNotificationsDelayedDrop = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_event_notifications_delayed_drop"), + "(GeneralStatistics.EventNotificationsDelayedDrop)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsHTTPAuthenticatedRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_http_authenticated_requests"), + "(GeneralStatistics.HTTPAuthenticatedRequests)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsLogicalConnections = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_logical_connections"), + "(GeneralStatistics.LogicalConnections)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsLogins = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_logins"), + "(GeneralStatistics.Logins)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsLogouts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_logouts"), + "(GeneralStatistics.Logouts)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsMarsDeadlocks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_mars_deadlocks"), + "(GeneralStatistics.MarsDeadlocks)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsNonatomicyieldrate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_non_atomic_yields"), + "(GeneralStatistics.Nonatomicyields)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsProcessesblocked = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_blocked_processes"), + "(GeneralStatistics.Processesblocked)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSOAPEmptyRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_empty_requests"), + "(GeneralStatistics.SOAPEmptyRequests)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSOAPMethodInvocations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_method_invocations"), + "(GeneralStatistics.SOAPMethodInvocations)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSOAPSessionInitiateRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_session_initiate_requests"), + "(GeneralStatistics.SOAPSessionInitiateRequests)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSOAPSessionTerminateRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_soap_session_terminate_requests"), + "(GeneralStatistics.SOAPSessionTerminateRequests)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSOAPSQLRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_soapsql_requests"), + "(GeneralStatistics.SOAPSQLRequests)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSOAPWSDLRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_soapwsdl_requests"), + "(GeneralStatistics.SOAPWSDLRequests)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsSQLTraceIOProviderLockWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_sql_trace_io_provider_lock_waits"), + "(GeneralStatistics.SQLTraceIOProviderLockWaits)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsTempdbrecoveryunitid = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_tempdb_recovery_unit_ids_generated"), + "(GeneralStatistics.Tempdbrecoveryunitid)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsTempdbrowsetid = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_tempdb_rowset_ids_generated"), + "(GeneralStatistics.Tempdbrowsetid)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsTempTablesCreationRate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_temp_tables_creations"), + "(GeneralStatistics.TempTablesCreations)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsTempTablesForDestruction = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_temp_tables_awaiting_destruction"), + "(GeneralStatistics.TempTablesForDestruction)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsTraceEventNotificationQueue = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_trace_event_notification_queue_size"), + "(GeneralStatistics.TraceEventNotificationQueue)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsTransactions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_transactions"), + "(GeneralStatistics.Transactions)", + []string{"mssql_instance"}, + nil, + ) + c.GenStatsUserConnections = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "genstats_user_connections"), + "(GeneralStatistics.UserConnections)", + []string{"mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerLocks + c.LocksWaitTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_wait_time_seconds"), + "(Locks.AverageWaitTimems Total time in seconds which locks have been holding resources)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_count"), + "(Locks.AverageWaitTimems_Base count of how often requests have run into locks)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksLockRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_lock_requests"), + "(Locks.LockRequests)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksLockTimeouts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_lock_timeouts"), + "(Locks.LockTimeouts)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksLockTimeoutstimeout0 = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_lock_timeouts_excluding_NOWAIT"), + "(Locks.LockTimeoutstimeout0)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksLockWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_lock_waits"), + "(Locks.LockWaits)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksLockWaitTimems = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_lock_wait_seconds"), + "(Locks.LockWaitTimems)", + []string{"mssql_instance", "resource"}, + nil, + ) + c.LocksNumberofDeadlocks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "locks_deadlocks"), + "(Locks.NumberofDeadlocks)", + []string{"mssql_instance", "resource"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerMemoryManager + c.MemMgrConnectionMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_connection_memory_bytes"), + "(MemoryManager.ConnectionMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrDatabaseCacheMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_database_cache_memory_bytes"), + "(MemoryManager.DatabaseCacheMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrExternalbenefitofmemory = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_external_benefit_of_memory"), + "(MemoryManager.Externalbenefitofmemory)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrFreeMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_free_memory_bytes"), + "(MemoryManager.FreeMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrGrantedWorkspaceMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_granted_workspace_memory_bytes"), + "(MemoryManager.GrantedWorkspaceMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrLockBlocks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_lock_blocks"), + "(MemoryManager.LockBlocks)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrLockBlocksAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_allocated_lock_blocks"), + "(MemoryManager.LockBlocksAllocated)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrLockMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_lock_memory_bytes"), + "(MemoryManager.LockMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrLockOwnerBlocks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_lock_owner_blocks"), + "(MemoryManager.LockOwnerBlocks)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrLockOwnerBlocksAllocated = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_allocated_lock_owner_blocks"), + "(MemoryManager.LockOwnerBlocksAllocated)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrLogPoolMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_log_pool_memory_bytes"), + "(MemoryManager.LogPoolMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrMaximumWorkspaceMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_maximum_workspace_memory_bytes"), + "(MemoryManager.MaximumWorkspaceMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrMemoryGrantsOutstanding = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_outstanding_memory_grants"), + "(MemoryManager.MemoryGrantsOutstanding)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrMemoryGrantsPending = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_pending_memory_grants"), + "(MemoryManager.MemoryGrantsPending)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrOptimizerMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_optimizer_memory_bytes"), + "(MemoryManager.OptimizerMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrReservedServerMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_reserved_server_memory_bytes"), + "(MemoryManager.ReservedServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrSQLCacheMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_sql_cache_memory_bytes"), + "(MemoryManager.SQLCacheMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrStolenServerMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_stolen_server_memory_bytes"), + "(MemoryManager.StolenServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrTargetServerMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_target_server_memory_bytes"), + "(MemoryManager.TargetServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + c.MemMgrTotalServerMemoryKB = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "memmgr_total_server_memory_bytes"), + "(MemoryManager.TotalServerMemoryKB)", + []string{"mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerSQLStatistics + c.SQLStatsAutoParamAttempts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_auto_parameterization_attempts"), + "(SQLStatistics.AutoParamAttempts)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsBatchRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_batch_requests"), + "(SQLStatistics.BatchRequests)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsFailedAutoParams = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_failed_auto_parameterization_attempts"), + "(SQLStatistics.FailedAutoParams)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsForcedParameterizations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_forced_parameterizations"), + "(SQLStatistics.ForcedParameterizations)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsGuidedplanexecutions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_guided_plan_executions"), + "(SQLStatistics.Guidedplanexecutions)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsMisguidedplanexecutions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_misguided_plan_executions"), + "(SQLStatistics.Misguidedplanexecutions)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsSafeAutoParams = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_safe_auto_parameterization_attempts"), + "(SQLStatistics.SafeAutoParams)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsSQLAttentionrate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_sql_attentions"), + "(SQLStatistics.SQLAttentions)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsSQLCompilations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_sql_compilations"), + "(SQLStatistics.SQLCompilations)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsSQLReCompilations = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_sql_recompilations"), + "(SQLStatistics.SQLReCompilations)", + []string{"mssql_instance"}, + nil, + ) + c.SQLStatsUnsafeAutoParams = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sqlstats_unsafe_auto_parameterization_attempts"), + "(SQLStatistics.UnsafeAutoParams)", + []string{"mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerSQLErrors + c.SQLErrorsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "sql_errors_total"), + "(SQLErrors.Total)", + []string{"mssql_instance", "resource"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerTransactions + c.TransactionsTempDbFreeSpaceBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_tempdb_free_space_bytes"), + "(Transactions.FreeSpaceInTempDbKB)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsLongestTransactionRunningSeconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_longest_transaction_running_seconds"), + "(Transactions.LongestTransactionRunningTime)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsNonSnapshotVersionActiveTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_nonsnapshot_version_active_total"), + "(Transactions.NonSnapshotVersionTransactions)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsSnapshotActiveTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_snapshot_active_total"), + "(Transactions.SnapshotTransactions)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsActive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_active"), + "(Transactions.Transactions)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsUpdateConflictsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_update_conflicts_total"), + "(Transactions.UpdateConflictRatio)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsUpdateSnapshotActiveTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_update_snapshot_active_total"), + "(Transactions.UpdateSnapshotTransactions)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsVersionCleanupRateBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_version_cleanup_rate_bytes"), + "(Transactions.VersionCleanupRateKBs)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsVersionGenerationRateBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_version_generation_rate_bytes"), + "(Transactions.VersionGenerationRateKBs)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsVersionStoreSizeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_version_store_size_bytes"), + "(Transactions.VersionStoreSizeKB)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsVersionStoreUnits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_version_store_units"), + "(Transactions.VersionStoreUnitCount)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsVersionStoreCreationUnits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_version_store_creation_units"), + "(Transactions.VersionStoreUnitCreation)", + []string{"mssql_instance"}, + nil, + ) + c.TransactionsVersionStoreTruncationUnits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "transactions_version_store_truncation_units"), + "(Transactions.VersionStoreUnitTruncation)", + []string{"mssql_instance"}, + nil, + ) + + // Win32_PerfRawData_{instance}_SQLServerWaitStatistics + c.WaitStatsLockWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_lock_waits"), + "(WaitStats.LockWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + + c.WaitStatsMemoryGrantQueueWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_memory_grant_queue_waits"), + "(WaitStats.MemoryGrantQueueWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsThreadSafeMemoryObjectsWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_thread_safe_memory_objects_waits"), + "(WaitStats.ThreadSafeMemoryObjectsWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsLogWriteWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_log_write_waits"), + "(WaitStats.LogWriteWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsLogBufferWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_log_buffer_waits"), + "(WaitStats.LogBufferWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsNetworkIOWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_network_io_waits"), + "(WaitStats.NetworkIOWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsPageIOLatchWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_page_io_latch_waits"), + "(WaitStats.PageIOLatchWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsPageLatchWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_page_latch_waits"), + "(WaitStats.PageLatchWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsNonpageLatchWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_nonpage_latch_waits"), + "(WaitStats.NonpageLatchWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsWaitForTheWorkerWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_wait_for_the_worker_waits"), + "(WaitStats.WaitForTheWorkerWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsWorkspaceSynchronizationWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_workspace_synchronization_waits"), + "(WaitStats.WorkspaceSynchronizationWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + c.WaitStatsTransactionOwnershipWaits = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "waitstats_transaction_ownership_waits"), + "(WaitStats.TransactionOwnershipWaits)", + []string{"mssql_instance", "item"}, + nil, + ) + + c.mssqlCollectors = c.getMSSQLCollectors() - if *mssqlPrintCollectors { + if *c.mssqlPrintCollectors { fmt.Printf("Available SQLServer Classes:\n") - for name := range mssqlCollector.mssqlCollectors { + for name := range c.mssqlCollectors { fmt.Printf(" - %s\n", name) } os.Exit(0) } - return &mssqlCollector, nil + return nil } -type mssqlCollectorFunc func(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) +type mssqlCollectorFunc func(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) -func (c *MSSQLCollector) execute(ctx *ScrapeContext, name string, fn mssqlCollectorFunc, ch chan<- prometheus.Metric, sqlInstance string, wg *sync.WaitGroup) { +func (c *collector) execute(ctx *types.ScrapeContext, name string, fn mssqlCollectorFunc, ch chan<- prometheus.Metric, sqlInstance string, wg *sync.WaitGroup) { // Reset failure counter on each scrape c.mssqlChildCollectorFailure = 0 defer wg.Done() @@ -1956,10 +1968,10 @@ func (c *MSSQLCollector) execute(ctx *ScrapeContext, name string, fn mssqlCollec // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *MSSQLCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { wg := sync.WaitGroup{} - enabled := expandEnabledChildCollectors(*mssqlEnabledCollectors) + enabled := utils.ExpandEnabledChildCollectors(*c.mssqlEnabledCollectors) for sqlInstance := range c.mssqlInstances { for _, name := range enabled { function := c.mssqlCollectors[name] @@ -2026,11 +2038,11 @@ type mssqlAccessMethods struct { WorktablesFromCacheRatio_Base float64 `perflib:"Worktables From Cache Base_Base"` } -func (c *MSSQLCollector) collectAccessMethods(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectAccessMethods(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlAccessMethods _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_accessmethods collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "accessmethods")], &dst, c.logger); err != nil { return nil, err } @@ -2361,11 +2373,11 @@ type mssqlAvailabilityReplica struct { SendstoTransportPersec float64 `perflib:"Sends to Transport/sec"` } -func (c *MSSQLCollector) collectAvailabilityReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectAvailabilityReplica(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlAvailabilityReplica _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_availreplica collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "availreplica")], &dst, c.logger); err != nil { return nil, err } @@ -2469,11 +2481,11 @@ type mssqlBufferManager struct { Targetpages float64 `perflib:"Target pages"` } -func (c *MSSQLCollector) collectBufferManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectBufferManager(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlBufferManager _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_bufman collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "bufman")], &dst, c.logger); err != nil { return nil, err } @@ -2673,11 +2685,11 @@ type mssqlDatabaseReplica struct { TransactionDelay float64 `perflib:"Transaction Delay"` } -func (c *MSSQLCollector) collectDatabaseReplica(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectDatabaseReplica(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlDatabaseReplica _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_dbreplica collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "dbreplica")], &dst, c.logger); err != nil { return nil, err } @@ -2912,11 +2924,11 @@ type mssqlDatabases struct { XTPMemoryUsedKB float64 `perflib:"XTP Memory Used (KB)"` } -func (c *MSSQLCollector) collectDatabases(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectDatabases(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlDatabases _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_databases collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "databases")], &dst, c.logger); err != nil { return nil, err } @@ -3294,11 +3306,11 @@ type mssqlGeneralStatistics struct { UserConnections float64 `perflib:"User Connections"` } -func (c *MSSQLCollector) collectGeneralStatistics(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectGeneralStatistics(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlGeneralStatistics _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_genstats collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "genstats")], &dst, c.logger); err != nil { return nil, err } @@ -3489,11 +3501,11 @@ type mssqlLocks struct { NumberofDeadlocksPersec float64 `perflib:"Number of Deadlocks/sec"` } -func (c *MSSQLCollector) collectLocks(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectLocks(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlLocks _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_locks collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "locks")], &dst, c.logger); err != nil { return nil, err } @@ -3587,11 +3599,11 @@ type mssqlMemoryManager struct { TotalServerMemoryKB float64 `perflib:"Total Server Memory (KB)"` } -func (c *MSSQLCollector) collectMemoryManager(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectMemoryManager(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlMemoryManager _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_memmgr collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "memmgr")], &dst, c.logger); err != nil { return nil, err } @@ -3756,11 +3768,11 @@ type mssqlSQLStatistics struct { UnsafeAutoParamsPersec float64 `perflib:"Unsafe Auto-Params/sec"` } -func (c *MSSQLCollector) collectSQLStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectSQLStats(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlSQLStatistics _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_sqlstats collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlstats")], &dst, c.logger); err != nil { return nil, err } @@ -3864,11 +3876,11 @@ type mssqlWaitStatistics struct { WaitStatsTransactionOwnershipWaits float64 `perflib:"Transaction ownership waits"` } -func (c *MSSQLCollector) collectWaitStats(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectWaitStats(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlWaitStatistics _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_waitstats collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "waitstats")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "waitstats")], &dst, c.logger); err != nil { return nil, err } @@ -3970,11 +3982,11 @@ type mssqlSQLErrors struct { // Win32_PerfRawData_MSSQLSERVER_SQLServerErrors docs: // - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-sql-errors-object -func (c *MSSQLCollector) collectSQLErrors(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectSQLErrors(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlSQLErrors _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_sqlerrors collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "sqlerrors")], &dst, c.logger); err != nil { return nil, err } @@ -4013,11 +4025,11 @@ type mssqlTransactions struct { // Win32_PerfRawData_MSSQLSERVER_Transactions docs: // - https://docs.microsoft.com/en-us/sql/relational-databases/performance-monitor/sql-server-transactions-object -func (c *MSSQLCollector) collectTransactions(ctx *ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { +func (c *collector) collectTransactions(ctx *types.ScrapeContext, ch chan<- prometheus.Metric, sqlInstance string) (*prometheus.Desc, error) { var dst []mssqlTransactions _ = level.Debug(c.logger).Log("msg", fmt.Sprintf("mssql_transactions collector iterating sql instance %s.", sqlInstance)) - if err := unmarshalObject(ctx.perfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects[mssqlGetPerfObjectName(sqlInstance, "transactions")], &dst, c.logger); err != nil { return nil, err } diff --git a/pkg/collector/mssql/mssql_test.go b/pkg/collector/mssql/mssql_test.go new file mode 100644 index 0000000000..016e7842d2 --- /dev/null +++ b/pkg/collector/mssql/mssql_test.go @@ -0,0 +1,12 @@ +package mssql_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/mssql" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, mssql.Name, mssql.NewWithFlags) +} diff --git a/collector/net.go b/pkg/collector/net/net.go similarity index 52% rename from collector/net.go rename to pkg/collector/net/net.go index fe1bd7c26b..e0048c45df 100644 --- a/collector/net.go +++ b/pkg/collector/net/net.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package net import ( "errors" @@ -11,10 +10,14 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) const ( + Name = "net" + FlagNicOldExclude = "collector.net.nic-blacklist" FlagNicOldInclude = "collector.net.nic-whitelist" @@ -22,7 +25,22 @@ const ( FlagNicInclude = "collector.net.nic-include" ) -var ( +type Config struct { + NicInclude string `yaml:"nic_include"` + NicExclude string `yaml:"nic_exclude"` +} + +var ConfigDefaults = Config{ + NicInclude: ".+", + NicExclude: "", +} + +var nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") + +// A collector is a Prometheus collector for Perflib Network Interface metrics +type collector struct { + logger log.Logger + nicOldInclude *string nicOldExclude *string @@ -32,13 +50,6 @@ var ( nicIncludeSet bool nicExcludeSet bool - nicNameToUnderscore = regexp.MustCompile("[^a-zA-Z0-9]") -) - -// A NetworkCollector is a Prometheus collector for Perflib Network Interface metrics -type NetworkCollector struct { - logger log.Logger - BytesReceivedTotal *prometheus.Desc BytesSentTotal *prometheus.Desc BytesTotal *prometheus.Desc @@ -57,146 +68,175 @@ type NetworkCollector struct { nicExcludePattern *regexp.Regexp } -// newNetworkCollectorFlags ... -func newNetworkCollectorFlags(app *kingpin.Application) { - nicInclude = app.Flag( +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + nicExclude: &config.NicExclude, + nicInclude: &config.NicInclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{} + + c.nicInclude = app.Flag( FlagNicInclude, "Regexp of NIC:s to include. NIC name must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - nicIncludeSet = true + ).Default(ConfigDefaults.NicInclude).PreAction(func(_ *kingpin.ParseContext) error { + c.nicIncludeSet = true return nil }).String() - nicExclude = app.Flag( + c.nicExclude = app.Flag( FlagNicExclude, "Regexp of NIC:s to exclude. NIC name must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - nicExcludeSet = true + ).Default(ConfigDefaults.NicExclude).PreAction(func(_ *kingpin.ParseContext) error { + c.nicExcludeSet = true return nil }).String() - nicOldInclude = app.Flag( + c.nicOldInclude = app.Flag( FlagNicOldInclude, "DEPRECATED: Use --collector.net.nic-include", ).Hidden().String() - nicOldExclude = app.Flag( + c.nicOldExclude = app.Flag( FlagNicOldExclude, "DEPRECATED: Use --collector.net.nic-exclude", ).Hidden().String() + return c +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) } -// newNetworkCollector ... -func newNetworkCollector(logger log.Logger) (Collector, error) { - const subsystem = "net" - logger = log.With(logger, "collector", subsystem) +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Network Interface"}, nil +} - if *nicOldExclude != "" { - if !nicExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.net.nic-blacklist is DEPRECATED and will be removed in a future release, use --collector.net.nic-exclude") - *nicExclude = *nicOldExclude +func (c *collector) Build() error { + if *c.nicOldExclude != "" { + if !c.nicExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.net.nic-blacklist is DEPRECATED and will be removed in a future release, use --collector.net.nic-exclude") + *c.nicExclude = *c.nicOldExclude } else { - return nil, errors.New("--collector.net.nic-blacklist and --collector.net.nic-exclude are mutually exclusive") + return errors.New("--collector.net.nic-blacklist and --collector.net.nic-exclude are mutually exclusive") } } - if *nicOldInclude != "" { - if !nicIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.net.nic-whitelist is DEPRECATED and will be removed in a future release, use --collector.net.nic-include") - *nicInclude = *nicOldInclude + if *c.nicOldInclude != "" { + if !c.nicIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.net.nic-whitelist is DEPRECATED and will be removed in a future release, use --collector.net.nic-include") + *c.nicInclude = *c.nicOldInclude } else { - return nil, errors.New("--collector.net.nic-whitelist and --collector.net.nic-include are mutually exclusive") + return errors.New("--collector.net.nic-whitelist and --collector.net.nic-include are mutually exclusive") } } + c.BytesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_received_total"), + "(Network.BytesReceivedPerSec)", + []string{"nic"}, + nil, + ) + c.BytesSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_sent_total"), + "(Network.BytesSentPerSec)", + []string{"nic"}, + nil, + ) + c.BytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_total"), + "(Network.BytesTotalPerSec)", + []string{"nic"}, + nil, + ) + c.OutputQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "output_queue_length_packets"), + "(Network.OutputQueueLength)", + []string{"nic"}, + nil, + ) + c.PacketsOutboundDiscarded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_outbound_discarded_total"), + "(Network.PacketsOutboundDiscarded)", + []string{"nic"}, + nil, + ) + c.PacketsOutboundErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_outbound_errors_total"), + "(Network.PacketsOutboundErrors)", + []string{"nic"}, + nil, + ) + c.PacketsReceivedDiscarded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_received_discarded_total"), + "(Network.PacketsReceivedDiscarded)", + []string{"nic"}, + nil, + ) + c.PacketsReceivedErrors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_received_errors_total"), + "(Network.PacketsReceivedErrors)", + []string{"nic"}, + nil, + ) + c.PacketsReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"), + "(Network.PacketsReceivedPerSec)", + []string{"nic"}, + nil, + ) + c.PacketsReceivedUnknown = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_received_unknown_total"), + "(Network.PacketsReceivedUnknown)", + []string{"nic"}, + nil, + ) + c.PacketsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_total"), + "(Network.PacketsPerSec)", + []string{"nic"}, + nil, + ) + c.PacketsSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_sent_total"), + "(Network.PacketsSentPerSec)", + []string{"nic"}, + nil, + ) + c.CurrentBandwidth = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_bandwidth_bytes"), + "(Network.CurrentBandwidth)", + []string{"nic"}, + nil, + ) - return &NetworkCollector{ - logger: logger, - BytesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"), - "(Network.BytesReceivedPerSec)", - []string{"nic"}, - nil, - ), - BytesSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"), - "(Network.BytesSentPerSec)", - []string{"nic"}, - nil, - ), - BytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_total"), - "(Network.BytesTotalPerSec)", - []string{"nic"}, - nil, - ), - OutputQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "output_queue_length_packets"), - "(Network.OutputQueueLength)", - []string{"nic"}, - nil, - ), - PacketsOutboundDiscarded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_discarded_total"), - "(Network.PacketsOutboundDiscarded)", - []string{"nic"}, - nil, - ), - PacketsOutboundErrors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_outbound_errors_total"), - "(Network.PacketsOutboundErrors)", - []string{"nic"}, - nil, - ), - PacketsReceivedDiscarded: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_received_discarded_total"), - "(Network.PacketsReceivedDiscarded)", - []string{"nic"}, - nil, - ), - PacketsReceivedErrors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_received_errors_total"), - "(Network.PacketsReceivedErrors)", - []string{"nic"}, - nil, - ), - PacketsReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"), - "(Network.PacketsReceivedPerSec)", - []string{"nic"}, - nil, - ), - PacketsReceivedUnknown: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_received_unknown_total"), - "(Network.PacketsReceivedUnknown)", - []string{"nic"}, - nil, - ), - PacketsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_total"), - "(Network.PacketsPerSec)", - []string{"nic"}, - nil, - ), - PacketsSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"), - "(Network.PacketsSentPerSec)", - []string{"nic"}, - nil, - ), - CurrentBandwidth: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_bandwidth_bytes"), - "(Network.CurrentBandwidth)", - []string{"nic"}, - nil, - ), - - nicIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicInclude)), - nicExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *nicExclude)), - }, nil + var err error + c.nicIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicInclude)) + if err != nil { + return err + } + + c.nicExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.nicExclude)) + if err != nil { + return err + } + + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *NetworkCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ctx, ch); err != nil { _ = level.Error(c.logger).Log("failed collecting net metrics", "desc", desc, "err", err) return err @@ -229,10 +269,10 @@ type networkInterface struct { CurrentBandwidth float64 `perflib:"Current Bandwidth"` } -func (c *NetworkCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []networkInterface - if err := unmarshalObject(ctx.perfObjects["Network Interface"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["Network Interface"], &dst, c.logger); err != nil { return nil, err } diff --git a/pkg/collector/net/net_bench_test.go b/pkg/collector/net/net_bench_test.go new file mode 100644 index 0000000000..180bc2990d --- /dev/null +++ b/pkg/collector/net/net_bench_test.go @@ -0,0 +1,19 @@ +//go:build windows + +package net_test + +import ( + "testing" + + "github.com/alecthomas/kingpin/v2" + "github.com/prometheus-community/windows_exporter/pkg/collector/net" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces. + localNicInclude := ".+" + + kingpin.CommandLine.GetArg(net.FlagNicInclude).StringVar(&localNicInclude) + testutils.FuncBenchmarkCollector(b, net.Name, net.NewWithFlags) +} diff --git a/collector/net_test.go b/pkg/collector/net/net_test.go similarity index 51% rename from collector/net_test.go rename to pkg/collector/net/net_test.go index 65d6e1a6d0..0add1196c6 100644 --- a/collector/net_test.go +++ b/pkg/collector/net/net_test.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package net import ( "testing" @@ -18,10 +17,3 @@ func TestNetworkToInstanceName(t *testing.T) { } } } - -func BenchmarkNetCollector(b *testing.B) { - // Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all interfaces. - localNicInclude := ".+" - nicInclude = &localNicInclude - benchmarkCollector(b, "net", newNetworkCollector) -} diff --git a/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go b/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go new file mode 100644 index 0000000000..6b0e8440c6 --- /dev/null +++ b/pkg/collector/netframework_clrexceptions/netframework_clrexceptions.go @@ -0,0 +1,144 @@ +//go:build windows + +package netframework_clrexceptions //nolint:revive + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrexceptions" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRExceptions metrics +type collector struct { + logger log.Logger + + NumberofExcepsThrown *prometheus.Desc + NumberofFilters *prometheus.Desc + NumberofFinallys *prometheus.Desc + ThrowToCatchDepth *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.NumberofExcepsThrown = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "exceptions_thrown_total"), + "Displays the total number of exceptions thrown since the application started. This includes both .NET exceptions and unmanaged exceptions that are converted into .NET exceptions.", + []string{"process"}, + nil, + ) + c.NumberofFilters = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "exceptions_filters_total"), + "Displays the total number of .NET exception filters executed. An exception filter evaluates regardless of whether an exception is handled.", + []string{"process"}, + nil, + ) + c.NumberofFinallys = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "exceptions_finallys_total"), + "Displays the total number of finally blocks executed. Only the finally blocks executed for an exception are counted; finally blocks on normal code paths are not counted by this counter.", + []string{"process"}, + nil, + ) + c.ThrowToCatchDepth = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "throw_to_catch_depth_total"), + "Displays the total number of stack frames traversed, from the frame that threw the exception to the frame that handled the exception.", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrexceptions metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRExceptions struct { + Name string + + NumberofExcepsThrown uint32 + NumberofExcepsThrownPersec uint32 + NumberofFiltersPersec uint32 + NumberofFinallysPersec uint32 + ThrowToCatchDepthPersec uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRExceptions + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberofExcepsThrown, + prometheus.CounterValue, + float64(process.NumberofExcepsThrown), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofFilters, + prometheus.CounterValue, + float64(process.NumberofFiltersPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofFinallys, + prometheus.CounterValue, + float64(process.NumberofFinallysPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ThrowToCatchDepth, + prometheus.CounterValue, + float64(process.ThrowToCatchDepthPersec), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrexceptions/netframework_clrexceptions_test.go b/pkg/collector/netframework_clrexceptions/netframework_clrexceptions_test.go new file mode 100644 index 0000000000..1bbe5278c7 --- /dev/null +++ b/pkg/collector/netframework_clrexceptions/netframework_clrexceptions_test.go @@ -0,0 +1,13 @@ +package netframework_clrexceptions_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrexceptions" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrexceptions.Name, netframework_clrexceptions.NewWithFlags) +} diff --git a/pkg/collector/netframework_clrinterop/netframework_clrinterop.go b/pkg/collector/netframework_clrinterop/netframework_clrinterop.go new file mode 100644 index 0000000000..0f8f824bcf --- /dev/null +++ b/pkg/collector/netframework_clrinterop/netframework_clrinterop.go @@ -0,0 +1,130 @@ +//go:build windows + +package netframework_clrinterop //nolint:revive + +import ( + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrinterop" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRInterop metrics +type collector struct { + logger log.Logger + + NumberofCCWs *prometheus.Desc + Numberofmarshalling *prometheus.Desc + NumberofStubs *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.NumberofCCWs = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "com_callable_wrappers_total"), + "Displays the current number of COM callable wrappers (CCWs). A CCW is a proxy for a managed object being referenced from an unmanaged COM client.", + []string{"process"}, + nil, + ) + c.Numberofmarshalling = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "interop_marshalling_total"), + "Displays the total number of times arguments and return values have been marshaled from managed to unmanaged code, and vice versa, since the application started.", + []string{"process"}, + nil, + ) + c.NumberofStubs = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "interop_stubs_created_total"), + "Displays the current number of stubs created by the common language runtime. Stubs are responsible for marshaling arguments and return values from managed to unmanaged code, and vice versa, during a COM interop call or a platform invoke call.", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrinterop metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRInterop struct { + Name string + + NumberofCCWs uint32 + Numberofmarshalling uint32 + NumberofStubs uint32 + NumberofTLBexportsPersec uint32 + NumberofTLBimportsPersec uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRInterop + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberofCCWs, + prometheus.CounterValue, + float64(process.NumberofCCWs), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Numberofmarshalling, + prometheus.CounterValue, + float64(process.Numberofmarshalling), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofStubs, + prometheus.CounterValue, + float64(process.NumberofStubs), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrinterop/netframework_clrinterop_test.go b/pkg/collector/netframework_clrinterop/netframework_clrinterop_test.go new file mode 100644 index 0000000000..a165be19b7 --- /dev/null +++ b/pkg/collector/netframework_clrinterop/netframework_clrinterop_test.go @@ -0,0 +1,13 @@ +package netframework_clrinterop_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrinterop" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrinterop.Name, netframework_clrinterop.NewWithFlags) +} diff --git a/pkg/collector/netframework_clrjit/netframework_clrjit.go b/pkg/collector/netframework_clrjit/netframework_clrjit.go new file mode 100644 index 0000000000..77a6933aaa --- /dev/null +++ b/pkg/collector/netframework_clrjit/netframework_clrjit.go @@ -0,0 +1,145 @@ +//go:build windows + +package netframework_clrjit //nolint:revive + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrjit" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRJit metrics +type collector struct { + logger log.Logger + + NumberofMethodsJitted *prometheus.Desc + TimeinJit *prometheus.Desc + StandardJitFailures *prometheus.Desc + TotalNumberofILBytesJitted *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.NumberofMethodsJitted = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "jit_methods_total"), + "Displays the total number of methods JIT-compiled since the application started. This counter does not include pre-JIT-compiled methods.", + []string{"process"}, + nil, + ) + c.TimeinJit = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "jit_time_percent"), + "Displays the percentage of time spent in JIT compilation. This counter is updated at the end of every JIT compilation phase. A JIT compilation phase occurs when a method and its dependencies are compiled.", + []string{"process"}, + nil, + ) + c.StandardJitFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "jit_standard_failures_total"), + "Displays the peak number of methods the JIT compiler has failed to compile since the application started. This failure can occur if the MSIL cannot be verified or if there is an internal error in the JIT compiler.", + []string{"process"}, + nil, + ) + c.TotalNumberofILBytesJitted = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "jit_il_bytes_total"), + "Displays the total number of Microsoft intermediate language (MSIL) bytes compiled by the just-in-time (JIT) compiler since the application started", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrjit metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRJit struct { + Name string + + Frequency_PerfTime uint32 + ILBytesJittedPersec uint32 + NumberofILBytesJitted uint32 + NumberofMethodsJitted uint32 + PercentTimeinJit uint32 + StandardJitFailures uint32 + TotalNumberofILBytesJitted uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRJit + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberofMethodsJitted, + prometheus.CounterValue, + float64(process.NumberofMethodsJitted), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeinJit, + prometheus.GaugeValue, + float64(process.PercentTimeinJit)/float64(process.Frequency_PerfTime), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.StandardJitFailures, + prometheus.GaugeValue, + float64(process.StandardJitFailures), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalNumberofILBytesJitted, + prometheus.CounterValue, + float64(process.TotalNumberofILBytesJitted), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrjit/netframework_clrjit_test.go b/pkg/collector/netframework_clrjit/netframework_clrjit_test.go new file mode 100644 index 0000000000..04f243ef94 --- /dev/null +++ b/pkg/collector/netframework_clrjit/netframework_clrjit_test.go @@ -0,0 +1,13 @@ +package netframework_clrjit_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrjit" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrjit.Name, netframework_clrjit.NewWithFlags) +} diff --git a/pkg/collector/netframework_clrloading/netframework_clrloading.go b/pkg/collector/netframework_clrloading/netframework_clrloading.go new file mode 100644 index 0000000000..59f497f964 --- /dev/null +++ b/pkg/collector/netframework_clrloading/netframework_clrloading.go @@ -0,0 +1,224 @@ +//go:build windows + +package netframework_clrloading //nolint:revive + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrloading" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLoading metrics +type collector struct { + logger log.Logger + + BytesinLoaderHeap *prometheus.Desc + Currentappdomains *prometheus.Desc + CurrentAssemblies *prometheus.Desc + CurrentClassesLoaded *prometheus.Desc + TotalAppdomains *prometheus.Desc + Totalappdomainsunloaded *prometheus.Desc + TotalAssemblies *prometheus.Desc + TotalClassesLoaded *prometheus.Desc + TotalNumberofLoadFailures *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.BytesinLoaderHeap = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "loader_heap_size_bytes"), + "Displays the current size, in bytes, of the memory committed by the class loader across all application domains. Committed memory is the physical space reserved in the disk paging file.", + []string{"process"}, + nil, + ) + c.Currentappdomains = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "appdomains_loaded_current"), + "Displays the current number of application domains loaded in this application.", + []string{"process"}, + nil, + ) + c.CurrentAssemblies = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "assemblies_loaded_current"), + "Displays the current number of assemblies loaded across all application domains in the currently running application. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", + []string{"process"}, + nil, + ) + c.CurrentClassesLoaded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "classes_loaded_current"), + "Displays the current number of classes loaded in all assemblies.", + []string{"process"}, + nil, + ) + c.TotalAppdomains = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "appdomains_loaded_total"), + "Displays the peak number of application domains loaded since the application started.", + []string{"process"}, + nil, + ) + c.Totalappdomainsunloaded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "appdomains_unloaded_total"), + "Displays the total number of application domains unloaded since the application started. If an application domain is loaded and unloaded multiple times, this counter increments each time the application domain is unloaded.", + []string{"process"}, + nil, + ) + c.TotalAssemblies = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "assemblies_loaded_total"), + "Displays the total number of assemblies loaded since the application started. If the assembly is loaded as domain-neutral from multiple application domains, this counter is incremented only once.", + []string{"process"}, + nil, + ) + c.TotalClassesLoaded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "classes_loaded_total"), + "Displays the cumulative number of classes loaded in all assemblies since the application started.", + []string{"process"}, + nil, + ) + c.TotalNumberofLoadFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "class_load_failures_total"), + "Displays the peak number of classes that have failed to load since the application started.", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrloading metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRLoading struct { + Name string + + AssemblySearchLength uint32 + BytesinLoaderHeap uint64 + Currentappdomains uint32 + CurrentAssemblies uint32 + CurrentClassesLoaded uint32 + PercentTimeLoading uint64 + Rateofappdomains uint32 + Rateofappdomainsunloaded uint32 + RateofAssemblies uint32 + RateofClassesLoaded uint32 + RateofLoadFailures uint32 + TotalAppdomains uint32 + Totalappdomainsunloaded uint32 + TotalAssemblies uint32 + TotalClassesLoaded uint32 + TotalNumberofLoadFailures uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRLoading + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.BytesinLoaderHeap, + prometheus.GaugeValue, + float64(process.BytesinLoaderHeap), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Currentappdomains, + prometheus.GaugeValue, + float64(process.Currentappdomains), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CurrentAssemblies, + prometheus.GaugeValue, + float64(process.CurrentAssemblies), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.CurrentClassesLoaded, + prometheus.GaugeValue, + float64(process.CurrentClassesLoaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalAppdomains, + prometheus.CounterValue, + float64(process.TotalAppdomains), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Totalappdomainsunloaded, + prometheus.CounterValue, + float64(process.Totalappdomainsunloaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalAssemblies, + prometheus.CounterValue, + float64(process.TotalAssemblies), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalClassesLoaded, + prometheus.CounterValue, + float64(process.TotalClassesLoaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalNumberofLoadFailures, + prometheus.CounterValue, + float64(process.TotalNumberofLoadFailures), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrloading/netframework_clrloading_test.go b/pkg/collector/netframework_clrloading/netframework_clrloading_test.go new file mode 100644 index 0000000000..91a223477a --- /dev/null +++ b/pkg/collector/netframework_clrloading/netframework_clrloading_test.go @@ -0,0 +1,13 @@ +package netframework_clrloading_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrloading" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrloading.Name, netframework_clrloading.NewWithFlags) +} diff --git a/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go b/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go new file mode 100644 index 0000000000..a1d9065856 --- /dev/null +++ b/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads.go @@ -0,0 +1,190 @@ +//go:build windows + +package netframework_clrlocksandthreads //nolint:revive + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrlocksandthreads" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads metrics +type collector struct { + logger log.Logger + + CurrentQueueLength *prometheus.Desc + NumberofcurrentlogicalThreads *prometheus.Desc + NumberofcurrentphysicalThreads *prometheus.Desc + Numberofcurrentrecognizedthreads *prometheus.Desc + Numberoftotalrecognizedthreads *prometheus.Desc + QueueLengthPeak *prometheus.Desc + TotalNumberofContentions *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.CurrentQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_queue_length"), + "Displays the total number of threads that are currently waiting to acquire a managed lock in the application.", + []string{"process"}, + nil, + ) + c.NumberofcurrentlogicalThreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_logical_threads"), + "Displays the number of current managed thread objects in the application. This counter maintains the count of both running and stopped threads. ", + []string{"process"}, + nil, + ) + c.NumberofcurrentphysicalThreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "physical_threads_current"), + "Displays the number of native operating system threads created and owned by the common language runtime to act as underlying threads for managed thread objects. This counter's value does not include the threads used by the runtime in its internal operations; it is a subset of the threads in the operating system process.", + []string{"process"}, + nil, + ) + c.Numberofcurrentrecognizedthreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "recognized_threads_current"), + "Displays the number of threads that are currently recognized by the runtime. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", + []string{"process"}, + nil, + ) + c.Numberoftotalrecognizedthreads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "recognized_threads_total"), + "Displays the total number of threads that have been recognized by the runtime since the application started. These threads are associated with a corresponding managed thread object. The runtime does not create these threads, but they have run inside the runtime at least once.", + []string{"process"}, + nil, + ) + c.QueueLengthPeak = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "queue_length_total"), + "Displays the total number of threads that waited to acquire a managed lock since the application started.", + []string{"process"}, + nil, + ) + c.TotalNumberofContentions = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "contentions_total"), + "Displays the total number of times that threads in the runtime have attempted to acquire a managed lock unsuccessfully.", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrlocksandthreads metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads struct { + Name string + + ContentionRatePersec uint32 + CurrentQueueLength uint32 + NumberofcurrentlogicalThreads uint32 + NumberofcurrentphysicalThreads uint32 + Numberofcurrentrecognizedthreads uint32 + Numberoftotalrecognizedthreads uint32 + QueueLengthPeak uint32 + QueueLengthPersec uint32 + RateOfRecognizedThreadsPersec uint32 + TotalNumberofContentions uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.CurrentQueueLength, + prometheus.GaugeValue, + float64(process.CurrentQueueLength), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofcurrentlogicalThreads, + prometheus.GaugeValue, + float64(process.NumberofcurrentlogicalThreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.NumberofcurrentphysicalThreads, + prometheus.GaugeValue, + float64(process.NumberofcurrentphysicalThreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Numberofcurrentrecognizedthreads, + prometheus.GaugeValue, + float64(process.Numberofcurrentrecognizedthreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Numberoftotalrecognizedthreads, + prometheus.CounterValue, + float64(process.Numberoftotalrecognizedthreads), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.QueueLengthPeak, + prometheus.CounterValue, + float64(process.QueueLengthPeak), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalNumberofContentions, + prometheus.CounterValue, + float64(process.TotalNumberofContentions), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads_test.go b/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads_test.go new file mode 100644 index 0000000000..c3167a64d7 --- /dev/null +++ b/pkg/collector/netframework_clrlocksandthreads/netframework_clrlocksandthreads_test.go @@ -0,0 +1,13 @@ +package netframework_clrlocksandthreads_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrlocksandthreads" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrlocksandthreads.Name, netframework_clrlocksandthreads.NewWithFlags) +} diff --git a/collector/netframework_clrmemory.go b/pkg/collector/netframework_clrmemory/netframework_clrmemory.go similarity index 55% rename from collector/netframework_clrmemory.go rename to pkg/collector/netframework_clrmemory/netframework_clrmemory.go index e1e9bbe1d2..62e26fdaff 100644 --- a/collector/netframework_clrmemory.go +++ b/pkg/collector/netframework_clrmemory/netframework_clrmemory.go @@ -1,17 +1,24 @@ //go:build windows -// +build windows -package collector +package netframework_clrmemory //nolint:revive import ( + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A NETFramework_NETCLRMemoryCollector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics -type NETFramework_NETCLRMemoryCollector struct { +const Name = "netframework_clrmemory" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRMemory metrics +type collector struct { logger log.Logger AllocatedBytes *prometheus.Desc @@ -31,89 +38,107 @@ type NETFramework_NETCLRMemoryCollector struct { PromotedMemoryfromGen1 *prometheus.Desc } -// newNETFramework_NETCLRMemoryCollector ... -func newNETFramework_NETCLRMemoryCollector(logger log.Logger) (Collector, error) { - const subsystem = "netframework_clrmemory" - return &NETFramework_NETCLRMemoryCollector{ - logger: log.With(logger, "collector", subsystem), - AllocatedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "allocated_bytes_total"), - "Displays the total number of bytes allocated on the garbage collection heap.", - []string{"process"}, - nil, - ), - FinalizationSurvivors: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "finalization_survivors"), - "Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.", - []string{"process"}, - nil, - ), - HeapSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "heap_size_bytes"), - "Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.", - []string{"process", "area"}, - nil, - ), - PromotedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "promoted_bytes"), - "Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.", - []string{"process", "area"}, - nil, - ), - NumberGCHandles: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "number_gc_handles"), - "Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.", - []string{"process"}, - nil, - ), - NumberCollections: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "collections_total"), - "Displays the number of times the generation objects are garbage collected since the application started.", - []string{"process", "area"}, - nil, - ), - NumberInducedGC: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "induced_gc_total"), - "Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.", - []string{"process"}, - nil, - ), - NumberofPinnedObjects: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "number_pinned_objects"), - "Displays the number of pinned objects encountered in the last garbage collection.", - []string{"process"}, - nil, - ), - NumberofSinkBlocksinuse: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "number_sink_blocksinuse"), - "Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.", - []string{"process"}, - nil, - ), - NumberTotalCommittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "committed_bytes"), - "Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.", - []string{"process"}, - nil, - ), - NumberTotalreservedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "reserved_bytes"), - "Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.", - []string{"process"}, - nil, - ), - TimeinGC: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gc_time_percent"), - "Displays the percentage of time that was spent performing a garbage collection in the last sample.", - []string{"process"}, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.AllocatedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "allocated_bytes_total"), + "Displays the total number of bytes allocated on the garbage collection heap.", + []string{"process"}, + nil, + ) + c.FinalizationSurvivors = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "finalization_survivors"), + "Displays the number of garbage-collected objects that survive a collection because they are waiting to be finalized.", + []string{"process"}, + nil, + ) + c.HeapSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "heap_size_bytes"), + "Displays the maximum bytes that can be allocated; it does not indicate the current number of bytes allocated.", + []string{"process", "area"}, + nil, + ) + c.PromotedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "promoted_bytes"), + "Displays the bytes that were promoted from the generation to the next one during the last GC. Memory is promoted when it survives a garbage collection.", + []string{"process", "area"}, + nil, + ) + c.NumberGCHandles = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "number_gc_handles"), + "Displays the current number of garbage collection handles in use. Garbage collection handles are handles to resources external to the common language runtime and the managed environment.", + []string{"process"}, + nil, + ) + c.NumberCollections = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "collections_total"), + "Displays the number of times the generation objects are garbage collected since the application started.", + []string{"process", "area"}, + nil, + ) + c.NumberInducedGC = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "induced_gc_total"), + "Displays the peak number of times garbage collection was performed because of an explicit call to GC.Collect.", + []string{"process"}, + nil, + ) + c.NumberofPinnedObjects = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "number_pinned_objects"), + "Displays the number of pinned objects encountered in the last garbage collection.", + []string{"process"}, + nil, + ) + c.NumberofSinkBlocksinuse = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "number_sink_blocksinuse"), + "Displays the current number of synchronization blocks in use. Synchronization blocks are per-object data structures allocated for storing synchronization information. They hold weak references to managed objects and must be scanned by the garbage collector.", + []string{"process"}, + nil, + ) + c.NumberTotalCommittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "committed_bytes"), + "Displays the amount of virtual memory, in bytes, currently committed by the garbage collector. Committed memory is the physical memory for which space has been reserved in the disk paging file.", + []string{"process"}, + nil, + ) + c.NumberTotalreservedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "reserved_bytes"), + "Displays the amount of virtual memory, in bytes, currently reserved by the garbage collector. Reserved memory is the virtual memory space reserved for the application when no disk or main memory pages have been used.", + []string{"process"}, + nil, + ) + c.TimeinGC = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gc_time_percent"), + "Displays the percentage of time that was spent performing a garbage collection in the last sample.", + []string{"process"}, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *NETFramework_NETCLRMemoryCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrmemory metrics", "desc", desc, "err", err) return err @@ -155,9 +180,9 @@ type Win32_PerfRawData_NETFramework_NETCLRMemory struct { PromotedMemoryfromGen1 uint64 } -func (c *NETFramework_NETCLRMemoryCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_NETFramework_NETCLRMemory - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/netframework_clrmemory/netframework_clrmemory_test.go b/pkg/collector/netframework_clrmemory/netframework_clrmemory_test.go new file mode 100644 index 0000000000..c771c642d8 --- /dev/null +++ b/pkg/collector/netframework_clrmemory/netframework_clrmemory_test.go @@ -0,0 +1,13 @@ +package netframework_clrmemory_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrmemory" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrmemory.Name, netframework_clrmemory.NewWithFlags) +} diff --git a/pkg/collector/netframework_clrremoting/netframework_clrremoting.go b/pkg/collector/netframework_clrremoting/netframework_clrremoting.go new file mode 100644 index 0000000000..326e4e8ab0 --- /dev/null +++ b/pkg/collector/netframework_clrremoting/netframework_clrremoting.go @@ -0,0 +1,173 @@ +//go:build windows + +package netframework_clrremoting //nolint:revive + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrremoting" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRRemoting metrics +type collector struct { + logger log.Logger + + Channels *prometheus.Desc + ContextBoundClassesLoaded *prometheus.Desc + ContextBoundObjects *prometheus.Desc + ContextProxies *prometheus.Desc + Contexts *prometheus.Desc + TotalRemoteCalls *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.Channels = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "channels_total"), + "Displays the total number of remoting channels registered across all application domains since application started.", + []string{"process"}, + nil, + ) + c.ContextBoundClassesLoaded = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "context_bound_classes_loaded"), + "Displays the current number of context-bound classes that are loaded.", + []string{"process"}, + nil, + ) + c.ContextBoundObjects = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "context_bound_objects_total"), + "Displays the total number of context-bound objects allocated.", + []string{"process"}, + nil, + ) + c.ContextProxies = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "context_proxies_total"), + "Displays the total number of remoting proxy objects in this process since it started.", + []string{"process"}, + nil, + ) + c.Contexts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "contexts"), + "Displays the current number of remoting contexts in the application.", + []string{"process"}, + nil, + ) + c.TotalRemoteCalls = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "remote_calls_total"), + "Displays the total number of remote procedure calls invoked since the application started.", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrremoting metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRRemoting struct { + Name string + + Channels uint32 + ContextBoundClassesLoaded uint32 + ContextBoundObjectsAllocPersec uint32 + ContextProxies uint32 + Contexts uint32 + RemoteCallsPersec uint32 + TotalRemoteCalls uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRRemoting + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.Channels, + prometheus.CounterValue, + float64(process.Channels), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ContextBoundClassesLoaded, + prometheus.GaugeValue, + float64(process.ContextBoundClassesLoaded), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ContextBoundObjects, + prometheus.CounterValue, + float64(process.ContextBoundObjectsAllocPersec), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.ContextProxies, + prometheus.CounterValue, + float64(process.ContextProxies), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.Contexts, + prometheus.GaugeValue, + float64(process.Contexts), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalRemoteCalls, + prometheus.CounterValue, + float64(process.TotalRemoteCalls), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrremoting/netframework_clrremoting_test.go b/pkg/collector/netframework_clrremoting/netframework_clrremoting_test.go new file mode 100644 index 0000000000..749b46c62d --- /dev/null +++ b/pkg/collector/netframework_clrremoting/netframework_clrremoting_test.go @@ -0,0 +1,13 @@ +package netframework_clrremoting_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrremoting" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrremoting.Name, netframework_clrremoting.NewWithFlags) +} diff --git a/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go b/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go new file mode 100644 index 0000000000..cef01b990b --- /dev/null +++ b/pkg/collector/netframework_clrsecurity/netframework_clrsecurity.go @@ -0,0 +1,144 @@ +//go:build windows + +package netframework_clrsecurity //nolint:revive + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "netframework_clrsecurity" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_NETFramework_NETCLRSecurity metrics +type collector struct { + logger log.Logger + + NumberLinkTimeChecks *prometheus.Desc + TimeinRTchecks *prometheus.Desc + StackWalkDepth *prometheus.Desc + TotalRuntimeChecks *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.NumberLinkTimeChecks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "link_time_checks_total"), + "Displays the total number of link-time code access security checks since the application started.", + []string{"process"}, + nil, + ) + c.TimeinRTchecks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rt_checks_time_percent"), + "Displays the percentage of time spent performing runtime code access security checks in the last sample.", + []string{"process"}, + nil, + ) + c.StackWalkDepth = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "stack_walk_depth"), + "Displays the depth of the stack during that last runtime code access security check.", + []string{"process"}, + nil, + ) + c.TotalRuntimeChecks = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "runtime_checks_total"), + "Displays the total number of runtime code access security checks performed since the application started.", + []string{"process"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting win32_perfrawdata_netframework_netclrsecurity metrics", "desc", desc, "err", err) + return err + } + return nil +} + +type Win32_PerfRawData_NETFramework_NETCLRSecurity struct { + Name string + + Frequency_PerfTime uint32 + NumberLinkTimeChecks uint32 + PercentTimeinRTchecks uint32 + PercentTimeSigAuthenticating uint64 + StackWalkDepth uint32 + TotalRuntimeChecks uint32 +} + +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []Win32_PerfRawData_NETFramework_NETCLRSecurity + q := wmi.QueryAll(&dst, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return nil, err + } + + for _, process := range dst { + + if process.Name == "_Global_" { + continue + } + + ch <- prometheus.MustNewConstMetric( + c.NumberLinkTimeChecks, + prometheus.CounterValue, + float64(process.NumberLinkTimeChecks), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TimeinRTchecks, + prometheus.GaugeValue, + float64(process.PercentTimeinRTchecks)/float64(process.Frequency_PerfTime), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.StackWalkDepth, + prometheus.GaugeValue, + float64(process.StackWalkDepth), + process.Name, + ) + + ch <- prometheus.MustNewConstMetric( + c.TotalRuntimeChecks, + prometheus.CounterValue, + float64(process.TotalRuntimeChecks), + process.Name, + ) + } + + return nil, nil +} diff --git a/pkg/collector/netframework_clrsecurity/netframework_clrsecurity_test.go b/pkg/collector/netframework_clrsecurity/netframework_clrsecurity_test.go new file mode 100644 index 0000000000..822ba7a011 --- /dev/null +++ b/pkg/collector/netframework_clrsecurity/netframework_clrsecurity_test.go @@ -0,0 +1,13 @@ +package netframework_clrsecurity_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/netframework_clrsecurity" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, netframework_clrsecurity.Name, netframework_clrsecurity.NewWithFlags) +} diff --git a/collector/nps.go b/pkg/collector/nps/nps.go similarity index 57% rename from collector/nps.go rename to pkg/collector/nps/nps.go index cd913c68db..3e9cdbb588 100644 --- a/collector/nps.go +++ b/pkg/collector/nps/nps.go @@ -1,17 +1,24 @@ -package collector +package nps import ( "fmt" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A npsCollector is a Prometheus collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics +const Name = "nps" -type npsCollector struct { +type Config struct{} + +var ConfigDefaults = Config{} + +// collector is a Prometheus collector for WMI Win32_PerfRawData_IAS_NPSAuthenticationServer and Win32_PerfRawData_IAS_NPSAccountingServer metrics +type collector struct { logger log.Logger AccessAccepts *prometheus.Desc @@ -42,168 +49,186 @@ type npsCollector struct { AccountingUnknownType *prometheus.Desc } -func newNPSCollector(logger log.Logger) (Collector, error) { - const subsystem = "nps" - logger = log.With(logger, "collector", subsystem) - return &npsCollector{ - logger: logger, - AccessAccepts: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_accepts"), - "(AccessAccepts)", - nil, - nil, - ), - AccessChallenges: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_challenges"), - "(AccessChallenges)", - nil, - nil, - ), - AccessRejects: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_rejects"), - "(AccessRejects)", - nil, - nil, - ), - AccessRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_requests"), - "(AccessRequests)", - nil, - nil, - ), - AccessBadAuthenticators: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_bad_authenticators"), - "(BadAuthenticators)", - nil, - nil, - ), - AccessDroppedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_dropped_packets"), - "(DroppedPackets)", - nil, - nil, - ), - AccessInvalidRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_invalid_requests"), - "(InvalidRequests)", - nil, - nil, - ), - AccessMalformedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_malformed_packets"), - "(MalformedPackets)", - nil, - nil, - ), - AccessPacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_packets_received"), - "(PacketsReceived)", - nil, - nil, - ), - AccessPacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_packets_sent"), - "(PacketsSent)", - nil, - nil, - ), - AccessServerResetTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_server_reset_time"), - "(ServerResetTime)", - nil, - nil, - ), - AccessServerUpTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_server_up_time"), - "(ServerUpTime)", - nil, - nil, - ), - AccessUnknownType: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "access_unknown_type"), - "(UnknownType)", - nil, - nil, - ), - - AccountingRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_requests"), - "(AccountingRequests)", - nil, - nil, - ), - AccountingResponses: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_responses"), - "(AccountingResponses)", - nil, - nil, - ), - AccountingBadAuthenticators: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_bad_authenticators"), - "(BadAuthenticators)", - nil, - nil, - ), - AccountingDroppedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_dropped_packets"), - "(DroppedPackets)", - nil, - nil, - ), - AccountingInvalidRequests: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_invalid_requests"), - "(InvalidRequests)", - nil, - nil, - ), - AccountingMalformedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_malformed_packets"), - "(MalformedPackets)", - nil, - nil, - ), - AccountingNoRecord: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_no_record"), - "(NoRecord)", - nil, - nil, - ), - AccountingPacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_packets_received"), - "(PacketsReceived)", - nil, - nil, - ), - AccountingPacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_packets_sent"), - "(PacketsSent)", - nil, - nil, - ), - AccountingServerResetTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_server_reset_time"), - "(ServerResetTime)", - nil, - nil, - ), - AccountingServerUpTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_server_up_time"), - "(ServerUpTime)", - nil, - nil, - ), - AccountingUnknownType: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "accounting_unknown_type"), - "(UnknownType)", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.AccessAccepts = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_accepts"), + "(AccessAccepts)", + nil, + nil, + ) + c.AccessChallenges = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_challenges"), + "(AccessChallenges)", + nil, + nil, + ) + c.AccessRejects = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_rejects"), + "(AccessRejects)", + nil, + nil, + ) + c.AccessRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_requests"), + "(AccessRequests)", + nil, + nil, + ) + c.AccessBadAuthenticators = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_bad_authenticators"), + "(BadAuthenticators)", + nil, + nil, + ) + c.AccessDroppedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_dropped_packets"), + "(DroppedPackets)", + nil, + nil, + ) + c.AccessInvalidRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_invalid_requests"), + "(InvalidRequests)", + nil, + nil, + ) + c.AccessMalformedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_malformed_packets"), + "(MalformedPackets)", + nil, + nil, + ) + c.AccessPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_packets_received"), + "(PacketsReceived)", + nil, + nil, + ) + c.AccessPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_packets_sent"), + "(PacketsSent)", + nil, + nil, + ) + c.AccessServerResetTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_server_reset_time"), + "(ServerResetTime)", + nil, + nil, + ) + c.AccessServerUpTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_server_up_time"), + "(ServerUpTime)", + nil, + nil, + ) + c.AccessUnknownType = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "access_unknown_type"), + "(UnknownType)", + nil, + nil, + ) + + c.AccountingRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_requests"), + "(AccountingRequests)", + nil, + nil, + ) + c.AccountingResponses = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_responses"), + "(AccountingResponses)", + nil, + nil, + ) + c.AccountingBadAuthenticators = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_bad_authenticators"), + "(BadAuthenticators)", + nil, + nil, + ) + c.AccountingDroppedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_dropped_packets"), + "(DroppedPackets)", + nil, + nil, + ) + c.AccountingInvalidRequests = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_invalid_requests"), + "(InvalidRequests)", + nil, + nil, + ) + c.AccountingMalformedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_malformed_packets"), + "(MalformedPackets)", + nil, + nil, + ) + c.AccountingNoRecord = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_no_record"), + "(NoRecord)", + nil, + nil, + ) + c.AccountingPacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_packets_received"), + "(PacketsReceived)", + nil, + nil, + ) + c.AccountingPacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_packets_sent"), + "(PacketsSent)", + nil, + nil, + ) + c.AccountingServerResetTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_server_reset_time"), + "(ServerResetTime)", + nil, + nil, + ) + c.AccountingServerUpTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_server_up_time"), + "(ServerUpTime)", + nil, + nil, + ) + c.AccountingUnknownType = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "accounting_unknown_type"), + "(UnknownType)", + nil, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *npsCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.CollectAccept(ch); err != nil { _ = level.Error(c.logger).Log("msg", fmt.Sprintf("failed collecting NPS accept data: %s %v", desc, err)) return err @@ -252,11 +277,11 @@ type Win32_PerfRawData_IAS_NPSAccountingServer struct { AccountingUnknownType uint32 } -// Collect sends the metric values for each metric +// CollectAccept sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *npsCollector) CollectAccept(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) CollectAccept(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_IAS_NPSAuthenticationServer - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -342,9 +367,9 @@ func (c *npsCollector) CollectAccept(ch chan<- prometheus.Metric) (*prometheus.D return nil, nil } -func (c *npsCollector) CollectAccounting(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) CollectAccounting(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_IAS_NPSAccountingServer - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/nps/nps_test.go b/pkg/collector/nps/nps_test.go new file mode 100644 index 0000000000..e350a36f50 --- /dev/null +++ b/pkg/collector/nps/nps_test.go @@ -0,0 +1,12 @@ +package nps_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/nps" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, nps.Name, nps.NewWithFlags) +} diff --git a/collector/os.go b/pkg/collector/os/os.go similarity index 63% rename from collector/os.go rename to pkg/collector/os/os.go index 05a6b3db6c..7b05f5a1e9 100644 --- a/collector/os.go +++ b/pkg/collector/os/os.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package os import ( "fmt" @@ -9,17 +8,26 @@ import ( "strings" "time" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" - "github.com/prometheus-community/windows_exporter/headers/netapi32" - "github.com/prometheus-community/windows_exporter/headers/psapi" - "github.com/prometheus-community/windows_exporter/headers/sysinfoapi" + "github.com/prometheus-community/windows_exporter/pkg/headers/netapi32" + "github.com/prometheus-community/windows_exporter/pkg/headers/psapi" + "github.com/prometheus-community/windows_exporter/pkg/headers/sysinfoapi" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" "golang.org/x/sys/windows/registry" ) -// A OSCollector is a Prometheus collector for WMI metrics -type OSCollector struct { +const Name = "os" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI metrics +type collector struct { logger log.Logger OSInformation *prometheus.Desc @@ -43,97 +51,113 @@ type pagingFileCounter struct { UsagePeak float64 `perflib:"% Usage Peak"` } -// newOSCollector ... -func newOSCollector(logger log.Logger) (Collector, error) { - const subsystem = "os" - - return &OSCollector{ - logger: log.With(logger, "collector", subsystem), - - OSInformation: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "info"), - "OperatingSystem.Caption, OperatingSystem.Version", - []string{"product", "version", "major_version", "minor_version", "build_number"}, - nil, - ), - PagingLimitBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "paging_limit_bytes"), - "OperatingSystem.SizeStoredInPagingFiles", - nil, - nil, - ), - PagingFreeBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "paging_free_bytes"), - "OperatingSystem.FreeSpaceInPagingFiles", - nil, - nil, - ), - PhysicalMemoryFreeBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "physical_memory_free_bytes"), - "OperatingSystem.FreePhysicalMemory", - nil, - nil, - ), - Time: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "time"), - "OperatingSystem.LocalDateTime", - nil, - nil, - ), - Timezone: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "timezone"), - "OperatingSystem.LocalDateTime", - []string{"timezone"}, - nil, - ), - Processes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processes"), - "OperatingSystem.NumberOfProcesses", - nil, - nil, - ), - ProcessesLimit: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "processes_limit"), - "OperatingSystem.MaxNumberOfProcesses", - nil, - nil, - ), - ProcessMemoryLimitBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "process_memory_limit_bytes"), - "OperatingSystem.MaxProcessMemorySize", - nil, - nil, - ), - Users: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "users"), - "OperatingSystem.NumberOfUsers", - nil, - nil, - ), - VirtualMemoryBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_bytes"), - "OperatingSystem.TotalVirtualMemorySize", - nil, - nil, - ), - VisibleMemoryBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "visible_memory_bytes"), - "OperatingSystem.TotalVisibleMemorySize", - nil, - nil, - ), - VirtualMemoryFreeBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "virtual_memory_free_bytes"), - "OperatingSystem.FreeVirtualMemory", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Paging File"}, nil +} + +func (c *collector) Build() error { + c.OSInformation = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "info"), + "OperatingSystem.Caption, OperatingSystem.Version", + []string{"product", "version", "major_version", "minor_version", "build_number"}, + nil, + ) + c.PagingLimitBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "paging_limit_bytes"), + "OperatingSystem.SizeStoredInPagingFiles", + nil, + nil, + ) + c.PagingFreeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "paging_free_bytes"), + "OperatingSystem.FreeSpaceInPagingFiles", + nil, + nil, + ) + c.PhysicalMemoryFreeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "physical_memory_free_bytes"), + "OperatingSystem.FreePhysicalMemory", + nil, + nil, + ) + c.Time = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "time"), + "OperatingSystem.LocalDateTime", + nil, + nil, + ) + c.Timezone = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "timezone"), + "OperatingSystem.LocalDateTime", + []string{"timezone"}, + nil, + ) + c.Processes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processes"), + "OperatingSystem.NumberOfProcesses", + nil, + nil, + ) + c.ProcessesLimit = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processes_limit"), + "OperatingSystem.MaxNumberOfProcesses", + nil, + nil, + ) + c.ProcessMemoryLimitBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "process_memory_limit_bytes"), + "OperatingSystem.MaxProcessMemorySize", + nil, + nil, + ) + c.Users = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "users"), + "OperatingSystem.NumberOfUsers", + nil, + nil, + ) + c.VirtualMemoryBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_memory_bytes"), + "OperatingSystem.TotalVirtualMemorySize", + nil, + nil, + ) + c.VisibleMemoryBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "visible_memory_bytes"), + "OperatingSystem.TotalVisibleMemorySize", + nil, + nil, + ) + c.VirtualMemoryFreeBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_memory_free_bytes"), + "OperatingSystem.FreeVirtualMemory", + nil, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *OSCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ctx, ch); err != nil { _ = level.Error(c.logger).Log("failed collecting os metrics", "desc", desc, "err", err) return err @@ -159,7 +183,7 @@ type Win32_OperatingSystem struct { Version string } -func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { nwgi, err := netapi32.GetWorkstationInfo() if err != nil { return nil, err @@ -216,8 +240,8 @@ func (c *OSCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) ( return nil, err } - var pfc = make([]pagingFileCounter, 0) - if err := unmarshalObject(ctx.perfObjects["Paging File"], &pfc, c.logger); err != nil { + pfc := make([]pagingFileCounter, 0) + if err := perflib.UnmarshalObject(ctx.PerfObjects["Paging File"], &pfc, c.logger); err != nil { return nil, err } diff --git a/pkg/collector/os/os_test.go b/pkg/collector/os/os_test.go new file mode 100644 index 0000000000..edd5432598 --- /dev/null +++ b/pkg/collector/os/os_test.go @@ -0,0 +1,12 @@ +package os_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/os" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, os.Name, os.NewWithFlags) +} diff --git a/pkg/collector/physical_disk/physical_disk.go b/pkg/collector/physical_disk/physical_disk.go new file mode 100644 index 0000000000..d288a067b6 --- /dev/null +++ b/pkg/collector/physical_disk/physical_disk.go @@ -0,0 +1,338 @@ +//go:build windows + +package physical_disk + +import ( + "fmt" + "regexp" + "strings" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + Name = "physical_disk" + FlagPhysicalDiskExclude = "collector.physical_disk.disk-exclude" + FlagPhysicalDiskInclude = "collector.physical_disk.disk-include" +) + +type Config struct { + DiskInclude string `yaml:"disk_include"` + DiskExclude string `yaml:"disk_exclude"` +} + +var ConfigDefaults = Config{ + DiskInclude: ".+", + DiskExclude: "", +} + +// A collector is a Prometheus collector for perflib PhysicalDisk metrics +type collector struct { + logger log.Logger + + diskInclude *string + diskExclude *string + + diskIncludeSet bool + diskExcludeSet bool + + RequestsQueued *prometheus.Desc + ReadBytesTotal *prometheus.Desc + ReadsTotal *prometheus.Desc + WriteBytesTotal *prometheus.Desc + WritesTotal *prometheus.Desc + ReadTime *prometheus.Desc + WriteTime *prometheus.Desc + IdleTime *prometheus.Desc + SplitIOs *prometheus.Desc + ReadLatency *prometheus.Desc + WriteLatency *prometheus.Desc + ReadWriteLatency *prometheus.Desc + + diskIncludePattern *regexp.Regexp + diskExcludePattern *regexp.Regexp +} + +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + diskExclude: &config.DiskExclude, + diskInclude: &config.DiskInclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{} + + c.diskInclude = app.Flag( + FlagPhysicalDiskInclude, + "Regexp of disks to include. Disk number must both match include and not match exclude to be included.", + ).Default(ConfigDefaults.DiskInclude).PreAction(func(_ *kingpin.ParseContext) error { + c.diskIncludeSet = true + return nil + }).String() + + c.diskExclude = app.Flag( + FlagPhysicalDiskExclude, + "Regexp of disks to exclude. Disk number must both match include and not match exclude to be included.", + ).Default(ConfigDefaults.DiskExclude).PreAction(func(_ *kingpin.ParseContext) error { + c.diskExcludeSet = true + return nil + }).String() + return c +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"PhysicalDisk"}, nil +} + +func (c *collector) Build() error { + c.RequestsQueued = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "requests_queued"), + "The number of requests queued to the disk (PhysicalDisk.CurrentDiskQueueLength)", + []string{"disk"}, + nil, + ) + + c.ReadBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_bytes_total"), + "The number of bytes transferred from the disk during read operations (PhysicalDisk.DiskReadBytesPerSec)", + []string{"disk"}, + nil, + ) + + c.ReadsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "reads_total"), + "The number of read operations on the disk (PhysicalDisk.DiskReadsPerSec)", + []string{"disk"}, + nil, + ) + + c.WriteBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_bytes_total"), + "The number of bytes transferred to the disk during write operations (PhysicalDisk.DiskWriteBytesPerSec)", + []string{"disk"}, + nil, + ) + + c.WritesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "writes_total"), + "The number of write operations on the disk (PhysicalDisk.DiskWritesPerSec)", + []string{"disk"}, + nil, + ) + + c.ReadTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_seconds_total"), + "Seconds that the disk was busy servicing read requests (PhysicalDisk.PercentDiskReadTime)", + []string{"disk"}, + nil, + ) + + c.WriteTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_seconds_total"), + "Seconds that the disk was busy servicing write requests (PhysicalDisk.PercentDiskWriteTime)", + []string{"disk"}, + nil, + ) + + c.IdleTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "idle_seconds_total"), + "Seconds that the disk was idle (PhysicalDisk.PercentIdleTime)", + []string{"disk"}, + nil, + ) + + c.SplitIOs = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "split_ios_total"), + "The number of I/Os to the disk were split into multiple I/Os (PhysicalDisk.SplitIOPerSec)", + []string{"disk"}, + nil, + ) + + c.ReadLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_latency_seconds_total"), + "Shows the average time, in seconds, of a read operation from the disk (PhysicalDisk.AvgDiskSecPerRead)", + []string{"disk"}, + nil, + ) + + c.WriteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "write_latency_seconds_total"), + "Shows the average time, in seconds, of a write operation to the disk (PhysicalDisk.AvgDiskSecPerWrite)", + []string{"disk"}, + nil, + ) + + c.ReadWriteLatency = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "read_write_latency_seconds_total"), + "Shows the time, in seconds, of the average disk transfer (PhysicalDisk.AvgDiskSecPerTransfer)", + []string{"disk"}, + nil, + ) + + var err error + c.diskIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.diskInclude)) + if err != nil { + return err + } + + c.diskExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.diskExclude)) + if err != nil { + return err + } + + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting physical_disk metrics", "desc", desc, "err", err) + return err + } + return nil +} + +// PhysicalDisk +// Win32_PerfRawData_PerfDisk_PhysicalDisk docs: +// - https://docs.microsoft.com/en-us/previous-versions/aa394308(v=vs.85) - Win32_PerfRawData_PerfDisk_PhysicalDisk class +type PhysicalDisk struct { + Name string + CurrentDiskQueueLength float64 `perflib:"Current Disk Queue Length"` + DiskReadBytesPerSec float64 `perflib:"Disk Read Bytes/sec"` + DiskReadsPerSec float64 `perflib:"Disk Reads/sec"` + DiskWriteBytesPerSec float64 `perflib:"Disk Write Bytes/sec"` + DiskWritesPerSec float64 `perflib:"Disk Writes/sec"` + PercentDiskReadTime float64 `perflib:"% Disk Read Time"` + PercentDiskWriteTime float64 `perflib:"% Disk Write Time"` + PercentIdleTime float64 `perflib:"% Idle Time"` + SplitIOPerSec float64 `perflib:"Split IO/Sec"` + AvgDiskSecPerRead float64 `perflib:"Avg. Disk sec/Read"` + AvgDiskSecPerWrite float64 `perflib:"Avg. Disk sec/Write"` + AvgDiskSecPerTransfer float64 `perflib:"Avg. Disk sec/Transfer"` +} + +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []PhysicalDisk + if err := perflib.UnmarshalObject(ctx.PerfObjects["PhysicalDisk"], &dst, c.logger); err != nil { + return nil, err + } + + for _, disk := range dst { + if disk.Name == "_Total" || + c.diskExcludePattern.MatchString(disk.Name) || + !c.diskIncludePattern.MatchString(disk.Name) { + continue + } + + // Parse physical disk number from disk.Name. Mountpoint information is + // sometimes included, e.g. "1 C:". + disk_number, _, _ := strings.Cut(disk.Name, " ") + + ch <- prometheus.MustNewConstMetric( + c.RequestsQueued, + prometheus.GaugeValue, + disk.CurrentDiskQueueLength, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadBytesTotal, + prometheus.CounterValue, + disk.DiskReadBytesPerSec, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadsTotal, + prometheus.CounterValue, + disk.DiskReadsPerSec, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteBytesTotal, + prometheus.CounterValue, + disk.DiskWriteBytesPerSec, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.WritesTotal, + prometheus.CounterValue, + disk.DiskWritesPerSec, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadTime, + prometheus.CounterValue, + disk.PercentDiskReadTime, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteTime, + prometheus.CounterValue, + disk.PercentDiskWriteTime, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.IdleTime, + prometheus.CounterValue, + disk.PercentIdleTime, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.SplitIOs, + prometheus.CounterValue, + disk.SplitIOPerSec, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadLatency, + prometheus.CounterValue, + disk.AvgDiskSecPerRead*perflib.TicksToSecondScaleFactor, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.WriteLatency, + prometheus.CounterValue, + disk.AvgDiskSecPerWrite*perflib.TicksToSecondScaleFactor, + disk_number, + ) + + ch <- prometheus.MustNewConstMetric( + c.ReadWriteLatency, + prometheus.CounterValue, + disk.AvgDiskSecPerTransfer*perflib.TicksToSecondScaleFactor, + disk_number, + ) + } + + return nil, nil +} diff --git a/collector/process.go b/pkg/collector/process/process.go similarity index 53% rename from collector/process.go rename to pkg/collector/process/process.go index 2fb2846d65..30547302bb 100644 --- a/collector/process.go +++ b/pkg/collector/process/process.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package process import ( "errors" @@ -13,11 +12,14 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) const ( + Name = "process" FlagProcessOldExclude = "collector.process.blacklist" FlagProcessOldInclude = "collector.process.whitelist" @@ -25,7 +27,19 @@ const ( FlagProcessInclude = "collector.process.include" ) -var ( +type Config struct { + ProcessInclude string `yaml:"process_include"` + ProcessExclude string `yaml:"process_exclude"` +} + +var ConfigDefaults = Config{ + ProcessInclude: ".+", + ProcessExclude: "", +} + +type collector struct { + logger log.Logger + processOldInclude *string processOldExclude *string @@ -36,10 +50,6 @@ var ( processExcludeSet bool enableWorkerProcess *bool -) - -type processCollector struct { - logger log.Logger StartTime *prometheus.Desc CPUTimeTotal *prometheus.Desc @@ -61,160 +71,193 @@ type processCollector struct { processExcludePattern *regexp.Regexp } -// newProcessCollectorFlags ... -func newProcessCollectorFlags(app *kingpin.Application) { - processInclude = app.Flag( +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + processExclude: &config.ProcessExclude, + processInclude: &config.ProcessInclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{} + + c.processInclude = app.Flag( FlagProcessInclude, "Regexp of processes to include. Process name must both match include and not match exclude to be included.", - ).Default(".*").PreAction(func(c *kingpin.ParseContext) error { - processIncludeSet = true + ).Default(".*").PreAction(func(_ *kingpin.ParseContext) error { + c.processIncludeSet = true return nil }).String() - processExclude = app.Flag( + c.processExclude = app.Flag( FlagProcessExclude, "Regexp of processes to exclude. Process name must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - processExcludeSet = true + ).Default("").PreAction(func(_ *kingpin.ParseContext) error { + c.processExcludeSet = true return nil }).String() - enableWorkerProcess = kingpin.Flag( + c.enableWorkerProcess = kingpin.Flag( "collector.process.iis", "Enable IIS worker process name queries. May cause the collector to leak memory.", ).Default("false").Bool() - processOldInclude = app.Flag( + c.processOldInclude = app.Flag( FlagProcessOldInclude, "DEPRECATED: Use --collector.process.include", ).Hidden().String() - processOldExclude = app.Flag( + c.processOldExclude = app.Flag( FlagProcessOldExclude, "DEPRECATED: Use --collector.process.exclude", ).Hidden().String() + + return c +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) } -// NewProcessCollector ... -func newProcessCollector(logger log.Logger) (Collector, error) { - const subsystem = "process" - logger = log.With(logger, "collector", subsystem) +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Process"}, nil +} - if *processOldExclude != "" { - if !processExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.process.blacklist is DEPRECATED and will be removed in a future release, use --collector.process.exclude") - *processExclude = *processOldExclude +func (c *collector) Build() error { + if *c.processOldExclude != "" { + if !c.processExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.process.blacklist is DEPRECATED and will be removed in a future release, use --collector.process.exclude") + *c.processExclude = *c.processOldExclude } else { - return nil, errors.New("--collector.process.blacklist and --collector.process.exclude are mutually exclusive") + return errors.New("--collector.process.blacklist and --collector.process.exclude are mutually exclusive") } } - if *processOldInclude != "" { - if !processIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.process.whitelist is DEPRECATED and will be removed in a future release, use --collector.process.include") - *processInclude = *processOldInclude + if *c.processOldInclude != "" { + if !c.processIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.process.whitelist is DEPRECATED and will be removed in a future release, use --collector.process.include") + *c.processInclude = *c.processOldInclude } else { - return nil, errors.New("--collector.process.whitelist and --collector.process.include are mutually exclusive") + return errors.New("--collector.process.whitelist and --collector.process.include are mutually exclusive") } } - if *processInclude == ".*" && *processExclude == "" { - _ = level.Warn(logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!") + if *c.processInclude == ".*" && *c.processExclude == "" { + _ = level.Warn(c.logger).Log("msg", "No filters specified for process collector. This will generate a very large number of metrics!") } - return &processCollector{ - logger: logger, - StartTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "start_time"), - "Time of process start.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - CPUTimeTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_time_total"), - "Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user).", - []string{"process", "process_id", "creating_process_id", "mode"}, - nil, - ), - HandleCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "handles"), - "Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - IOBytesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "io_bytes_total"), - "Bytes issued to I/O operations in different modes (read, write, other).", - []string{"process", "process_id", "creating_process_id", "mode"}, - nil, - ), - IOOperationsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "io_operations_total"), - "I/O operations issued in different modes (read, write, other).", - []string{"process", "process_id", "creating_process_id", "mode"}, - nil, - ), - PageFaultsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "page_faults_total"), - "Page faults by the threads executing in this process.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - PageFileBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "page_file_bytes"), - "Current number of bytes this process has used in the paging file(s).", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - PoolBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pool_bytes"), - "Pool Bytes is the last observed number of bytes in the paged or nonpaged pool.", - []string{"process", "process_id", "creating_process_id", "pool"}, - nil, - ), - PriorityBase: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "priority_base"), - "Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - PrivateBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "private_bytes"), - "Current number of bytes this process has allocated that cannot be shared with other processes.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - ThreadCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "threads"), - "Number of threads currently active in this process.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - VirtualBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "virtual_bytes"), - "Current size, in bytes, of the virtual address space that the process is using.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - WorkingSetPrivate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "working_set_private_bytes"), - "Size of the working set, in bytes, that is use for this process only and not shared nor shareable by other processes.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - WorkingSetPeak: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "working_set_peak_bytes"), - "Maximum size, in bytes, of the Working Set of this process at any point in time. The Working Set is the set of memory pages touched recently by the threads in the process.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - WorkingSet: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "working_set_bytes"), - "Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process.", - []string{"process", "process_id", "creating_process_id"}, - nil, - ), - processIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processInclude)), - processExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *processExclude)), - }, nil + c.StartTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "start_time"), + "Time of process start.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.CPUTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_time_total"), + "Returns elapsed time that all of the threads of this process used the processor to execute instructions by mode (privileged, user).", + []string{"process", "process_id", "creating_process_id", "mode"}, + nil, + ) + c.HandleCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "handles"), + "Total number of handles the process has open. This number is the sum of the handles currently open by each thread in the process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.IOBytesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "io_bytes_total"), + "Bytes issued to I/O operations in different modes (read, write, other).", + []string{"process", "process_id", "creating_process_id", "mode"}, + nil, + ) + c.IOOperationsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "io_operations_total"), + "I/O operations issued in different modes (read, write, other).", + []string{"process", "process_id", "creating_process_id", "mode"}, + nil, + ) + c.PageFaultsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "page_faults_total"), + "Page faults by the threads executing in this process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.PageFileBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "page_file_bytes"), + "Current number of bytes this process has used in the paging file(s).", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.PoolBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_bytes"), + "Pool Bytes is the last observed number of bytes in the paged or nonpaged pool.", + []string{"process", "process_id", "creating_process_id", "pool"}, + nil, + ) + c.PriorityBase = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "priority_base"), + "Current base priority of this process. Threads within a process can raise and lower their own base priority relative to the process base priority of the process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.PrivateBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "private_bytes"), + "Current number of bytes this process has allocated that cannot be shared with other processes.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.ThreadCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "threads"), + "Number of threads currently active in this process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.VirtualBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_bytes"), + "Current size, in bytes, of the virtual address space that the process is using.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.WorkingSetPrivate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "working_set_private_bytes"), + "Size of the working set, in bytes, that is use for this process only and not shared nor shareable by other processes.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.WorkingSetPeak = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "working_set_peak_bytes"), + "Maximum size, in bytes, of the Working Set of this process at any point in time. The Working Set is the set of memory pages touched recently by the threads in the process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + c.WorkingSet = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "working_set_bytes"), + "Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process.", + []string{"process", "process_id", "creating_process_id"}, + nil, + ) + + var err error + + c.processIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.processInclude)) + if err != nil { + return err + } + + c.processExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.processExclude)) + if err != nil { + return err + } + + return nil } type perflibProcess struct { @@ -254,16 +297,16 @@ type WorkerProcess struct { ProcessId uint64 } -func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { data := make([]perflibProcess, 0) - err := unmarshalObject(ctx.perfObjects["Process"], &data, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["Process"], &data, c.logger) if err != nil { return err } var dst_wp []WorkerProcess - if *enableWorkerProcess { - q_wp := queryAll(&dst_wp, c.logger) + if *c.enableWorkerProcess { + q_wp := wmi.QueryAll(&dst_wp, c.logger) if err := wmi.QueryNamespace(q_wp, &dst_wp, "root\\WebAdministration"); err != nil { _ = level.Debug(c.logger).Log(fmt.Sprintf("Could not query WebAdministration namespace for IIS worker processes: %v. Skipping\n", err)) } @@ -280,7 +323,7 @@ func (c *processCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metr pid := strconv.FormatUint(uint64(process.IDProcess), 10) cpid := strconv.FormatUint(uint64(process.CreatingProcessID), 10) - if *enableWorkerProcess { + if *c.enableWorkerProcess { for _, wp := range dst_wp { if wp.ProcessId == uint64(process.IDProcess) { processName = strings.Join([]string{processName, wp.AppPoolName}, "_") diff --git a/pkg/collector/process/process_test.go b/pkg/collector/process/process_test.go new file mode 100644 index 0000000000..4a86f1bb06 --- /dev/null +++ b/pkg/collector/process/process_test.go @@ -0,0 +1,17 @@ +package process_test + +import ( + "testing" + + "github.com/alecthomas/kingpin/v2" + "github.com/prometheus-community/windows_exporter/pkg/collector/process" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkProcessCollector(b *testing.B) { + // Include is not set in testing context (kingpin flags not parsed), causing the collector to skip all processes. + localProcessInclude := ".+" + kingpin.CommandLine.GetArg(process.FlagProcessInclude).StringVar(&localProcessInclude) + // No context name required as collector source is WMI + testutils.FuncBenchmarkCollector(b, process.Name, process.NewWithFlags) +} diff --git a/collector/prometheus.go b/pkg/collector/prometheus.go similarity index 51% rename from collector/prometheus.go rename to pkg/collector/prometheus.go index c9460a8de9..1cc7bdd584 100644 --- a/collector/prometheus.go +++ b/pkg/collector/prometheus.go @@ -1,5 +1,4 @@ //go:build windows -// +build windows package collector @@ -10,60 +9,62 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) -// Base metrics returned by Prometheus - -var ( - scrapeDurationDesc = prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "exporter", "collector_duration_seconds"), - "windows_exporter: Duration of a collection.", - []string{"collector"}, - nil, - ) - scrapeSuccessDesc = prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "exporter", "collector_success"), - "windows_exporter: Whether the collector was successful.", - []string{"collector"}, - nil, - ) - scrapeTimeoutDesc = prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "exporter", "collector_timeout"), - "windows_exporter: Whether the collector timed out.", - []string{"collector"}, - nil, - ) - snapshotDuration = prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "exporter", "perflib_snapshot_duration_seconds"), - "Duration of perflib snapshot capture", - nil, - nil, - ) -) - -// Prometheus implements prometheus.Collector for a set of Windows collectors. +// Prometheus implements prometheus.Collector for a set of Windows Collectors. type Prometheus struct { maxScrapeDuration time.Duration - collectors map[string]Collector + collectors *Collectors logger log.Logger + + // Base metrics returned by Prometheus + scrapeDurationDesc *prometheus.Desc + scrapeSuccessDesc *prometheus.Desc + scrapeTimeoutDesc *prometheus.Desc + snapshotDuration *prometheus.Desc } -// NewPrometheus returns a new Prometheus where the set of collectors must +// NewPrometheus returns a new Prometheus where the set of Collectors must // return metrics within the given timeout. -func NewPrometheus(timeout time.Duration, cs map[string]Collector, logger log.Logger) *Prometheus { +func NewPrometheus(timeout time.Duration, cs *Collectors, logger log.Logger) *Prometheus { return &Prometheus{ maxScrapeDuration: timeout, collectors: cs, logger: logger, + scrapeDurationDesc: prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, "exporter", "collector_duration_seconds"), + "windows_exporter: Duration of a collection.", + []string{"collector"}, + nil, + ), + scrapeSuccessDesc: prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, "exporter", "collector_success"), + "windows_exporter: Whether the collector was successful.", + []string{"collector"}, + nil, + ), + scrapeTimeoutDesc: prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, "exporter", "collector_timeout"), + "windows_exporter: Whether the collector timed out.", + []string{"collector"}, + nil, + ), + snapshotDuration: prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, "exporter", "perflib_snapshot_duration_seconds"), + "Duration of perflib snapshot capture", + nil, + nil, + ), } } -// Describe sends all the descriptors of the collectors included to +// Describe sends all the descriptors of the Collectors included to // the provided channel. func (coll *Prometheus) Describe(ch chan<- *prometheus.Desc) { - ch <- scrapeDurationDesc - ch <- scrapeSuccessDesc + ch <- coll.scrapeDurationDesc + ch <- coll.scrapeSuccessDesc } type collectorOutcome int @@ -74,29 +75,26 @@ const ( failed ) -// Collect sends the collected metrics from each of the collectors to +// Collect sends the collected metrics from each of the Collectors to // prometheus. func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) { t := time.Now() - cs := make([]string, 0, len(coll.collectors)) - for name := range coll.collectors { - cs = append(cs, name) - } - scrapeContext, err := PrepareScrapeContext(cs) + + scrapeContext, err := coll.collectors.PrepareScrapeContext() ch <- prometheus.MustNewConstMetric( - snapshotDuration, + coll.snapshotDuration, prometheus.GaugeValue, time.Since(t).Seconds(), ) if err != nil { - ch <- prometheus.NewInvalidMetric(scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %v", err)) + ch <- prometheus.NewInvalidMetric(coll.scrapeSuccessDesc, fmt.Errorf("failed to prepare scrape: %v", err)) return } wg := sync.WaitGroup{} - wg.Add(len(coll.collectors)) + wg.Add(len(coll.collectors.collectors)) collectorOutcomes := make(map[string]collectorOutcome) - for name := range coll.collectors { + for name := range coll.collectors.collectors { collectorOutcomes[name] = pending } @@ -113,10 +111,10 @@ func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) { } }() - for name, c := range coll.collectors { - go func(name string, c Collector) { + for name, c := range coll.collectors.collectors { + go func(name string, c types.Collector) { defer wg.Done() - outcome := execute(name, c, scrapeContext, metricsBuffer, coll.logger) + outcome := coll.execute(name, c, scrapeContext, metricsBuffer) l.Lock() if !finished { collectorOutcomes[name] = outcome @@ -132,7 +130,7 @@ func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) { close(metricsBuffer) }() - // Wait until either all collectors finish, or timeout expires + // Wait until either all Collectors finish, or timeout expires select { case <-allDone: case <-time.After(coll.maxScrapeDuration): @@ -153,13 +151,13 @@ func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) { } ch <- prometheus.MustNewConstMetric( - scrapeSuccessDesc, + coll.scrapeSuccessDesc, prometheus.GaugeValue, successValue, name, ) ch <- prometheus.MustNewConstMetric( - scrapeTimeoutDesc, + coll.scrapeTimeoutDesc, prometheus.GaugeValue, timeoutValue, name, @@ -173,21 +171,21 @@ func (coll *Prometheus) Collect(ch chan<- prometheus.Metric) { l.Unlock() } -func execute(name string, c Collector, ctx *ScrapeContext, ch chan<- prometheus.Metric, logger log.Logger) collectorOutcome { +func (coll *Prometheus) execute(name string, c types.Collector, ctx *types.ScrapeContext, ch chan<- prometheus.Metric) collectorOutcome { t := time.Now() err := c.Collect(ctx, ch) duration := time.Since(t).Seconds() ch <- prometheus.MustNewConstMetric( - scrapeDurationDesc, + coll.scrapeDurationDesc, prometheus.GaugeValue, duration, name, ) if err != nil { - _ = level.Error(logger).Log("msg", fmt.Sprintf("collector %s failed after %fs", name, duration), "err", err) + _ = level.Error(coll.logger).Log("msg", fmt.Sprintf("collector %s failed after %fs", name, duration), "err", err) return failed } - _ = level.Debug(logger).Log("msg", fmt.Sprintf("collector %s succeeded after %fs.", name, duration)) + _ = level.Debug(coll.logger).Log("msg", fmt.Sprintf("collector %s succeeded after %fs.", name, duration)) return success } diff --git a/collector/remote_fx.go b/pkg/collector/remote_fx/remote_fx.go similarity index 57% rename from collector/remote_fx.go rename to pkg/collector/remote_fx/remote_fx.go index f611a13208..de2c335456 100644 --- a/collector/remote_fx.go +++ b/pkg/collector/remote_fx/remote_fx.go @@ -1,22 +1,31 @@ //go:build windows -// +build windows -package collector +package remote_fx import ( "strings" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" "github.com/prometheus/client_golang/prometheus" ) +const Name = "remote_fx" + +type Config struct{} + +var ConfigDefaults = Config{} + +// collector // A RemoteFxNetworkCollector is a Prometheus collector for // WMI Win32_PerfRawData_Counters_RemoteFXNetwork & Win32_PerfRawData_Counters_RemoteFXGraphics metrics // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxnetwork/ // https://wutils.com/wmi/root/cimv2/win32_perfrawdata_counters_remotefxgraphics/ - -type RemoteFxCollector struct { +type collector struct { logger log.Logger // net @@ -31,7 +40,7 @@ type RemoteFxCollector struct { UDPPacketsReceivedPersec *prometheus.Desc UDPPacketsSentPersec *prometheus.Desc - //gfx + // gfx AverageEncodingTime *prometheus.Desc FrameQuality *prometheus.Desc FramesSkippedPerSecondInsufficientResources *prometheus.Desc @@ -41,123 +50,140 @@ type RemoteFxCollector struct { SourceFramesPerSecond *prometheus.Desc } -// newRemoteFx ... -func newRemoteFx(logger log.Logger) (Collector, error) { - const subsystem = "remote_fx" - return &RemoteFxCollector{ - logger: log.With(logger, "collector", subsystem), +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} - // net - BaseTCPRTT: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_base_tcp_rtt_seconds"), - "Base TCP round-trip time (RTT) detected in seconds", - []string{"session_name"}, - nil, - ), - BaseUDPRTT: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_base_udp_rtt_seconds"), - "Base UDP round-trip time (RTT) detected in seconds.", - []string{"session_name"}, - nil, - ), - CurrentTCPBandwidth: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_bandwidth"), - "TCP Bandwidth detected in bytes per second.", - []string{"session_name"}, - nil, - ), - CurrentTCPRTT: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_current_tcp_rtt_seconds"), - "Average TCP round-trip time (RTT) detected in seconds.", - []string{"session_name"}, - nil, - ), - CurrentUDPBandwidth: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_current_udp_bandwidth"), - "UDP Bandwidth detected in bytes per second.", - []string{"session_name"}, - nil, - ), - CurrentUDPRTT: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_current_udp_rtt_seconds"), - "Average UDP round-trip time (RTT) detected in seconds.", - []string{"session_name"}, - nil, - ), - TotalReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_received_bytes_total"), - "(TotalReceivedBytes)", - []string{"session_name"}, - nil, - ), - TotalSentBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_sent_bytes_total"), - "(TotalSentBytes)", - []string{"session_name"}, - nil, - ), - UDPPacketsReceivedPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_udp_packets_received_total"), - "Rate in packets per second at which packets are received over UDP.", - []string{"session_name"}, - nil, - ), - UDPPacketsSentPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "net_udp_packets_sent_total"), - "Rate in packets per second at which packets are sent over UDP.", - []string{"session_name"}, - nil, - ), +func (c *collector) GetName() string { + return Name +} - //gfx - AverageEncodingTime: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_average_encoding_time_seconds"), - "Average frame encoding time in seconds", - []string{"session_name"}, - nil, - ), - FrameQuality: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_frame_quality"), - "Quality of the output frame expressed as a percentage of the quality of the source frame.", - []string{"session_name"}, - nil, - ), - FramesSkippedPerSecondInsufficientResources: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_frames_skipped_insufficient_resource_total"), - "Number of frames skipped per second due to insufficient client resources.", - []string{"session_name", "resource"}, - nil, - ), - GraphicsCompressionratio: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_graphics_compression_ratio"), - "Ratio of the number of bytes encoded to the number of bytes input.", - []string{"session_name"}, - nil, - ), - InputFramesPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_input_frames_total"), - "Number of sources frames provided as input to RemoteFX graphics per second.", - []string{"session_name"}, - nil, - ), - OutputFramesPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_output_frames_total"), - "Number of frames sent to the client per second.", - []string{"session_name"}, - nil, - ), - SourceFramesPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "gfx_source_frames_total"), - "Number of frames composed by the source (DWM) per second.", - []string{"session_name"}, - nil, - ), - }, nil +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"RemoteFX Network"}, nil +} + +func (c *collector) Build() error { + // net + c.BaseTCPRTT = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_base_tcp_rtt_seconds"), + "Base TCP round-trip time (RTT) detected in seconds", + []string{"session_name"}, + nil, + ) + c.BaseUDPRTT = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_base_udp_rtt_seconds"), + "Base UDP round-trip time (RTT) detected in seconds.", + []string{"session_name"}, + nil, + ) + c.CurrentTCPBandwidth = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_current_tcp_bandwidth"), + "TCP Bandwidth detected in bytes per second.", + []string{"session_name"}, + nil, + ) + c.CurrentTCPRTT = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_current_tcp_rtt_seconds"), + "Average TCP round-trip time (RTT) detected in seconds.", + []string{"session_name"}, + nil, + ) + c.CurrentUDPBandwidth = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_current_udp_bandwidth"), + "UDP Bandwidth detected in bytes per second.", + []string{"session_name"}, + nil, + ) + c.CurrentUDPRTT = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_current_udp_rtt_seconds"), + "Average UDP round-trip time (RTT) detected in seconds.", + []string{"session_name"}, + nil, + ) + c.TotalReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_received_bytes_total"), + "(TotalReceivedBytes)", + []string{"session_name"}, + nil, + ) + c.TotalSentBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_sent_bytes_total"), + "(TotalSentBytes)", + []string{"session_name"}, + nil, + ) + c.UDPPacketsReceivedPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_udp_packets_received_total"), + "Rate in packets per second at which packets are received over UDP.", + []string{"session_name"}, + nil, + ) + c.UDPPacketsSentPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "net_udp_packets_sent_total"), + "Rate in packets per second at which packets are sent over UDP.", + []string{"session_name"}, + nil, + ) + + // gfx + c.AverageEncodingTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_average_encoding_time_seconds"), + "Average frame encoding time in seconds", + []string{"session_name"}, + nil, + ) + c.FrameQuality = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_frame_quality"), + "Quality of the output frame expressed as a percentage of the quality of the source frame.", + []string{"session_name"}, + nil, + ) + c.FramesSkippedPerSecondInsufficientResources = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_frames_skipped_insufficient_resource_total"), + "Number of frames skipped per second due to insufficient client resources.", + []string{"session_name", "resource"}, + nil, + ) + c.GraphicsCompressionratio = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_graphics_compression_ratio"), + "Ratio of the number of bytes encoded to the number of bytes input.", + []string{"session_name"}, + nil, + ) + c.InputFramesPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_input_frames_total"), + "Number of sources frames provided as input to RemoteFX graphics per second.", + []string{"session_name"}, + nil, + ) + c.OutputFramesPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_output_frames_total"), + "Number of frames sent to the client per second.", + []string{"session_name"}, + nil, + ) + c.SourceFramesPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "gfx_source_frames_total"), + "Number of frames composed by the source (DWM) per second.", + []string{"session_name"}, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *RemoteFxCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectRemoteFXNetworkCount(ctx, ch); err != nil { _ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err) return err @@ -183,9 +209,9 @@ type perflibRemoteFxNetwork struct { UDPPacketsSentPersec float64 `perflib:"UDP Packets Sent/sec"` } -func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectRemoteFXNetworkCount(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { dst := make([]perflibRemoteFxNetwork, 0) - err := unmarshalObject(ctx.perfObjects["RemoteFX Network"], &dst, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["RemoteFX Network"], &dst, c.logger) if err != nil { return nil, err } @@ -199,13 +225,13 @@ func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch c ch <- prometheus.MustNewConstMetric( c.BaseTCPRTT, prometheus.GaugeValue, - milliSecToSec(d.BaseTCPRTT), + utils.MilliSecToSec(d.BaseTCPRTT), d.Name, ) ch <- prometheus.MustNewConstMetric( c.BaseUDPRTT, prometheus.GaugeValue, - milliSecToSec(d.BaseUDPRTT), + utils.MilliSecToSec(d.BaseUDPRTT), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -217,7 +243,7 @@ func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch c ch <- prometheus.MustNewConstMetric( c.CurrentTCPRTT, prometheus.GaugeValue, - milliSecToSec(d.CurrentTCPRTT), + utils.MilliSecToSec(d.CurrentTCPRTT), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -229,7 +255,7 @@ func (c *RemoteFxCollector) collectRemoteFXNetworkCount(ctx *ScrapeContext, ch c ch <- prometheus.MustNewConstMetric( c.CurrentUDPRTT, prometheus.GaugeValue, - milliSecToSec(d.CurrentUDPRTT), + utils.MilliSecToSec(d.CurrentUDPRTT), d.Name, ) ch <- prometheus.MustNewConstMetric( @@ -273,9 +299,9 @@ type perflibRemoteFxGraphics struct { SourceFramesPerSecond float64 `perflib:"Source Frames/Second"` } -func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectRemoteFXGraphicsCounters(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { dst := make([]perflibRemoteFxGraphics, 0) - err := unmarshalObject(ctx.perfObjects["RemoteFX Graphics"], &dst, c.logger) + err := perflib.UnmarshalObject(ctx.PerfObjects["RemoteFX Graphics"], &dst, c.logger) if err != nil { return nil, err } @@ -289,7 +315,7 @@ func (c *RemoteFxCollector) collectRemoteFXGraphicsCounters(ctx *ScrapeContext, ch <- prometheus.MustNewConstMetric( c.AverageEncodingTime, prometheus.GaugeValue, - milliSecToSec(d.AverageEncodingTime), + utils.MilliSecToSec(d.AverageEncodingTime), d.Name, ) ch <- prometheus.MustNewConstMetric( diff --git a/pkg/collector/remote_fx/remote_fx_test.go b/pkg/collector/remote_fx/remote_fx_test.go new file mode 100644 index 0000000000..872e7ba6f9 --- /dev/null +++ b/pkg/collector/remote_fx/remote_fx_test.go @@ -0,0 +1,12 @@ +package remote_fx_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/remote_fx" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, remote_fx.Name, remote_fx.NewWithFlags) +} diff --git a/collector/scheduled_task.go b/pkg/collector/scheduled_task/scheduled_task.go similarity index 70% rename from collector/scheduled_task.go rename to pkg/collector/scheduled_task/scheduled_task.go index ccd0a33510..0bed452cc9 100644 --- a/collector/scheduled_task.go +++ b/pkg/collector/scheduled_task/scheduled_task.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package scheduled_task import ( "errors" @@ -13,12 +12,14 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" - ole "github.com/go-ole/go-ole" + "github.com/go-ole/go-ole" "github.com/go-ole/go-ole/oleutil" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) const ( + Name = "scheduled_task" FlagScheduledTaskOldExclude = "collector.scheduled_task.blacklist" FlagScheduledTaskOldInclude = "collector.scheduled_task.whitelist" @@ -26,7 +27,19 @@ const ( FlagScheduledTaskInclude = "collector.scheduled_task.include" ) -var ( +type Config struct { + TaskExclude string `yaml:"task_exclude"` + TaskInclude string `yaml:"task_include"` +} + +var ConfigDefaults = Config{ + TaskExclude: "", + TaskInclude: ".+", +} + +type collector struct { + logger log.Logger + taskOldExclude *string taskOldInclude *string @@ -35,10 +48,6 @@ var ( taskIncludeSet bool taskExcludeSet bool -) - -type ScheduledTaskCollector struct { - logger log.Logger LastResult *prometheus.Desc MissedRuns *prometheus.Desc @@ -75,53 +84,77 @@ type ScheduledTask struct { type ScheduledTasks []ScheduledTask -// newScheduledTask ... -func newScheduledTaskFlags(app *kingpin.Application) { - taskInclude = app.Flag( +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + taskExclude: &config.TaskExclude, + taskInclude: &config.TaskInclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{} + + c.taskInclude = app.Flag( FlagScheduledTaskInclude, "Regexp of tasks to include. Task path must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - taskIncludeSet = true + ).Default(ConfigDefaults.TaskInclude).PreAction(func(_ *kingpin.ParseContext) error { + c.taskIncludeSet = true return nil }).String() - taskExclude = app.Flag( + c.taskExclude = app.Flag( FlagScheduledTaskExclude, "Regexp of tasks to exclude. Task path must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - taskExcludeSet = true + ).Default(ConfigDefaults.TaskExclude).PreAction(func(_ *kingpin.ParseContext) error { + c.taskExcludeSet = true return nil }).String() - taskOldInclude = app.Flag( + c.taskOldInclude = app.Flag( FlagScheduledTaskOldInclude, "DEPRECATED: Use --collector.scheduled_task.include", ).Hidden().String() - taskOldExclude = app.Flag( + c.taskOldExclude = app.Flag( FlagScheduledTaskOldExclude, "DEPRECATED: Use --collector.scheduled_task.exclude", ).Hidden().String() + + return c } -// newScheduledTask ... -func newScheduledTask(logger log.Logger) (Collector, error) { - const subsystem = "scheduled_task" - logger = log.With(logger, "collector", subsystem) +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} - if *taskOldExclude != "" { - if !taskExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.scheduled_task.blacklist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.exclude") - *taskExclude = *taskOldExclude +func (c *collector) Build() error { + if *c.taskOldExclude != "" { + if !c.taskExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.scheduled_task.blacklist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.exclude") + *c.taskExclude = *c.taskOldExclude } else { - return nil, errors.New("--collector.scheduled_task.blacklist and --collector.scheduled_task.exclude are mutually exclusive") + return errors.New("--collector.scheduled_task.blacklist and --collector.scheduled_task.exclude are mutually exclusive") } } - if *taskOldInclude != "" { - if !taskIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.scheduled_task.whitelist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.include") - *taskInclude = *taskOldInclude + if *c.taskOldInclude != "" { + if !c.taskIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.scheduled_task.whitelist is DEPRECATED and will be removed in a future release, use --collector.scheduled_task.include") + *c.taskInclude = *c.taskOldInclude } else { - return nil, errors.New("--collector.scheduled_task.whitelist and --collector.scheduled_task.include are mutually exclusive") + return errors.New("--collector.scheduled_task.whitelist and --collector.scheduled_task.include are mutually exclusive") } } @@ -132,40 +165,46 @@ func newScheduledTask(logger log.Logger) (Collector, error) { if err != nil { code := err.(*ole.OleError).Code() if code != ole.S_OK && code != S_FALSE { - return nil, err + return err } } defer ole.CoUninitialize() - return &ScheduledTaskCollector{ - logger: logger, - LastResult: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "last_result"), - "The result that was returned the last time the registered task was run", - []string{"task"}, - nil, - ), - - MissedRuns: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "missed_runs"), - "The number of times the registered task missed a scheduled run", - []string{"task"}, - nil, - ), - - State: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "state"), - "The current state of a scheduled task", - []string{"task", "state"}, - nil, - ), - - taskIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskInclude)), - taskExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *taskExclude)), - }, nil + c.LastResult = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "last_result"), + "The result that was returned the last time the registered task was run", + []string{"task"}, + nil, + ) + + c.MissedRuns = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "missed_runs"), + "The number of times the registered task missed a scheduled run", + []string{"task"}, + nil, + ) + + c.State = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "state"), + "The current state of a scheduled task", + []string{"task", "state"}, + nil, + ) + + c.taskIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.taskInclude)) + if err != nil { + return err + } + + c.taskExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.taskExclude)) + if err != nil { + return err + } + + return nil } -func (c *ScheduledTaskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting user metrics", "desc", desc, "err", err) return err @@ -176,7 +215,7 @@ func (c *ScheduledTaskCollector) Collect(ctx *ScrapeContext, ch chan<- prometheu var TASK_STATES = []string{"disabled", "queued", "ready", "running", "unknown"} -func (c *ScheduledTaskCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { scheduledTasks, err := getScheduledTasks() if err != nil { return nil, err diff --git a/pkg/collector/scheduled_task/scheduled_task_test.go b/pkg/collector/scheduled_task/scheduled_task_test.go new file mode 100644 index 0000000000..c1495b9dcf --- /dev/null +++ b/pkg/collector/scheduled_task/scheduled_task_test.go @@ -0,0 +1,12 @@ +package scheduled_task_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/scheduled_task" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, scheduled_task.Name, scheduled_task.NewWithFlags) +} diff --git a/pkg/collector/service/service.go b/pkg/collector/service/service.go new file mode 100644 index 0000000000..4067bb8309 --- /dev/null +++ b/pkg/collector/service/service.go @@ -0,0 +1,363 @@ +//go:build windows + +package service + +import ( + "fmt" + "strconv" + "strings" + "syscall" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" + "golang.org/x/sys/windows" + "golang.org/x/sys/windows/svc/mgr" +) + +const ( + Name = "service" + FlagServiceWhereClause = "collector.service.services-where" + FlagServiceUseAPI = "collector.service.use-api" +) + +type Config struct { + ServiceWhereClause string `yaml:"service_where_clause"` + UseAPI bool `yaml:"use_api"` +} + +var ConfigDefaults = Config{ + ServiceWhereClause: "", + UseAPI: false, +} + +// A collector is a Prometheus collector for WMI Win32_Service metrics +type collector struct { + logger log.Logger + + serviceWhereClause *string + useAPI *bool + + Information *prometheus.Desc + State *prometheus.Desc + StartMode *prometheus.Desc + Status *prometheus.Desc + + queryWhereClause string +} + +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + serviceWhereClause: &config.ServiceWhereClause, + useAPI: &config.UseAPI, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + return &collector{ + serviceWhereClause: app.Flag( + FlagServiceWhereClause, + "WQL 'where' clause to use in WMI metrics query. Limits the response to the services you specify and reduces the size of the response.", + ).Default(ConfigDefaults.ServiceWhereClause).String(), + useAPI: app.Flag( + FlagServiceUseAPI, + "Use API calls to collect service data instead of WMI. Flag 'collector.service.services-where' won't be effective.", + ).Default(strconv.FormatBool(ConfigDefaults.UseAPI)).Bool(), + } +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + if *c.serviceWhereClause == "" { + _ = level.Warn(c.logger).Log("msg", "No where-clause specified for service collector. This will generate a very large number of metrics!") + } + if *c.useAPI { + _ = level.Warn(c.logger).Log("msg", "API collection is enabled.") + } + + c.Information = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "info"), + "A metric with a constant '1' value labeled with service information", + []string{"name", "display_name", "process_id", "run_as"}, + nil, + ) + c.State = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "state"), + "The state of the service (State)", + []string{"name", "state"}, + nil, + ) + c.StartMode = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "start_mode"), + "The start mode of the service (StartMode)", + []string{"name", "start_mode"}, + nil, + ) + c.Status = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "status"), + "The status of the service (Status)", + []string{"name", "status"}, + nil, + ) + c.queryWhereClause = *c.serviceWhereClause + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if *c.useAPI { + if err := c.collectAPI(ch); err != nil { + _ = level.Error(c.logger).Log("msg", "failed collecting API service metrics:", "err", err) + return err + } + } else { + if err := c.collectWMI(ch); err != nil { + _ = level.Error(c.logger).Log("msg", "failed collecting WMI service metrics:", "err", err) + return err + } + } + return nil +} + +// Win32_Service docs: +// - https://msdn.microsoft.com/en-us/library/aa394418(v=vs.85).aspx +type Win32_Service struct { + DisplayName string + Name string + ProcessId uint32 + State string + Status string + StartMode string + StartName *string +} + +var ( + allStates = []string{ + "stopped", + "start pending", + "stop pending", + "running", + "continue pending", + "pause pending", + "paused", + "unknown", + } + apiStateValues = map[uint]string{ + windows.SERVICE_CONTINUE_PENDING: "continue pending", + windows.SERVICE_PAUSE_PENDING: "pause pending", + windows.SERVICE_PAUSED: "paused", + windows.SERVICE_RUNNING: "running", + windows.SERVICE_START_PENDING: "start pending", + windows.SERVICE_STOP_PENDING: "stop pending", + windows.SERVICE_STOPPED: "stopped", + } + allStartModes = []string{ + "boot", + "system", + "auto", + "manual", + "disabled", + } + apiStartModeValues = map[uint32]string{ + windows.SERVICE_AUTO_START: "auto", + windows.SERVICE_BOOT_START: "boot", + windows.SERVICE_DEMAND_START: "manual", + windows.SERVICE_DISABLED: "disabled", + windows.SERVICE_SYSTEM_START: "system", + } + allStatuses = []string{ + "ok", + "error", + "degraded", + "unknown", + "pred fail", + "starting", + "stopping", + "service", + "stressed", + "nonrecover", + "no contact", + "lost comm", + } +) + +func (c *collector) collectWMI(ch chan<- prometheus.Metric) error { + var dst []Win32_Service + q := wmi.QueryAllWhere(&dst, c.queryWhereClause, c.logger) + if err := wmi.Query(q, &dst); err != nil { + return err + } + for _, service := range dst { + pid := fmt.Sprintf("%d", uint64(service.ProcessId)) + + runAs := "" + if service.StartName != nil { + runAs = *service.StartName + } + ch <- prometheus.MustNewConstMetric( + c.Information, + prometheus.GaugeValue, + 1.0, + strings.ToLower(service.Name), + service.DisplayName, + pid, + runAs, + ) + + for _, state := range allStates { + isCurrentState := 0.0 + if state == strings.ToLower(service.State) { + isCurrentState = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + isCurrentState, + strings.ToLower(service.Name), + state, + ) + } + + for _, startMode := range allStartModes { + isCurrentStartMode := 0.0 + if startMode == strings.ToLower(service.StartMode) { + isCurrentStartMode = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.StartMode, + prometheus.GaugeValue, + isCurrentStartMode, + strings.ToLower(service.Name), + startMode, + ) + } + + for _, status := range allStatuses { + isCurrentStatus := 0.0 + if status == strings.ToLower(service.Status) { + isCurrentStatus = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.Status, + prometheus.GaugeValue, + isCurrentStatus, + strings.ToLower(service.Name), + status, + ) + } + } + return nil +} + +func (c *collector) collectAPI(ch chan<- prometheus.Metric) error { + svcmgrConnection, err := mgr.Connect() + if err != nil { + return err + } + defer svcmgrConnection.Disconnect() //nolint:errcheck + + // List All Services from the Services Manager. + serviceList, err := svcmgrConnection.ListServices() + if err != nil { + return err + } + + // Iterate through the Services List. + for _, service := range serviceList { + (func() { + // Get UTF16 service name. + serviceName, err := syscall.UTF16PtrFromString(service) + if err != nil { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Service %s get name error: %#v", service, err)) + return + } + + // Open connection for service handler. + serviceHandle, err := windows.OpenService(svcmgrConnection.Handle, serviceName, windows.GENERIC_READ) + if err != nil { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Open service %s error: %#v", service, err)) + return + } + + // Create handle for each service. + serviceManager := &mgr.Service{Name: service, Handle: serviceHandle} + defer serviceManager.Close() + + // Get Service Configuration. + serviceConfig, err := serviceManager.Config() + if err != nil { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get service %s config error: %#v", service, err)) + return + } + + // Get Service Current Status. + serviceStatus, err := serviceManager.Query() + if err != nil { + _ = level.Warn(c.logger).Log("msg", fmt.Sprintf("Get service %s status error: %#v", service, err)) + return + } + + pid := fmt.Sprintf("%d", uint64(serviceStatus.ProcessId)) + + ch <- prometheus.MustNewConstMetric( + c.Information, + prometheus.GaugeValue, + 1.0, + strings.ToLower(service), + serviceConfig.DisplayName, + pid, + serviceConfig.ServiceStartName, + ) + + for _, state := range apiStateValues { + isCurrentState := 0.0 + if state == apiStateValues[uint(serviceStatus.State)] { + isCurrentState = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.State, + prometheus.GaugeValue, + isCurrentState, + strings.ToLower(service), + state, + ) + } + + for _, startMode := range apiStartModeValues { + isCurrentStartMode := 0.0 + if startMode == apiStartModeValues[serviceConfig.StartType] { + isCurrentStartMode = 1.0 + } + ch <- prometheus.MustNewConstMetric( + c.StartMode, + prometheus.GaugeValue, + isCurrentStartMode, + strings.ToLower(service), + startMode, + ) + } + })() + } + return nil +} diff --git a/pkg/collector/service/service_test.go b/pkg/collector/service/service_test.go new file mode 100644 index 0000000000..bb97c07080 --- /dev/null +++ b/pkg/collector/service/service_test.go @@ -0,0 +1,12 @@ +package service_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/service" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, service.Name, service.NewWithFlags) +} diff --git a/collector/smtp.go b/pkg/collector/smtp/smtp.go similarity index 56% rename from collector/smtp.go rename to pkg/collector/smtp/smtp.go index ee779c27de..d4446566e3 100644 --- a/collector/smtp.go +++ b/pkg/collector/smtp/smtp.go @@ -1,7 +1,6 @@ //go:build windows -// +build windows -package collector +package smtp import ( "errors" @@ -11,10 +10,13 @@ import ( "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) const ( + Name = "smtp" FlagSmtpServerOldExclude = "collector.smtp.server-blacklist" FlagSmtpServerOldInclude = "collector.smtp.server-whitelist" @@ -22,7 +24,19 @@ const ( FlagSmtpServerInclude = "collector.smtp.server-include" ) -var ( +type Config struct { + ServerInclude string `yaml:"server_include"` + ServerExclude string `yaml:"server_exclude"` +} + +var ConfigDefaults = Config{ + ServerInclude: ".+", + ServerExclude: "", +} + +type collector struct { + logger log.Logger + serverOldInclude *string serverOldExclude *string @@ -31,10 +45,6 @@ var ( serverIncludeSet bool serverExcludeSet bool -) - -type SMTPCollector struct { - logger log.Logger BadmailedMessagesBadPickupFileTotal *prometheus.Desc BadmailedMessagesGeneralFailureTotal *prometheus.Desc @@ -83,319 +93,353 @@ type SMTPCollector struct { serverExcludePattern *regexp.Regexp } -func newSMTPCollectorFlags(app *kingpin.Application) { - serverInclude = app.Flag( +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + c := &collector{ + serverExclude: &config.ServerExclude, + serverInclude: &config.ServerInclude, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + c := &collector{} + + c.serverInclude = app.Flag( FlagSmtpServerInclude, "Regexp of virtual servers to include. Server name must both match include and not match exclude to be included.", - ).Default(".+").PreAction(func(c *kingpin.ParseContext) error { - serverIncludeSet = true + ).Default(ConfigDefaults.ServerInclude).PreAction(func(_ *kingpin.ParseContext) error { + c.serverIncludeSet = true return nil }).String() - serverExclude = app.Flag( + c.serverExclude = app.Flag( FlagSmtpServerExclude, "Regexp of virtual servers to exclude. Server name must both match include and not match exclude to be included.", - ).Default("").PreAction(func(c *kingpin.ParseContext) error { - serverExcludeSet = true + ).Default(ConfigDefaults.ServerExclude).PreAction(func(_ *kingpin.ParseContext) error { + c.serverExcludeSet = true return nil }).String() - serverOldInclude = app.Flag( + c.serverOldInclude = app.Flag( FlagSmtpServerOldInclude, "DEPRECATED: Use --collector.smtp.server-include", ).Hidden().String() - serverOldExclude = app.Flag( + c.serverOldExclude = app.Flag( FlagSmtpServerOldExclude, "DEPRECATED: Use --collector.smtp.server-exclude", ).Hidden().String() + + return c +} + +func (c *collector) GetName() string { + return Name } -func newSMTPCollector(logger log.Logger) (Collector, error) { - const subsystem = "smtp" - logger = log.With(logger, "collector", subsystem) +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"SMTP Server"}, nil +} - _ = level.Info(logger).Log("msg", "smtp collector is in an experimental state! Metrics for this collector have not been tested.") +func (c *collector) Build() error { + _ = level.Info(c.logger).Log("msg", "smtp collector is in an experimental state! Metrics for this collector have not been tested.") - if *serverOldExclude != "" { - if !serverExcludeSet { - _ = level.Warn(logger).Log("msg", "--collector.smtp.server-blacklist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-exclude") - *serverExclude = *serverOldExclude + if *c.serverOldExclude != "" { + if !c.serverExcludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.smtp.server-blacklist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-exclude") + *c.serverExclude = *c.serverOldExclude } else { - return nil, errors.New("--collector.smtp.server-blacklist and --collector.smtp.server-exclude are mutually exclusive") + return errors.New("--collector.smtp.server-blacklist and --collector.smtp.server-exclude are mutually exclusive") } } - if *serverOldInclude != "" { - if !serverIncludeSet { - _ = level.Warn(logger).Log("msg", "--collector.smtp.server-whitelist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-include") - *serverInclude = *serverOldInclude + if *c.serverOldInclude != "" { + if !c.serverIncludeSet { + _ = level.Warn(c.logger).Log("msg", "--collector.smtp.server-whitelist is DEPRECATED and will be removed in a future release, use --collector.smtp.server-include") + *c.serverInclude = *c.serverOldInclude } else { - return nil, errors.New("--collector.smtp.server-whitelist and --collector.smtp.server-include are mutually exclusive") + return errors.New("--collector.smtp.server-whitelist and --collector.smtp.server-include are mutually exclusive") } } - return &SMTPCollector{ - logger: logger, - BadmailedMessagesBadPickupFileTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_bad_pickup_file_total"), - "Total number of malformed pickup messages sent to badmail", - []string{"site"}, - nil, - ), - BadmailedMessagesGeneralFailureTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_general_failure_total"), - "Total number of messages sent to badmail for reasons not associated with a specific counter", - []string{"site"}, - nil, - ), - BadmailedMessagesHopCountExceededTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_hop_count_exceeded_total"), - "Total number of messages sent to badmail because they had exceeded the maximum hop count", - []string{"site"}, - nil, - ), - BadmailedMessagesNDROfDSNTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_ndr_of_dns_total"), - "Total number of Delivery Status Notifications sent to badmail because they could not be delivered", - []string{"site"}, - nil, - ), - BadmailedMessagesNoRecipientsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_no_recipients_total"), - "Total number of messages sent to badmail because they had no recipients", - []string{"site"}, - nil, - ), - BadmailedMessagesTriggeredViaEventTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "badmailed_messages_triggered_via_event_total"), - "Total number of messages sent to badmail at the request of a server event sink", - []string{"site"}, - nil, - ), - BytesSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"), - "Total number of bytes sent", - []string{"site"}, - nil, - ), - BytesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"), - "Total number of bytes received", - []string{"site"}, - nil, - ), - CategorizerQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "categorizer_queue_length"), - "Number of messages in the categorizer queue", - []string{"site"}, - nil, - ), - ConnectionErrorsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_errors_total"), - "Total number of connection errors", - []string{"site"}, - nil, - ), - CurrentMessagesInLocalDelivery: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "current_messages_in_local_delivery"), - "Number of messages that are currently being processed by a server event sink for local delivery", - []string{"site"}, - nil, - ), - DirectoryDropsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "directory_drops_total"), - "Total number of messages placed in a drop directory", - []string{"site"}, - nil, - ), - DSNFailuresTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dsn_failures_total"), - "Total number of failed DSN generation attempts", - []string{"site"}, - nil, - ), - DNSQueriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "dns_queries_total"), - "Total number of DNS lookups", - []string{"site"}, - nil, - ), - ETRNMessagesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "etrn_messages_total"), - "Total number of ETRN messages received by the server", - []string{"site"}, - nil, - ), - InboundConnectionsCurrent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "inbound_connections_current"), - "Total number of connections currently inbound", - []string{"site"}, - nil, - ), - InboundConnectionsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "inbound_connections_total"), - "Total number of inbound connections received", - []string{"site"}, - nil, - ), - LocalQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "local_queue_length"), - "Number of messages in the local queue", - []string{"site"}, - nil, - ), - LocalRetryQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "local_retry_queue_length"), - "Number of messages in the local retry queue", - []string{"site"}, - nil, - ), - MailFilesOpen: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mail_files_open"), - "Number of handles to open mail files", - []string{"site"}, - nil, - ), - MessageBytesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "message_bytes_received_total"), - "Total number of bytes received in messages", - []string{"site"}, - nil, - ), - MessageBytesSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "message_bytes_sent_total"), - "Total number of bytes sent in messages", - []string{"site"}, - nil, - ), - MessageDeliveryRetriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "message_delivery_retries_total"), - "Total number of local deliveries that were retried", - []string{"site"}, - nil, - ), - MessageSendRetriesTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "message_send_retries_total"), - "Total number of outbound message sends that were retried", - []string{"site"}, - nil, - ), - MessagesCurrentlyUndeliverable: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_currently_undeliverable"), - "Number of messages that have been reported as currently undeliverable by routing", - []string{"site"}, - nil, - ), - MessagesDeliveredTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_delivered_total"), - "Total number of messages delivered to local mailboxes", - []string{"site"}, - nil, - ), - MessagesPendingRouting: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_pending_routing"), - "Number of messages that have been categorized but not routed", - []string{"site"}, - nil, - ), - MessagesReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_received_total"), - "Total number of inbound messages accepted", - []string{"site"}, - nil, - ), - MessagesRefusedForAddressObjectsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_address_objects_total"), - "Total number of messages refused due to no address objects", - []string{"site"}, - nil, - ), - MessagesRefusedForMailObjectsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_mail_objects_total"), - "Total number of messages refused due to no mail objects", - []string{"site"}, - nil, - ), - MessagesRefusedForSizeTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_refused_for_size_total"), - "Total number of messages rejected because they were too big", - []string{"site"}, - nil, - ), - MessagesSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_sent_total"), - "Total number of outbound messages sent", - []string{"site"}, - nil, - ), - MessagesSubmittedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "messages_submitted_total"), - "Total number of messages submitted to queuing for delivery", - []string{"site"}, - nil, - ), - NDRsGeneratedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "ndrs_generated_total"), - "Total number of non-delivery reports that have been generated", - []string{"site"}, - nil, - ), - OutboundConnectionsCurrent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_current"), - "Number of connections currently outbound", - []string{"site"}, - nil, - ), - OutboundConnectionsRefusedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_refused_total"), - "Total number of connection attempts refused by remote sites", - []string{"site"}, - nil, - ), - OutboundConnectionsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "outbound_connections_total"), - "Total number of outbound connections attempted", - []string{"site"}, - nil, - ), - PickupDirectoryMessagesRetrievedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "pickup_directory_messages_retrieved_total"), - "Total number of messages retrieved from the mail pick-up directory", - []string{"site"}, - nil, - ), - QueueFilesOpen: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "queue_files_open"), - "Number of handles to open queue files", - []string{"site"}, - nil, - ), - RemoteQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "remote_queue_length"), - "Number of messages in the remote queue", - []string{"site"}, - nil, - ), - RemoteRetryQueueLength: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "remote_retry_queue_length"), - "Number of messages in the retry queue for remote delivery", - []string{"site"}, - nil, - ), - RoutingTableLookupsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "routing_table_lookups_total"), - "Total number of routing table lookups", - []string{"site"}, - nil, - ), - - serverIncludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverInclude)), - serverExcludePattern: regexp.MustCompile(fmt.Sprintf("^(?:%s)$", *serverExclude)), - }, nil + c.BadmailedMessagesBadPickupFileTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_bad_pickup_file_total"), + "Total number of malformed pickup messages sent to badmail", + []string{"site"}, + nil, + ) + c.BadmailedMessagesGeneralFailureTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_general_failure_total"), + "Total number of messages sent to badmail for reasons not associated with a specific counter", + []string{"site"}, + nil, + ) + c.BadmailedMessagesHopCountExceededTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_hop_count_exceeded_total"), + "Total number of messages sent to badmail because they had exceeded the maximum hop count", + []string{"site"}, + nil, + ) + c.BadmailedMessagesNDROfDSNTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_ndr_of_dns_total"), + "Total number of Delivery Status Notifications sent to badmail because they could not be delivered", + []string{"site"}, + nil, + ) + c.BadmailedMessagesNoRecipientsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_no_recipients_total"), + "Total number of messages sent to badmail because they had no recipients", + []string{"site"}, + nil, + ) + c.BadmailedMessagesTriggeredViaEventTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "badmailed_messages_triggered_via_event_total"), + "Total number of messages sent to badmail at the request of a server event sink", + []string{"site"}, + nil, + ) + c.BytesSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_sent_total"), + "Total number of bytes sent", + []string{"site"}, + nil, + ) + c.BytesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_received_total"), + "Total number of bytes received", + []string{"site"}, + nil, + ) + c.CategorizerQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "categorizer_queue_length"), + "Number of messages in the categorizer queue", + []string{"site"}, + nil, + ) + c.ConnectionErrorsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_errors_total"), + "Total number of connection errors", + []string{"site"}, + nil, + ) + c.CurrentMessagesInLocalDelivery = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "current_messages_in_local_delivery"), + "Number of messages that are currently being processed by a server event sink for local delivery", + []string{"site"}, + nil, + ) + c.DirectoryDropsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "directory_drops_total"), + "Total number of messages placed in a drop directory", + []string{"site"}, + nil, + ) + c.DSNFailuresTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dsn_failures_total"), + "Total number of failed DSN generation attempts", + []string{"site"}, + nil, + ) + c.DNSQueriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "dns_queries_total"), + "Total number of DNS lookups", + []string{"site"}, + nil, + ) + c.ETRNMessagesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "etrn_messages_total"), + "Total number of ETRN messages received by the server", + []string{"site"}, + nil, + ) + c.InboundConnectionsCurrent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "inbound_connections_current"), + "Total number of connections currently inbound", + []string{"site"}, + nil, + ) + c.InboundConnectionsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "inbound_connections_total"), + "Total number of inbound connections received", + []string{"site"}, + nil, + ) + c.LocalQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "local_queue_length"), + "Number of messages in the local queue", + []string{"site"}, + nil, + ) + c.LocalRetryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "local_retry_queue_length"), + "Number of messages in the local retry queue", + []string{"site"}, + nil, + ) + c.MailFilesOpen = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mail_files_open"), + "Number of handles to open mail files", + []string{"site"}, + nil, + ) + c.MessageBytesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "message_bytes_received_total"), + "Total number of bytes received in messages", + []string{"site"}, + nil, + ) + c.MessageBytesSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "message_bytes_sent_total"), + "Total number of bytes sent in messages", + []string{"site"}, + nil, + ) + c.MessageDeliveryRetriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "message_delivery_retries_total"), + "Total number of local deliveries that were retried", + []string{"site"}, + nil, + ) + c.MessageSendRetriesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "message_send_retries_total"), + "Total number of outbound message sends that were retried", + []string{"site"}, + nil, + ) + c.MessagesCurrentlyUndeliverable = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_currently_undeliverable"), + "Number of messages that have been reported as currently undeliverable by routing", + []string{"site"}, + nil, + ) + c.MessagesDeliveredTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_delivered_total"), + "Total number of messages delivered to local mailboxes", + []string{"site"}, + nil, + ) + c.MessagesPendingRouting = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_pending_routing"), + "Number of messages that have been categorized but not routed", + []string{"site"}, + nil, + ) + c.MessagesReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_received_total"), + "Total number of inbound messages accepted", + []string{"site"}, + nil, + ) + c.MessagesRefusedForAddressObjectsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_refused_for_address_objects_total"), + "Total number of messages refused due to no address objects", + []string{"site"}, + nil, + ) + c.MessagesRefusedForMailObjectsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_refused_for_mail_objects_total"), + "Total number of messages refused due to no mail objects", + []string{"site"}, + nil, + ) + c.MessagesRefusedForSizeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_refused_for_size_total"), + "Total number of messages rejected because they were too big", + []string{"site"}, + nil, + ) + c.MessagesSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_sent_total"), + "Total number of outbound messages sent", + []string{"site"}, + nil, + ) + c.MessagesSubmittedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "messages_submitted_total"), + "Total number of messages submitted to queuing for delivery", + []string{"site"}, + nil, + ) + c.NDRsGeneratedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ndrs_generated_total"), + "Total number of non-delivery reports that have been generated", + []string{"site"}, + nil, + ) + c.OutboundConnectionsCurrent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "outbound_connections_current"), + "Number of connections currently outbound", + []string{"site"}, + nil, + ) + c.OutboundConnectionsRefusedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "outbound_connections_refused_total"), + "Total number of connection attempts refused by remote sites", + []string{"site"}, + nil, + ) + c.OutboundConnectionsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "outbound_connections_total"), + "Total number of outbound connections attempted", + []string{"site"}, + nil, + ) + c.PickupDirectoryMessagesRetrievedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pickup_directory_messages_retrieved_total"), + "Total number of messages retrieved from the mail pick-up directory", + []string{"site"}, + nil, + ) + c.QueueFilesOpen = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "queue_files_open"), + "Number of handles to open queue files", + []string{"site"}, + nil, + ) + c.RemoteQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "remote_queue_length"), + "Number of messages in the remote queue", + []string{"site"}, + nil, + ) + c.RemoteRetryQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "remote_retry_queue_length"), + "Number of messages in the retry queue for remote delivery", + []string{"site"}, + nil, + ) + c.RoutingTableLookupsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "routing_table_lookups_total"), + "Total number of routing table lookups", + []string{"site"}, + nil, + ) + + var err error + + c.serverIncludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.serverInclude)) + if err != nil { + return err + } + + c.serverExcludePattern, err = regexp.Compile(fmt.Sprintf("^(?:%s)$", *c.serverExclude)) + if err != nil { + return err + } + + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *SMTPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ctx, ch); err != nil { _ = level.Error(c.logger).Log("failed collecting smtp metrics", "desc", desc, "err", err) return err @@ -403,7 +447,7 @@ func (c *SMTPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) return nil } -// Perflib: "SMTP Server" +// PerflibSMTPServer Perflib: "SMTP Server" type PerflibSMTPServer struct { Name string @@ -451,9 +495,9 @@ type PerflibSMTPServer struct { RoutingTableLookupsTotal float64 `perflib:"Routing Table Lookups Total"` } -func (c *SMTPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []PerflibSMTPServer - if err := unmarshalObject(ctx.perfObjects["SMTP Server"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["SMTP Server"], &dst, c.logger); err != nil { return nil, err } diff --git a/pkg/collector/smtp/smtp_test.go b/pkg/collector/smtp/smtp_test.go new file mode 100644 index 0000000000..713f1ad675 --- /dev/null +++ b/pkg/collector/smtp/smtp_test.go @@ -0,0 +1,12 @@ +package smtp_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/smtp" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, smtp.Name, smtp.NewWithFlags) +} diff --git a/pkg/collector/system/system.go b/pkg/collector/system/system.go new file mode 100644 index 0000000000..22379da753 --- /dev/null +++ b/pkg/collector/system/system.go @@ -0,0 +1,152 @@ +//go:build windows + +package system + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "system" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI metrics +type collector struct { + logger log.Logger + + ContextSwitchesTotal *prometheus.Desc + ExceptionDispatchesTotal *prometheus.Desc + ProcessorQueueLength *prometheus.Desc + SystemCallsTotal *prometheus.Desc + SystemUpTime *prometheus.Desc + Threads *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"System"}, nil +} + +func (c *collector) Build() error { + c.ContextSwitchesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "context_switches_total"), + "Total number of context switches (WMI source: PerfOS_System.ContextSwitchesPersec)", + nil, + nil, + ) + c.ExceptionDispatchesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "exception_dispatches_total"), + "Total number of exceptions dispatched (WMI source: PerfOS_System.ExceptionDispatchesPersec)", + nil, + nil, + ) + c.ProcessorQueueLength = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_queue_length"), + "Length of processor queue (WMI source: PerfOS_System.ProcessorQueueLength)", + nil, + nil, + ) + c.SystemCallsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_calls_total"), + "Total number of system calls (WMI source: PerfOS_System.SystemCallsPersec)", + nil, + nil, + ) + c.SystemUpTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "system_up_time"), + "System boot time (WMI source: PerfOS_System.SystemUpTime)", + nil, + nil, + ) + c.Threads = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "threads"), + "Current number of threads (WMI source: PerfOS_System.Threads)", + nil, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting system metrics", "desc", desc, "err", err) + return err + } + return nil +} + +// Win32_PerfRawData_PerfOS_System docs: +// - https://web.archive.org/web/20050830140516/http://msdn.microsoft.com/library/en-us/wmisdk/wmi/win32_perfrawdata_perfos_system.asp +type system struct { + ContextSwitchesPersec float64 `perflib:"Context Switches/sec"` + ExceptionDispatchesPersec float64 `perflib:"Exception Dispatches/sec"` + ProcessorQueueLength float64 `perflib:"Processor Queue Length"` + SystemCallsPersec float64 `perflib:"System Calls/sec"` + SystemUpTime float64 `perflib:"System Up Time"` + Threads float64 `perflib:"Threads"` +} + +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []system + if err := perflib.UnmarshalObject(ctx.PerfObjects["System"], &dst, c.logger); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.ContextSwitchesTotal, + prometheus.CounterValue, + dst[0].ContextSwitchesPersec, + ) + ch <- prometheus.MustNewConstMetric( + c.ExceptionDispatchesTotal, + prometheus.CounterValue, + dst[0].ExceptionDispatchesPersec, + ) + ch <- prometheus.MustNewConstMetric( + c.ProcessorQueueLength, + prometheus.GaugeValue, + dst[0].ProcessorQueueLength, + ) + ch <- prometheus.MustNewConstMetric( + c.SystemCallsTotal, + prometheus.CounterValue, + dst[0].SystemCallsPersec, + ) + ch <- prometheus.MustNewConstMetric( + c.SystemUpTime, + prometheus.GaugeValue, + dst[0].SystemUpTime, + ) + ch <- prometheus.MustNewConstMetric( + c.Threads, + prometheus.GaugeValue, + dst[0].Threads, + ) + return nil, nil +} diff --git a/pkg/collector/system/system_test.go b/pkg/collector/system/system_test.go new file mode 100644 index 0000000000..d20e3720b7 --- /dev/null +++ b/pkg/collector/system/system_test.go @@ -0,0 +1,12 @@ +package system_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/system" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, system.Name, system.NewWithFlags) +} diff --git a/collector/tcp.go b/pkg/collector/tcp/tcp.go similarity index 53% rename from collector/tcp.go rename to pkg/collector/tcp/tcp.go index b557185018..5235f7ac00 100644 --- a/collector/tcp.go +++ b/pkg/collector/tcp/tcp.go @@ -1,16 +1,24 @@ //go:build windows -// +build windows -package collector +package tcp import ( + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" ) -// A TCPCollector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics -type TCPCollector struct { +const Name = "tcp" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_Tcpip_TCPv{4,6} metrics +type collector struct { logger log.Logger ConnectionFailures *prometheus.Desc @@ -24,72 +32,89 @@ type TCPCollector struct { SegmentsSentTotal *prometheus.Desc } -// newTCPCollector ... -func newTCPCollector(logger log.Logger) (Collector, error) { - const subsystem = "tcp" - - return &TCPCollector{ - logger: log.With(logger, "collector", subsystem), - ConnectionFailures: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connection_failures_total"), - "(TCP.ConnectionFailures)", - []string{"af"}, - nil, - ), - ConnectionsActive: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connections_active_total"), - "(TCP.ConnectionsActive)", - []string{"af"}, - nil, - ), - ConnectionsEstablished: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connections_established"), - "(TCP.ConnectionsEstablished)", - []string{"af"}, - nil, - ), - ConnectionsPassive: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connections_passive_total"), - "(TCP.ConnectionsPassive)", - []string{"af"}, - nil, - ), - ConnectionsReset: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "connections_reset_total"), - "(TCP.ConnectionsReset)", - []string{"af"}, - nil, - ), - SegmentsTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "segments_total"), - "(TCP.SegmentsTotal)", - []string{"af"}, - nil, - ), - SegmentsReceivedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "segments_received_total"), - "(TCP.SegmentsReceivedTotal)", - []string{"af"}, - nil, - ), - SegmentsRetransmittedTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "segments_retransmitted_total"), - "(TCP.SegmentsRetransmittedTotal)", - []string{"af"}, - nil, - ), - SegmentsSentTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "segments_sent_total"), - "(TCP.SegmentsSentTotal)", - []string{"af"}, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"TCPv4"}, nil +} + +func (c *collector) Build() error { + c.ConnectionFailures = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_failures_total"), + "(TCP.ConnectionFailures)", + []string{"af"}, + nil, + ) + c.ConnectionsActive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connections_active_total"), + "(TCP.ConnectionsActive)", + []string{"af"}, + nil, + ) + c.ConnectionsEstablished = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connections_established"), + "(TCP.ConnectionsEstablished)", + []string{"af"}, + nil, + ) + c.ConnectionsPassive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connections_passive_total"), + "(TCP.ConnectionsPassive)", + []string{"af"}, + nil, + ) + c.ConnectionsReset = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connections_reset_total"), + "(TCP.ConnectionsReset)", + []string{"af"}, + nil, + ) + c.SegmentsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "segments_total"), + "(TCP.SegmentsTotal)", + []string{"af"}, + nil, + ) + c.SegmentsReceivedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "segments_received_total"), + "(TCP.SegmentsReceivedTotal)", + []string{"af"}, + nil, + ) + c.SegmentsRetransmittedTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "segments_retransmitted_total"), + "(TCP.SegmentsRetransmittedTotal)", + []string{"af"}, + nil, + ) + c.SegmentsSentTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "segments_sent_total"), + "(TCP.SegmentsSentTotal)", + []string{"af"}, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *TCPCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ctx, ch); err != nil { _ = level.Error(c.logger).Log("failed collecting tcp metrics", "desc", desc, "err", err) return err @@ -112,7 +137,7 @@ type tcp struct { SegmentsSentPersec float64 `perflib:"Segments Sent/sec"` } -func writeTCPCounters(metrics tcp, labels []string, c *TCPCollector, ch chan<- prometheus.Metric) { +func writeTCPCounters(metrics tcp, labels []string, c *collector, ch chan<- prometheus.Metric) { ch <- prometheus.MustNewConstMetric( c.ConnectionFailures, prometheus.CounterValue, @@ -169,11 +194,11 @@ func writeTCPCounters(metrics tcp, labels []string, c *TCPCollector, ch chan<- p ) } -func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []tcp // TCPv4 counters - if err := unmarshalObject(ctx.perfObjects["TCPv4"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["TCPv4"], &dst, c.logger); err != nil { return nil, err } if len(dst) != 0 { @@ -181,7 +206,7 @@ func (c *TCPCollector) collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) } // TCPv6 counters - if err := unmarshalObject(ctx.perfObjects["TCPv6"], &dst, c.logger); err != nil { + if err := perflib.UnmarshalObject(ctx.PerfObjects["TCPv6"], &dst, c.logger); err != nil { return nil, err } if len(dst) != 0 { diff --git a/pkg/collector/tcp/tcp_test.go b/pkg/collector/tcp/tcp_test.go new file mode 100644 index 0000000000..4bcbdfc827 --- /dev/null +++ b/pkg/collector/tcp/tcp_test.go @@ -0,0 +1,12 @@ +package tcp_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/tcp" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, tcp.Name, tcp.NewWithFlags) +} diff --git a/collector/teradici_pcoip.go b/pkg/collector/teradici_pcoip/teradici_pcoip.go similarity index 61% rename from collector/teradici_pcoip.go rename to pkg/collector/teradici_pcoip/teradici_pcoip.go index e6094af051..71ca59344b 100644 --- a/collector/teradici_pcoip.go +++ b/pkg/collector/teradici_pcoip/teradici_pcoip.go @@ -1,25 +1,31 @@ //go:build windows -// +build windows -package collector +package teradici_pcoip //nolint:revive import ( "errors" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A teradiciPcoipCollector is a Prometheus collector for WMI metrics: +const Name = "teradici_pcoip" + +type Config struct{} + +var ConfigDefaults = Config{} + +// collector is a Prometheus collector for WMI metrics: // win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics // win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics - -type teradiciPcoipCollector struct { +type collector struct { logger log.Logger AudioBytesReceived *prometheus.Desc @@ -65,243 +71,261 @@ type teradiciPcoipCollector struct { USBTXBWkbitPersec *prometheus.Desc } -// newTeradiciPcoipCollector constructs a new teradiciPcoipCollector -func newTeradiciPcoipCollector(logger log.Logger) (Collector, error) { - const subsystem = "teradici_pcoip" - return &teradiciPcoipCollector{ - logger: log.With(logger, "collector", subsystem), - AudioBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_bytes_received_total"), - "(AudioBytesReceived)", - nil, - nil, - ), - AudioBytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_bytes_sent_total"), - "(AudioBytesSent)", - nil, - nil, - ), - AudioRXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_rx_bw_kbit_persec"), - "(AudioRXBWkbitPersec)", - nil, - nil, - ), - AudioTXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_tx_bw_kbit_persec"), - "(AudioTXBWkbitPersec)", - nil, - nil, - ), - AudioTXBWLimitkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_tx_bw_limit_kbit_persec"), - "(AudioTXBWLimitkbitPersec)", - nil, - nil, - ), - - BytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_received_total"), - "(BytesReceived)", - nil, - nil, - ), - BytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "bytes_sent_total"), - "(BytesSent)", - nil, - nil, - ), - PacketsReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_received_total"), - "(PacketsReceived)", - nil, - nil, - ), - PacketsSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "packets_sent_total"), - "(PacketsSent)", - nil, - nil, - ), - RXPacketsLost: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rx_packets_lost_total"), - "(RXPacketsLost)", - nil, - nil, - ), - SessionDurationSeconds: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_duration_seconds_total"), - "(SessionDurationSeconds)", - nil, - nil, - ), - TXPacketsLost: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tx_packets_lost_total"), - "(TXPacketsLost)", - nil, - nil, - ), - - ImagingActiveMinimumQuality: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_active_min_quality"), - "(ImagingActiveMinimumQuality)", - nil, - nil, - ), - ImagingApex2800Offload: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_apex2800_offload"), - "(ImagingApex2800Offload)", - nil, - nil, - ), - ImagingBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_bytes_received_total"), - "(ImagingBytesReceived)", - nil, - nil, - ), - ImagingBytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_bytes_sent_total"), - "(ImagingBytesSent)", - nil, - nil, - ), - ImagingDecoderCapabilitykbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_decoder_capability_kbit_persec"), - "(ImagingDecoderCapabilitykbitPersec)", - nil, - nil, - ), - ImagingEncodedFramesPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_encoded_frames_persec"), - "(ImagingEncodedFramesPersec)", - nil, - nil, - ), - ImagingMegapixelPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_megapixel_persec"), - "(ImagingMegapixelPersec)", - nil, - nil, - ), - ImagingNegativeAcknowledgements: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_negative_acks_total"), - "(ImagingNegativeAcknowledgements)", - nil, - nil, - ), - ImagingRXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_rx_bw_kbit_persec"), - "(ImagingRXBWkbitPersec)", - nil, - nil, - ), - ImagingSVGAdevTapframesPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_svga_devtap_frames_persec"), - "(ImagingSVGAdevTapframesPersec)", - nil, - nil, - ), - ImagingTXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_tx_bw_kbit_persec"), - "(ImagingTXBWkbitPersec)", - nil, - nil, - ), - - RoundTripLatencyms: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "round_trip_latency_ms"), - "(RoundTripLatencyms)", - nil, - nil, - ), - RXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rx_bw_kbit_persec"), - "(RXBWkbitPersec)", - nil, - nil, - ), - RXBWPeakkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rx_bw_peak_kbit_persec"), - "(RXBWPeakkbitPersec)", - nil, - nil, - ), - RXPacketLossPercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rx_packet_loss_percent"), - "(RXPacketLossPercent)", - nil, - nil, - ), - RXPacketLossPercent_Base: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rx_packet_loss_percent_base"), - "(RXPacketLossPercent_Base)", - nil, - nil, - ), - TXBWActiveLimitkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tx_bw_active_limit_kbit_persec"), - "(TXBWActiveLimitkbitPersec)", - nil, - nil, - ), - TXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tx_bw_kbit_persec"), - "(TXBWkbitPersec)", - nil, - nil, - ), - TXBWLimitkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tx_bw_limit_kbit_persec"), - "(TXBWLimitkbitPersec)", - nil, - nil, - ), - TXPacketLossPercent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tx_packet_loss_percent"), - "(TXPacketLossPercent)", - nil, - nil, - ), - TXPacketLossPercent_Base: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "tx_packet_loss_percent_base"), - "(TXPacketLossPercent_Base)", - nil, - nil, - ), - - USBBytesReceived: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_bytes_received_total"), - "(USBBytesReceived)", - nil, - nil, - ), - USBBytesSent: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_bytes_sent_total"), - "(USBBytesSent)", - nil, - nil, - ), - USBRXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_rx_bw_kbit_persec"), - "(USBRXBWkbitPersec)", - nil, - nil, - ), - USBTXBWkbitPersec: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_tx_bw_kbit_persec"), - "(USBTXBWkbitPersec)", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.AudioBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_bytes_received_total"), + "(AudioBytesReceived)", + nil, + nil, + ) + c.AudioBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_bytes_sent_total"), + "(AudioBytesSent)", + nil, + nil, + ) + c.AudioRXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_rx_bw_kbit_persec"), + "(AudioRXBWkbitPersec)", + nil, + nil, + ) + c.AudioTXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_tx_bw_kbit_persec"), + "(AudioTXBWkbitPersec)", + nil, + nil, + ) + c.AudioTXBWLimitkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_tx_bw_limit_kbit_persec"), + "(AudioTXBWLimitkbitPersec)", + nil, + nil, + ) + + c.BytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_received_total"), + "(BytesReceived)", + nil, + nil, + ) + c.BytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "bytes_sent_total"), + "(BytesSent)", + nil, + nil, + ) + c.PacketsReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_received_total"), + "(PacketsReceived)", + nil, + nil, + ) + c.PacketsSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "packets_sent_total"), + "(PacketsSent)", + nil, + nil, + ) + c.RXPacketsLost = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rx_packets_lost_total"), + "(RXPacketsLost)", + nil, + nil, + ) + c.SessionDurationSeconds = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_duration_seconds_total"), + "(SessionDurationSeconds)", + nil, + nil, + ) + c.TXPacketsLost = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tx_packets_lost_total"), + "(TXPacketsLost)", + nil, + nil, + ) + + c.ImagingActiveMinimumQuality = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_active_min_quality"), + "(ImagingActiveMinimumQuality)", + nil, + nil, + ) + c.ImagingApex2800Offload = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_apex2800_offload"), + "(ImagingApex2800Offload)", + nil, + nil, + ) + c.ImagingBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_bytes_received_total"), + "(ImagingBytesReceived)", + nil, + nil, + ) + c.ImagingBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_bytes_sent_total"), + "(ImagingBytesSent)", + nil, + nil, + ) + c.ImagingDecoderCapabilitykbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_decoder_capability_kbit_persec"), + "(ImagingDecoderCapabilitykbitPersec)", + nil, + nil, + ) + c.ImagingEncodedFramesPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_encoded_frames_persec"), + "(ImagingEncodedFramesPersec)", + nil, + nil, + ) + c.ImagingMegapixelPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_megapixel_persec"), + "(ImagingMegapixelPersec)", + nil, + nil, + ) + c.ImagingNegativeAcknowledgements = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_negative_acks_total"), + "(ImagingNegativeAcknowledgements)", + nil, + nil, + ) + c.ImagingRXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_rx_bw_kbit_persec"), + "(ImagingRXBWkbitPersec)", + nil, + nil, + ) + c.ImagingSVGAdevTapframesPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_svga_devtap_frames_persec"), + "(ImagingSVGAdevTapframesPersec)", + nil, + nil, + ) + c.ImagingTXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_tx_bw_kbit_persec"), + "(ImagingTXBWkbitPersec)", + nil, + nil, + ) + + c.RoundTripLatencyms = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "round_trip_latency_ms"), + "(RoundTripLatencyms)", + nil, + nil, + ) + c.RXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rx_bw_kbit_persec"), + "(RXBWkbitPersec)", + nil, + nil, + ) + c.RXBWPeakkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rx_bw_peak_kbit_persec"), + "(RXBWPeakkbitPersec)", + nil, + nil, + ) + c.RXPacketLossPercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rx_packet_loss_percent"), + "(RXPacketLossPercent)", + nil, + nil, + ) + c.RXPacketLossPercent_Base = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rx_packet_loss_percent_base"), + "(RXPacketLossPercent_Base)", + nil, + nil, + ) + c.TXBWActiveLimitkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tx_bw_active_limit_kbit_persec"), + "(TXBWActiveLimitkbitPersec)", + nil, + nil, + ) + c.TXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tx_bw_kbit_persec"), + "(TXBWkbitPersec)", + nil, + nil, + ) + c.TXBWLimitkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tx_bw_limit_kbit_persec"), + "(TXBWLimitkbitPersec)", + nil, + nil, + ) + c.TXPacketLossPercent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tx_packet_loss_percent"), + "(TXPacketLossPercent)", + nil, + nil, + ) + c.TXPacketLossPercent_Base = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "tx_packet_loss_percent_base"), + "(TXPacketLossPercent_Base)", + nil, + nil, + ) + + c.USBBytesReceived = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_bytes_received_total"), + "(USBBytesReceived)", + nil, + nil, + ) + c.USBBytesSent = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_bytes_sent_total"), + "(USBBytesSent)", + nil, + nil, + ) + c.USBRXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_rx_bw_kbit_persec"), + "(USBRXBWkbitPersec)", + nil, + nil, + ) + c.USBTXBWkbitPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_tx_bw_kbit_persec"), + "(USBTXBWkbitPersec)", + nil, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *teradiciPcoipCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectAudio(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting teradici session audio metrics", "desc", desc, "err", err) return err @@ -377,9 +401,9 @@ type win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics struct { USBTXBWkbitPersec uint64 } -func (c *teradiciPcoipCollector) collectAudio(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectAudio(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionAudioStatistics - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -420,9 +444,9 @@ func (c *teradiciPcoipCollector) collectAudio(ch chan<- prometheus.Metric) (*pro return nil, nil } -func (c *teradiciPcoipCollector) collectGeneral(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectGeneral(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionGeneralStatistics - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -475,9 +499,9 @@ func (c *teradiciPcoipCollector) collectGeneral(ch chan<- prometheus.Metric) (*p return nil, nil } -func (c *teradiciPcoipCollector) collectImaging(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectImaging(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionImagingStatistics - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -554,9 +578,9 @@ func (c *teradiciPcoipCollector) collectImaging(ch chan<- prometheus.Metric) (*p return nil, nil } -func (c *teradiciPcoipCollector) collectNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectNetwork(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionNetworkStatistics - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -627,9 +651,9 @@ func (c *teradiciPcoipCollector) collectNetwork(ch chan<- prometheus.Metric) (*p return nil, nil } -func (c *teradiciPcoipCollector) collectUsb(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectUsb(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_TeradiciPerf_PCoIPSessionUsbStatistics - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/teradici_pcoip/teradici_pcoip_test.go b/pkg/collector/teradici_pcoip/teradici_pcoip_test.go new file mode 100644 index 0000000000..f25e50c283 --- /dev/null +++ b/pkg/collector/teradici_pcoip/teradici_pcoip_test.go @@ -0,0 +1,12 @@ +package teradici_pcoip_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/teradici_pcoip" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, teradici_pcoip.Name, teradici_pcoip.NewWithFlags) +} diff --git a/pkg/collector/terminal_services/terminal_services.go b/pkg/collector/terminal_services/terminal_services.go new file mode 100644 index 0000000000..eca174fc30 --- /dev/null +++ b/pkg/collector/terminal_services/terminal_services.go @@ -0,0 +1,441 @@ +//go:build windows + +package terminal_services //nolint:revive + +import ( + "errors" + "strings" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" + "github.com/prometheus/client_golang/prometheus" +) + +const ( + Name = "terminal_services" + ConnectionBrokerFeatureID uint32 = 133 +) + +type Config struct{} + +var ConfigDefaults = Config{} + +type Win32_ServerFeature struct { + ID uint32 +} + +func isConnectionBrokerServer(logger log.Logger) bool { + var dst []Win32_ServerFeature + q := wmi.QueryAll(&dst, logger) + if err := wmi.Query(q, &dst); err != nil { + return false + } + for _, d := range dst { + if d.ID == ConnectionBrokerFeatureID { + return true + } + } + _ = level.Debug(logger).Log("msg", "host is not a connection broker skipping Connection Broker performance metrics.") + return false +} + +// A collector is a Prometheus collector for WMI +// Win32_PerfRawData_LocalSessionManager_TerminalServices & Win32_PerfRawData_TermService_TerminalServicesSession metrics +// https://docs.microsoft.com/en-us/previous-versions/aa394344(v%3Dvs.85) +// https://wutils.com/wmi/root/cimv2/win32_perfrawdata_localsessionmanager_terminalservices/ +type collector struct { + logger log.Logger + + connectionBrokerEnabled bool + + LocalSessionCount *prometheus.Desc + ConnectionBrokerPerformance *prometheus.Desc + HandleCount *prometheus.Desc + PageFaultsPersec *prometheus.Desc + PageFileBytes *prometheus.Desc + PageFileBytesPeak *prometheus.Desc + PercentPrivilegedTime *prometheus.Desc + PercentProcessorTime *prometheus.Desc + PercentUserTime *prometheus.Desc + PoolNonpagedBytes *prometheus.Desc + PoolPagedBytes *prometheus.Desc + PrivateBytes *prometheus.Desc + ThreadCount *prometheus.Desc + VirtualBytes *prometheus.Desc + VirtualBytesPeak *prometheus.Desc + WorkingSet *prometheus.Desc + WorkingSetPeak *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{ + "Terminal Services", + "Terminal Services Session", + "Remote Desktop Connection Broker Counterset", + }, nil +} + +func (c *collector) Build() error { + c.connectionBrokerEnabled = isConnectionBrokerServer(c.logger) + + c.LocalSessionCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "local_session_count"), + "Number of Terminal Services sessions", + []string{"session"}, + nil, + ) + c.ConnectionBrokerPerformance = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "connection_broker_performance_total"), + "The total number of connections handled by the Connection Brokers since the service started.", + []string{"connection"}, + nil, + ) + c.HandleCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "handles"), + "Total number of handles currently opened by this process. This number is the sum of the handles currently opened by each thread in this process.", + []string{"session_name"}, + nil, + ) + c.PageFaultsPersec = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "page_fault_total"), + "Rate at which page faults occur in the threads executing in this process. A page fault occurs when a thread refers to a virtual memory page that is not in its working set in main memory. The page may not be retrieved from disk if it is on the standby list and therefore already in main memory. The page also may not be retrieved if it is in use by another process which shares the page.", + []string{"session_name"}, + nil, + ) + c.PageFileBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "page_file_bytes"), + "Current number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", + []string{"session_name"}, + nil, + ) + c.PageFileBytesPeak = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "page_file_bytes_peak"), + "Maximum number of bytes this process has used in the paging file(s). Paging files are used to store pages of memory used by the process that are not contained in other files. Paging files are shared by all processes, and lack of space in paging files can prevent other processes from allocating memory.", + []string{"session_name"}, + nil, + ) + c.PercentPrivilegedTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "privileged_time_seconds_total"), + "Total elapsed time that the threads of the process have spent executing code in privileged mode.", + []string{"session_name"}, + nil, + ) + c.PercentProcessorTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "processor_time_seconds_total"), + "Total elapsed time that all of the threads of this process used the processor to execute instructions.", + []string{"session_name"}, + nil, + ) + c.PercentUserTime = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "user_time_seconds_total"), + "Total elapsed time that this process's threads have spent executing code in user mode. Applications, environment Names, and integral Names execute in user mode.", + []string{"session_name"}, + nil, + ) + c.PoolNonpagedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_non_paged_bytes"), + "Number of bytes in the non-paged pool, an area of system memory (physical memory used by the operating system) for objects that cannot be written to disk, but must remain in physical memory as long as they are allocated. This property displays the last observed value only; it is not an average.", + []string{"session_name"}, + nil, + ) + c.PoolPagedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "pool_paged_bytes"), + "Number of bytes in the paged pool, an area of system memory (physical memory used by the operating system) for objects that can be written to disk when they are not being used. This property displays the last observed value only; it is not an average.", + []string{"session_name"}, + nil, + ) + c.PrivateBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "private_bytes"), + "Current number of bytes this process has allocated that cannot be shared with other processes.", + []string{"session_name"}, + nil, + ) + c.ThreadCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "threads"), + "Number of threads currently active in this process. An instruction is the basic unit of execution in a processor, and a thread is the object that executes instructions. Every running process has at least one thread.", + []string{"session_name"}, + nil, + ) + c.VirtualBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_bytes"), + "Current size, in bytes, of the virtual address space the process is using. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process can limit its ability to load libraries.", + []string{"session_name"}, + nil, + ) + c.VirtualBytesPeak = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "virtual_bytes_peak"), + "Maximum number of bytes of virtual address space the process has used at any one time. Use of virtual address space does not necessarily imply corresponding use of either disk or main memory pages. Virtual space is finite and, by using too much, the process might limit its ability to load libraries.", + []string{"session_name"}, + nil, + ) + c.WorkingSet = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "working_set_bytes"), + "Current number of bytes in the working set of this process. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", + []string{"session_name"}, + nil, + ) + c.WorkingSetPeak = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "working_set_bytes_peak"), + "Maximum number of bytes in the working set of this process at any point in time. The working set is the set of memory pages touched recently by the threads in the process. If free memory in the computer is above a threshold, pages are left in the working set of a process even if they are not in use. When free memory falls below a threshold, pages are trimmed from working sets. If they are needed, they are then soft-faulted back into the working set before they leave main memory.", + []string{"session_name"}, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collectTSSessionCount(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err) + return err + } + if desc, err := c.collectTSSessionCounters(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting terminal services session count metrics", "desc", desc, "err", err) + return err + } + + // only collect CollectionBrokerPerformance if host is a Connection Broker + if c.connectionBrokerEnabled { + if desc, err := c.collectCollectionBrokerPerformanceCounter(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting Connection Broker performance metrics", "desc", desc, "err", err) + return err + } + } + return nil +} + +type perflibTerminalServices struct { + ActiveSessions float64 `perflib:"Active Sessions"` + InactiveSessions float64 `perflib:"Inactive Sessions"` + TotalSessions float64 `perflib:"Total Sessions"` +} + +func (c *collector) collectTSSessionCount(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibTerminalServices, 0) + err := perflib.UnmarshalObject(ctx.PerfObjects["Terminal Services"], &dst, c.logger) + if err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.LocalSessionCount, + prometheus.GaugeValue, + dst[0].ActiveSessions, + "active", + ) + + ch <- prometheus.MustNewConstMetric( + c.LocalSessionCount, + prometheus.GaugeValue, + dst[0].InactiveSessions, + "inactive", + ) + + ch <- prometheus.MustNewConstMetric( + c.LocalSessionCount, + prometheus.GaugeValue, + dst[0].TotalSessions, + "total", + ) + + return nil, nil +} + +type perflibTerminalServicesSession struct { + Name string + HandleCount float64 `perflib:"Handle Count"` + PageFaultsPersec float64 `perflib:"Page Faults/sec"` + PageFileBytes float64 `perflib:"Page File Bytes"` + PageFileBytesPeak float64 `perflib:"Page File Bytes Peak"` + PercentPrivilegedTime float64 `perflib:"% Privileged Time"` + PercentProcessorTime float64 `perflib:"% Processor Time"` + PercentUserTime float64 `perflib:"% User Time"` + PoolNonpagedBytes float64 `perflib:"Pool Nonpaged Bytes"` + PoolPagedBytes float64 `perflib:"Pool Paged Bytes"` + PrivateBytes float64 `perflib:"Private Bytes"` + ThreadCount float64 `perflib:"Thread Count"` + VirtualBytes float64 `perflib:"Virtual Bytes"` + VirtualBytesPeak float64 `perflib:"Virtual Bytes Peak"` + WorkingSet float64 `perflib:"Working Set"` + WorkingSetPeak float64 `perflib:"Working Set Peak"` +} + +func (c *collector) collectTSSessionCounters(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibTerminalServicesSession, 0) + err := perflib.UnmarshalObject(ctx.PerfObjects["Terminal Services Session"], &dst, c.logger) + if err != nil { + return nil, err + } + names := make(map[string]bool) + + for _, d := range dst { + // only connect metrics for remote named sessions + n := strings.ToLower(d.Name) + if n == "" || n == "services" || n == "console" { + continue + } + // don't add name already present in labels list + if _, ok := names[n]; ok { + continue + } + names[n] = true + + ch <- prometheus.MustNewConstMetric( + c.HandleCount, + prometheus.GaugeValue, + d.HandleCount, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PageFaultsPersec, + prometheus.CounterValue, + d.PageFaultsPersec, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PageFileBytes, + prometheus.GaugeValue, + d.PageFileBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PageFileBytesPeak, + prometheus.GaugeValue, + d.PageFileBytesPeak, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PercentPrivilegedTime, + prometheus.CounterValue, + d.PercentPrivilegedTime, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PercentProcessorTime, + prometheus.CounterValue, + d.PercentProcessorTime, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PercentUserTime, + prometheus.CounterValue, + d.PercentUserTime, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PoolNonpagedBytes, + prometheus.GaugeValue, + d.PoolNonpagedBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PoolPagedBytes, + prometheus.GaugeValue, + d.PoolPagedBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.PrivateBytes, + prometheus.GaugeValue, + d.PrivateBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.ThreadCount, + prometheus.GaugeValue, + d.ThreadCount, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.VirtualBytes, + prometheus.GaugeValue, + d.VirtualBytes, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.VirtualBytesPeak, + prometheus.GaugeValue, + d.VirtualBytesPeak, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.WorkingSet, + prometheus.GaugeValue, + d.WorkingSet, + d.Name, + ) + ch <- prometheus.MustNewConstMetric( + c.WorkingSetPeak, + prometheus.GaugeValue, + d.WorkingSetPeak, + d.Name, + ) + } + return nil, nil +} + +type perflibRemoteDesktopConnectionBrokerCounterset struct { + SuccessfulConnections float64 `perflib:"Successful Connections"` + PendingConnections float64 `perflib:"Pending Connections"` + FailedConnections float64 `perflib:"Failed Connections"` +} + +func (c *collector) collectCollectionBrokerPerformanceCounter(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + dst := make([]perflibRemoteDesktopConnectionBrokerCounterset, 0) + err := perflib.UnmarshalObject(ctx.PerfObjects["Remote Desktop Connection Broker Counterset"], &dst, c.logger) + if err != nil { + return nil, err + } + if len(dst) == 0 { + return nil, errors.New("WMI query returned empty result set") + } + + ch <- prometheus.MustNewConstMetric( + c.ConnectionBrokerPerformance, + prometheus.CounterValue, + dst[0].SuccessfulConnections, + "Successful", + ) + + ch <- prometheus.MustNewConstMetric( + c.ConnectionBrokerPerformance, + prometheus.CounterValue, + dst[0].PendingConnections, + "Pending", + ) + + ch <- prometheus.MustNewConstMetric( + c.ConnectionBrokerPerformance, + prometheus.CounterValue, + dst[0].FailedConnections, + "Failed", + ) + + return nil, nil +} diff --git a/pkg/collector/terminal_services/terminal_services_test.go b/pkg/collector/terminal_services/terminal_services_test.go new file mode 100644 index 0000000000..dac213a6a9 --- /dev/null +++ b/pkg/collector/terminal_services/terminal_services_test.go @@ -0,0 +1,12 @@ +package terminal_services_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/terminal_services" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, terminal_services.Name, terminal_services.NewWithFlags) +} diff --git a/collector/textfile.go b/pkg/collector/textfile/textfile.go similarity index 80% rename from collector/textfile.go rename to pkg/collector/textfile/textfile.go index 6585c72911..9be16e0a3f 100644 --- a/collector/textfile.go +++ b/pkg/collector/textfile/textfile.go @@ -12,9 +12,8 @@ // limitations under the License. //go:build !notextfile -// +build !notextfile -package collector +package textfile import ( "fmt" @@ -30,62 +29,94 @@ import ( "github.com/dimchansky/utfbom" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" "github.com/prometheus/common/expfmt" ) const ( + Name = "textfile" FlagTextFileDirectory = "collector.textfile.directory" FlagTextFileDirectories = "collector.textfile.directories" ) -var ( - textFileDirectory *string - textFileDirectories *string +type Config struct { + TextFileDirectories string `yaml:"text_file_directories"` +} - mtimeDesc = prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "textfile", "mtime_seconds"), - "Unixtime mtime of textfiles successfully read.", - []string{"file"}, - nil, - ) -) +var ConfigDefaults = Config{ + TextFileDirectories: getDefaultPath(), +} -type textFileCollector struct { +type collector struct { logger log.Logger + textFileDirectory *string + textFileDirectories *string + directories string // Only set for testing to get predictable output. mtime *float64 + + MtimeDesc *prometheus.Desc +} + +func New(logger log.Logger, config *Config) types.Collector { + if config == nil { + config = &ConfigDefaults + } + + textFileDirectory := "" + c := &collector{ + textFileDirectories: &config.TextFileDirectories, + textFileDirectory: &textFileDirectory, + } + c.SetLogger(logger) + return c +} + +func NewWithFlags(app *kingpin.Application) types.Collector { + return &collector{ + textFileDirectory: app.Flag( + FlagTextFileDirectory, + "DEPRECATED: Use --collector.textfile.directories", + ).Default("").Hidden().String(), + textFileDirectories: app.Flag( + FlagTextFileDirectories, + "Directory or Directories to read text files with metrics from.", + ).Default(ConfigDefaults.TextFileDirectories).String(), + } +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) } -// newTextFileCollectorFlags ... -func newTextFileCollectorFlags(app *kingpin.Application) { - textFileDirectory = app.Flag( - FlagTextFileDirectory, - "DEPRECATED: Use --collector.textfile.directories", - ).Default("").Hidden().String() - textFileDirectories = app.Flag( - FlagTextFileDirectories, - "Directory or Directories to read text files with metrics from.", - ).Default("").String() +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil } -// newTextFileCollector returns a new Collector exposing metrics read from files -// in the given textfile directory. -func newTextFileCollector(logger log.Logger) (Collector, error) { - const subsystem = "textfile" - directories := getDefaultPath() - if *textFileDirectory != "" || *textFileDirectories != "" { - directories = *textFileDirectory + "," + *textFileDirectories - directories = strings.Trim(directories, ",") +func (c *collector) Build() error { + c.directories = "" + if *c.textFileDirectory != "" || *c.textFileDirectories != "" { + c.directories = *c.textFileDirectory + "," + *c.textFileDirectories + c.directories = strings.Trim(c.directories, ",") } - _ = level.Info(logger).Log("msg", fmt.Sprintf("textfile collector directories: %s", directories)) - return &textFileCollector{ - logger: log.With(logger, "collector", subsystem), - directories: directories, - }, nil + _ = level.Info(c.logger).Log("msg", fmt.Sprintf("textfile collector directories: %s", c.directories)) + + c.MtimeDesc = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, "textfile", "mtime_seconds"), + "Unixtime mtime of textfiles successfully read.", + []string{"file"}, + nil, + ) + + return nil } // Given a slice of metric families, determine if any two entries are duplicates. @@ -113,7 +144,7 @@ func duplicateMetricEntry(metricFamilies []*dto.MetricFamily) bool { return false } -func (c *textFileCollector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) { +func (c *collector) convertMetricFamily(metricFamily *dto.MetricFamily, ch chan<- prometheus.Metric) { var valType prometheus.ValueType var val float64 @@ -215,7 +246,7 @@ func (c *textFileCollector) convertMetricFamily(metricFamily *dto.MetricFamily, } } -func (c *textFileCollector) exportMTimes(mtimes map[string]time.Time, ch chan<- prometheus.Metric) { +func (c *collector) exportMTimes(mtimes map[string]time.Time, ch chan<- prometheus.Metric) { // Export the mtimes of the successful files. if len(mtimes) > 0 { // Sorting is needed for predictable output comparison in tests. @@ -230,7 +261,7 @@ func (c *textFileCollector) exportMTimes(mtimes map[string]time.Time, ch chan<- if c.mtime != nil { mtime = *c.mtime } - ch <- prometheus.MustNewConstMetric(mtimeDesc, prometheus.GaugeValue, mtime, filename) + ch <- prometheus.MustNewConstMetric(c.MtimeDesc, prometheus.GaugeValue, mtime, filename) } } } @@ -259,14 +290,14 @@ func (cr carriageReturnFilteringReader) Read(p []byte) (int, error) { return pi, err } -// Update implements the Collector interface. -func (c *textFileCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +// Collect implements the Collector interface. +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { errorMetric := 0.0 - var mtimes = map[string]time.Time{} + mtimes := map[string]time.Time{} // Create empty metricFamily slice here and append parsedFamilies to it inside the loop. // Once loop is complete, raise error if any duplicates are present. // This will ensure that duplicate metrics are correctly detected between multiple .prom files. - var metricFamilies = []*dto.MetricFamily{} + metricFamilies := []*dto.MetricFamily{} // Iterate over files and accumulate their metrics. for _, directory := range strings.Split(c.directories, ",") { @@ -320,7 +351,7 @@ func (c *textFileCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Met // Export if there were errors. ch <- prometheus.MustNewConstMetric( prometheus.NewDesc( - prometheus.BuildFQName(Namespace, "textfile", "scrape_error"), + prometheus.BuildFQName(types.Namespace, "textfile", "scrape_error"), "1 if there was an error opening or reading a file, 0 otherwise", nil, nil, ), diff --git a/collector/textfile_test.go b/pkg/collector/textfile/textfile_test.go similarity index 64% rename from collector/textfile_test.go rename to pkg/collector/textfile/textfile_test.go index a398a4daa9..8857abd91c 100644 --- a/collector/textfile_test.go +++ b/pkg/collector/textfile/textfile_test.go @@ -1,21 +1,14 @@ -package collector +package textfile import ( - "fmt" "io" - "os" "strings" "testing" "github.com/dimchansky/utfbom" - "github.com/go-kit/log" - - "github.com/prometheus/client_golang/prometheus" dto "github.com/prometheus/client_model/go" ) -var baseDir = "../tools/textfile-test" - func TestCRFilter(t *testing.T) { sr := strings.NewReader("line 1\r\nline 2") cr := carriageReturnFilteringReader{r: sr} @@ -159,73 +152,3 @@ func TestDuplicateMetricEntry(t *testing.T) { t.Errorf("Unexpected duplicate found in differentValues") } } - -func TestMultipleDirectories(t *testing.T) { - testDir := baseDir + "/multiple-dirs" - testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir) - collector := &textFileCollector{ - logger: log.NewLogfmtLogger(os.Stdout), - directories: testDirs, - } - scrapeContext, err := PrepareScrapeContext([]string{"textfile_test"}) - if err != nil { - t.Errorf("Unexpected error %s", err) - } - metrics := make(chan prometheus.Metric) - got := "" - go func() { - for { - var metric dto.Metric - val := <-metrics - err := val.Write(&metric) - if err != nil { - t.Errorf("Unexpected error %s", err) - } - got += metric.String() - } - }() - err = collector.Collect(scrapeContext, metrics) - if err != nil { - t.Errorf("Unexpected error %s", err) - } - for _, f := range []string{"dir1", "dir2", "dir3", "dir3sub"} { - if !strings.Contains(got, f) { - t.Errorf("Unexpected output %s: %q", f, got) - } - } -} - -func TestDuplicateFileName(t *testing.T) { - testDir := baseDir + "/duplicate-filename" - collector := &textFileCollector{ - logger: log.NewLogfmtLogger(os.Stdout), - directories: testDir, - } - scrapeContext, err := PrepareScrapeContext([]string{"textfile_test"}) - if err != nil { - t.Errorf("Unexpected error %s", err) - } - metrics := make(chan prometheus.Metric) - got := "" - go func() { - for { - var metric dto.Metric - val := <-metrics - err := val.Write(&metric) - if err != nil { - t.Errorf("Unexpected error %s", err) - } - got += metric.String() - } - }() - err = collector.Collect(scrapeContext, metrics) - if err != nil { - t.Errorf("Unexpected error %s", err) - } - if !strings.Contains(got, "file") { - t.Errorf("Unexpected output %q", got) - } - if strings.Contains(got, "sub_file") { - t.Errorf("Unexpected output %q", got) - } -} diff --git a/pkg/collector/textfile/textfile_test_test.go b/pkg/collector/textfile/textfile_test_test.go new file mode 100644 index 0000000000..19131710b2 --- /dev/null +++ b/pkg/collector/textfile/textfile_test_test.go @@ -0,0 +1,99 @@ +package textfile_test + +import ( + "fmt" + "os" + "strings" + "testing" + + "github.com/stretchr/testify/require" + + "github.com/prometheus-community/windows_exporter/pkg/collector" + "github.com/prometheus-community/windows_exporter/pkg/collector/textfile" + "github.com/prometheus-community/windows_exporter/pkg/types" + + "github.com/go-kit/log" + "github.com/prometheus/client_golang/prometheus" + dto "github.com/prometheus/client_model/go" +) + +var baseDir = "../../../tools/textfile-test" + +func TestMultipleDirectories(t *testing.T) { + testDir := baseDir + "/multiple-dirs" + testDirs := fmt.Sprintf("%[1]s/dir1,%[1]s/dir2,%[1]s/dir3", testDir) + + textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ + TextFileDirectories: testDirs, + }) + + collectors := collector.New(map[string]types.Collector{textfile.Name: textfileCollector}) + require.NoError(t, collectors.Build()) + + scrapeContext, err := collectors.PrepareScrapeContext() + if err != nil { + t.Errorf("Unexpected error %s", err) + } + metrics := make(chan prometheus.Metric) + got := "" + go func() { + for { + var metric dto.Metric + val := <-metrics + err := val.Write(&metric) + if err != nil { + t.Errorf("Unexpected error %s", err) + } + got += metric.String() + } + }() + + err = textfileCollector.Collect(scrapeContext, metrics) + if err != nil { + t.Errorf("Unexpected error %s", err) + } + + for _, f := range []string{"dir1", "dir2", "dir3", "dir3sub"} { + if !strings.Contains(got, f) { + t.Errorf("Unexpected output %s: %q", f, got) + } + } +} + +func TestDuplicateFileName(t *testing.T) { + testDir := baseDir + "/duplicate-filename" + textfileCollector := textfile.New(log.NewLogfmtLogger(os.Stdout), &textfile.Config{ + TextFileDirectories: testDir, + }) + + collectors := collector.New(map[string]types.Collector{textfile.Name: textfileCollector}) + require.NoError(t, collectors.Build()) + + scrapeContext, err := collectors.PrepareScrapeContext() + if err != nil { + t.Errorf("Unexpected error %s", err) + } + metrics := make(chan prometheus.Metric) + got := "" + go func() { + for { + var metric dto.Metric + val := <-metrics + err := val.Write(&metric) + if err != nil { + t.Errorf("Unexpected error %s", err) + } + got += metric.String() + } + }() + err = textfileCollector.Collect(scrapeContext, metrics) + if err != nil { + t.Errorf("Unexpected error %s", err) + } + if !strings.Contains(got, "file") { + t.Errorf("Unexpected output %q", got) + } + if strings.Contains(got, "sub_file") { + t.Errorf("Unexpected output %q", got) + } +} diff --git a/collector/thermalzone.go b/pkg/collector/thermalzone/thermalzone.go similarity index 50% rename from collector/thermalzone.go rename to pkg/collector/thermalzone/thermalzone.go index 459dae4fc0..6e57e1a46e 100644 --- a/collector/thermalzone.go +++ b/pkg/collector/thermalzone/thermalzone.go @@ -1,16 +1,26 @@ -package collector +//go:build windows + +package thermalzone import ( "errors" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A thermalZoneCollector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics -type thermalZoneCollector struct { +const Name = "thermalzone" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_Counters_ThermalZoneInformation metrics +type collector struct { logger log.Logger PercentPassiveLimit *prometheus.Desc @@ -18,41 +28,59 @@ type thermalZoneCollector struct { ThrottleReasons *prometheus.Desc } -// newThermalZoneCollector ... -func newThermalZoneCollector(logger log.Logger) (Collector, error) { - const subsystem = "thermalzone" - return &thermalZoneCollector{ - logger: log.With(logger, "collector", subsystem), - Temperature: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "temperature_celsius"), - "(Temperature)", - []string{ - "name", - }, - nil, - ), - PercentPassiveLimit: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "percent_passive_limit"), - "(PercentPassiveLimit)", - []string{ - "name", - }, - nil, - ), - ThrottleReasons: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "throttle_reasons"), - "(ThrottleReasons)", - []string{ - "name", - }, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.Temperature = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "temperature_celsius"), + "(Temperature)", + []string{ + "name", + }, + nil, + ) + c.PercentPassiveLimit = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "percent_passive_limit"), + "(PercentPassiveLimit)", + []string{ + "name", + }, + nil, + ) + c.ThrottleReasons = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "throttle_reasons"), + "(ThrottleReasons)", + []string{ + "name", + }, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *thermalZoneCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collect(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting thermalzone metrics", "desc", desc, "err", err) return err @@ -70,9 +98,9 @@ type Win32_PerfRawData_Counters_ThermalZoneInformation struct { ThrottleReasons uint32 } -func (c *thermalZoneCollector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collect(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_Counters_ThermalZoneInformation - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -83,7 +111,7 @@ func (c *thermalZoneCollector) collect(ch chan<- prometheus.Metric) (*prometheus } for _, info := range dst { - //Divide by 10 and subtract 273.15 to convert decikelvin to celsius + // Divide by 10 and subtract 273.15 to convert decikelvin to celsius ch <- prometheus.MustNewConstMetric( c.Temperature, prometheus.GaugeValue, diff --git a/pkg/collector/thermalzone/thermalzone_test.go b/pkg/collector/thermalzone/thermalzone_test.go new file mode 100644 index 0000000000..b86fa4ae75 --- /dev/null +++ b/pkg/collector/thermalzone/thermalzone_test.go @@ -0,0 +1,12 @@ +package thermalzone_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/thermalzone" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, thermalzone.Name, thermalzone.NewWithFlags) +} diff --git a/pkg/collector/time/time.go b/pkg/collector/time/time.go new file mode 100644 index 0000000000..8b6888b556 --- /dev/null +++ b/pkg/collector/time/time.go @@ -0,0 +1,158 @@ +//go:build windows + +package time + +import ( + "errors" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/winversion" + "github.com/prometheus/client_golang/prometheus" +) + +const Name = "time" + +type Config struct{} + +var ConfigDefaults = Config{} + +// collector is a Prometheus collector for Perflib counter metrics +type collector struct { + logger log.Logger + + ClockFrequencyAdjustmentPPBTotal *prometheus.Desc + ComputedTimeOffset *prometheus.Desc + NTPClientTimeSourceCount *prometheus.Desc + NTPRoundtripDelay *prometheus.Desc + NTPServerIncomingRequestsTotal *prometheus.Desc + NTPServerOutgoingResponsesTotal *prometheus.Desc +} + +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{"Windows Time Service"}, nil +} + +func (c *collector) Build() error { + if winversion.WindowsVersionFloat <= 6.1 { + return errors.New("Windows version older than Server 2016 detected. The time collector will not run and should be disabled via CLI flags or configuration file") + } + + c.ClockFrequencyAdjustmentPPBTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clock_frequency_adjustment_ppb_total"), + "Total adjustment made to the local system clock frequency by W32Time in Parts Per Billion (PPB) units.", + nil, + nil, + ) + c.ComputedTimeOffset = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "computed_time_offset_seconds"), + "Absolute time offset between the system clock and the chosen time source, in seconds", + nil, + nil, + ) + c.NTPClientTimeSourceCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ntp_client_time_sources"), + "Active number of NTP Time sources being used by the client", + nil, + nil, + ) + c.NTPRoundtripDelay = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ntp_round_trip_delay_seconds"), + "Roundtrip delay experienced by the NTP client in receiving a response from the server for the most recent request, in seconds", + nil, + nil, + ) + c.NTPServerOutgoingResponsesTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ntp_server_outgoing_responses_total"), + "Total number of requests responded to by NTP server", + nil, + nil, + ) + c.NTPServerIncomingRequestsTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "ntp_server_incoming_requests_total"), + "Total number of requests received by NTP server", + nil, + nil, + ) + return nil +} + +// Collect sends the metric values for each metric +// to the provided prometheus Metric channel. +func (c *collector) Collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) error { + if desc, err := c.collect(ctx, ch); err != nil { + _ = level.Error(c.logger).Log("failed collecting time metrics", "desc", desc, "err", err) + return err + } + return nil +} + +// Perflib "Windows Time Service" +type windowsTime struct { + ClockFrequencyAdjustmentPPBTotal float64 `perflib:"Clock Frequency Adjustment (ppb)"` + ComputedTimeOffset float64 `perflib:"Computed Time Offset"` + NTPClientTimeSourceCount float64 `perflib:"NTP Client Time Source Count"` + NTPRoundtripDelay float64 `perflib:"NTP Roundtrip Delay"` + NTPServerIncomingRequestsTotal float64 `perflib:"NTP Server Incoming Requests"` + NTPServerOutgoingResponsesTotal float64 `perflib:"NTP Server Outgoing Responses"` +} + +func (c *collector) collect(ctx *types.ScrapeContext, ch chan<- prometheus.Metric) (*prometheus.Desc, error) { + var dst []windowsTime // Single-instance class, array is required but will have single entry. + if err := perflib.UnmarshalObject(ctx.PerfObjects["Windows Time Service"], &dst, c.logger); err != nil { + return nil, err + } + + ch <- prometheus.MustNewConstMetric( + c.ClockFrequencyAdjustmentPPBTotal, + prometheus.CounterValue, + dst[0].ClockFrequencyAdjustmentPPBTotal, + ) + ch <- prometheus.MustNewConstMetric( + c.ComputedTimeOffset, + prometheus.GaugeValue, + dst[0].ComputedTimeOffset/1000000, // microseconds -> seconds + ) + ch <- prometheus.MustNewConstMetric( + c.NTPClientTimeSourceCount, + prometheus.GaugeValue, + dst[0].NTPClientTimeSourceCount, + ) + ch <- prometheus.MustNewConstMetric( + c.NTPRoundtripDelay, + prometheus.GaugeValue, + dst[0].NTPRoundtripDelay/1000000, // microseconds -> seconds + ) + ch <- prometheus.MustNewConstMetric( + c.NTPServerIncomingRequestsTotal, + prometheus.CounterValue, + dst[0].NTPServerIncomingRequestsTotal, + ) + ch <- prometheus.MustNewConstMetric( + c.NTPServerOutgoingResponsesTotal, + prometheus.CounterValue, + dst[0].NTPServerOutgoingResponsesTotal, + ) + return nil, nil +} diff --git a/pkg/collector/time/time_test.go b/pkg/collector/time/time_test.go new file mode 100644 index 0000000000..b122bcae84 --- /dev/null +++ b/pkg/collector/time/time_test.go @@ -0,0 +1,12 @@ +package time_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/time" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, time.Name, time.NewWithFlags) +} diff --git a/collector/vmware.go b/pkg/collector/vmware/vmware.go similarity index 53% rename from collector/vmware.go rename to pkg/collector/vmware/vmware.go index c7039a52a2..08737e78d7 100644 --- a/collector/vmware.go +++ b/pkg/collector/vmware/vmware.go @@ -1,19 +1,27 @@ //go:build windows -// +build windows -package collector +package vmware import ( "errors" + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A VmwareCollector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics -type VmwareCollector struct { +const Name = "vmware" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI Win32_PerfRawData_vmGuestLib_VMem/Win32_PerfRawData_vmGuestLib_VCPU metrics +type collector struct { logger log.Logger MemActive *prometheus.Desc @@ -38,132 +46,150 @@ type VmwareCollector struct { HostProcessorSpeedMHz *prometheus.Desc } -// newVmwareCollector constructs a new VmwareCollector -func newVmwareCollector(logger log.Logger) (Collector, error) { - const subsystem = "vmware" - return &VmwareCollector{ - logger: log.With(logger, "collector", subsystem), - MemActive: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_active_bytes"), - "(MemActiveMB)", - nil, - nil, - ), - MemBallooned: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_ballooned_bytes"), - "(MemBalloonedMB)", - nil, - nil, - ), - MemLimit: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_limit_bytes"), - "(MemLimitMB)", - nil, - nil, - ), - MemMapped: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_mapped_bytes"), - "(MemMappedMB)", - nil, - nil, - ), - MemOverhead: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_overhead_bytes"), - "(MemOverheadMB)", - nil, - nil, - ), - MemReservation: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_reservation_bytes"), - "(MemReservationMB)", - nil, - nil, - ), - MemShared: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_shared_bytes"), - "(MemSharedMB)", - nil, - nil, - ), - MemSharedSaved: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_shared_saved_bytes"), - "(MemSharedSavedMB)", - nil, - nil, - ), - MemShares: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_shares"), - "(MemShares)", - nil, - nil, - ), - MemSwapped: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_swapped_bytes"), - "(MemSwappedMB)", - nil, - nil, - ), - MemTargetSize: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_target_size_bytes"), - "(MemTargetSizeMB)", - nil, - nil, - ), - MemUsed: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "mem_used_bytes"), - "(MemUsedMB)", - nil, - nil, - ), - - CpuLimitMHz: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_limit_mhz"), - "(CpuLimitMHz)", - nil, - nil, - ), - CpuReservationMHz: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_reservation_mhz"), - "(CpuReservationMHz)", - nil, - nil, - ), - CpuShares: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_shares"), - "(CpuShares)", - nil, - nil, - ), - CpuStolenTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_stolen_seconds_total"), - "(CpuStolenMs)", - nil, - nil, - ), - CpuTimeTotal: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cpu_time_seconds_total"), - "(CpuTimePercents)", - nil, - nil, - ), - EffectiveVMSpeedMHz: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "effective_vm_speed_mhz"), - "(EffectiveVMSpeedMHz)", - nil, - nil, - ), - HostProcessorSpeedMHz: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "host_processor_speed_mhz"), - "(HostProcessorSpeedMHz)", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.MemActive = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_active_bytes"), + "(MemActiveMB)", + nil, + nil, + ) + c.MemBallooned = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_ballooned_bytes"), + "(MemBalloonedMB)", + nil, + nil, + ) + c.MemLimit = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_limit_bytes"), + "(MemLimitMB)", + nil, + nil, + ) + c.MemMapped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_mapped_bytes"), + "(MemMappedMB)", + nil, + nil, + ) + c.MemOverhead = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_overhead_bytes"), + "(MemOverheadMB)", + nil, + nil, + ) + c.MemReservation = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_reservation_bytes"), + "(MemReservationMB)", + nil, + nil, + ) + c.MemShared = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_shared_bytes"), + "(MemSharedMB)", + nil, + nil, + ) + c.MemSharedSaved = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_shared_saved_bytes"), + "(MemSharedSavedMB)", + nil, + nil, + ) + c.MemShares = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_shares"), + "(MemShares)", + nil, + nil, + ) + c.MemSwapped = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_swapped_bytes"), + "(MemSwappedMB)", + nil, + nil, + ) + c.MemTargetSize = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_target_size_bytes"), + "(MemTargetSizeMB)", + nil, + nil, + ) + c.MemUsed = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "mem_used_bytes"), + "(MemUsedMB)", + nil, + nil, + ) + + c.CpuLimitMHz = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_limit_mhz"), + "(CpuLimitMHz)", + nil, + nil, + ) + c.CpuReservationMHz = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_reservation_mhz"), + "(CpuReservationMHz)", + nil, + nil, + ) + c.CpuShares = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_shares"), + "(CpuShares)", + nil, + nil, + ) + c.CpuStolenTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_stolen_seconds_total"), + "(CpuStolenMs)", + nil, + nil, + ) + c.CpuTimeTotal = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cpu_time_seconds_total"), + "(CpuTimePercents)", + nil, + nil, + ) + c.EffectiveVMSpeedMHz = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "effective_vm_speed_mhz"), + "(EffectiveVMSpeedMHz)", + nil, + nil, + ) + c.HostProcessorSpeedMHz = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "host_processor_speed_mhz"), + "(HostProcessorSpeedMHz)", + nil, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *VmwareCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectMem(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting vmware memory metrics", "desc", desc, "err", err) return err @@ -200,9 +226,9 @@ type Win32_PerfRawData_vmGuestLib_VCPU struct { HostProcessorSpeedMHz uint64 } -func (c *VmwareCollector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectMem(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_vmGuestLib_VMem - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -289,9 +315,9 @@ func mbToBytes(mb uint64) float64 { return float64(mb * 1024 * 1024) } -func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []Win32_PerfRawData_vmGuestLib_VCPU - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -320,13 +346,13 @@ func (c *VmwareCollector) collectCpu(ch chan<- prometheus.Metric) (*prometheus.D ch <- prometheus.MustNewConstMetric( c.CpuStolenTotal, prometheus.CounterValue, - float64(dst[0].CpuStolenMs)*ticksToSecondsScaleFactor, + float64(dst[0].CpuStolenMs)*perflib.TicksToSecondScaleFactor, ) ch <- prometheus.MustNewConstMetric( c.CpuTimeTotal, prometheus.CounterValue, - float64(dst[0].CpuTimePercents)*ticksToSecondsScaleFactor, + float64(dst[0].CpuTimePercents)*perflib.TicksToSecondScaleFactor, ) ch <- prometheus.MustNewConstMetric( diff --git a/pkg/collector/vmware/vmware_test.go b/pkg/collector/vmware/vmware_test.go new file mode 100644 index 0000000000..8257f48752 --- /dev/null +++ b/pkg/collector/vmware/vmware_test.go @@ -0,0 +1,12 @@ +package vmware_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/vmware" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, vmware.Name, vmware.NewWithFlags) +} diff --git a/collector/vmware_blast.go b/pkg/collector/vmware_blast/vmware_blast.go similarity index 63% rename from collector/vmware_blast.go rename to pkg/collector/vmware_blast/vmware_blast.go index 46563c4e37..64ff9b0296 100644 --- a/collector/vmware_blast.go +++ b/pkg/collector/vmware_blast/vmware_blast.go @@ -1,16 +1,23 @@ //go:build windows -// +build windows -package collector +package vmware_blast import ( + "github.com/alecthomas/kingpin/v2" "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/wmi" "github.com/prometheus/client_golang/prometheus" - "github.com/yusufpapurcu/wmi" ) -// A vmwareBlastCollector is a Prometheus collector for WMI metrics: +const Name = "vmware_blast" + +type Config struct{} + +var ConfigDefaults = Config{} + +// A collector is a Prometheus collector for WMI metrics: // win32_PerfRawData_Counters_VMwareBlastAudioCounters // win32_PerfRawData_Counters_VMwareBlastCDRCounters // win32_PerfRawData_Counters_VMwareBlastClipboardCounters @@ -24,7 +31,7 @@ import ( // win32_PerfRawData_Counters_VMwareBlastUSBCounters // win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters -type vmwareBlastCollector struct { +type collector struct { logger log.Logger AudioReceivedBytes *prometheus.Desc @@ -109,442 +116,460 @@ type vmwareBlastCollector struct { WindowsMediaMMRTransmittedPackets *prometheus.Desc } -// newVmwareBlastCollector constructs a new vmwareBlastCollector -func newVmwareBlastCollector(logger log.Logger) (Collector, error) { - const subsystem = "vmware_blast" - return &vmwareBlastCollector{ - logger: log.With(logger, "collector", subsystem), - AudioReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_received_bytes_total"), - "(AudioReceivedBytes)", - nil, - nil, - ), - AudioReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_received_packets_total"), - "(AudioReceivedPackets)", - nil, - nil, - ), - AudioTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_transmitted_bytes_total"), - "(AudioTransmittedBytes)", - nil, - nil, - ), - AudioTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "audio_transmitted_packets_total"), - "(AudioTransmittedPackets)", - nil, - nil, - ), - - CDRReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cdr_received_bytes_total"), - "(CDRReceivedBytes)", - nil, - nil, - ), - CDRReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cdr_received_packets_total"), - "(CDRReceivedPackets)", - nil, - nil, - ), - CDRTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cdr_transmitted_bytes_total"), - "(CDRTransmittedBytes)", - nil, - nil, - ), - CDRTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "cdr_transmitted_packets_total"), - "(CDRTransmittedPackets)", - nil, - nil, - ), - - ClipboardReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clipboard_received_bytes_total"), - "(ClipboardReceivedBytes)", - nil, - nil, - ), - ClipboardReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clipboard_received_packets_total"), - "(ClipboardReceivedPackets)", - nil, - nil, - ), - ClipboardTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clipboard_transmitted_bytes_total"), - "(ClipboardTransmittedBytes)", - nil, - nil, - ), - ClipboardTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "clipboard_transmitted_packets_total"), - "(ClipboardTransmittedPackets)", - nil, - nil, - ), - - HTML5MMRReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "html5_mmr_received_bytes_total"), - "(HTML5MMRReceivedBytes)", - nil, - nil, - ), - HTML5MMRReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "html5_mmr_received_packets_total"), - "(HTML5MMRReceivedPackets)", - nil, - nil, - ), - HTML5MMRTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "html5_mmr_transmitted_bytes_total"), - "(HTML5MMRTransmittedBytes)", - nil, - nil, - ), - HTML5MMRTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "html5_mmr_transmitted_packets_total"), - "(HTML5MMRTransmittedPackets)", - nil, - nil, - ), - - ImagingDirtyFramesPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_dirty_frames_per_second"), - "(ImagingDirtyFramesPerSecond)", - nil, - nil, - ), - ImagingFBCRate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_fbc_rate"), - "(ImagingFBCRate)", - nil, - nil, - ), - ImagingFramesPerSecond: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_frames_per_second"), - "(ImagingFramesPerSecond)", - nil, - nil, - ), - ImagingPollRate: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_poll_rate"), - "(ImagingPollRate)", - nil, - nil, - ), - ImagingReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_received_bytes_total"), - "(ImagingReceivedBytes)", - nil, - nil, - ), - ImagingReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_received_packets_total"), - "(ImagingReceivedPackets)", - nil, - nil, - ), - ImagingTotalDirtyFrames: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_total_dirty_frames_total"), - "(ImagingTotalDirtyFrames)", - nil, - nil, - ), - ImagingTotalFBC: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_fbc_total"), - "(ImagingTotalFBC)", - nil, - nil, - ), - ImagingTotalFrames: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_frames_total"), - "(ImagingTotalFrames)", - nil, - nil, - ), - ImagingTotalPoll: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_poll_total"), - "(ImagingTotalPoll)", - nil, - nil, - ), - ImagingTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_transmitted_bytes_total"), - "(ImagingTransmittedBytes)", - nil, - nil, - ), - ImagingTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "imaging_transmitted_packets_total"), - "(ImagingTransmittedPackets)", - nil, - nil, - ), - - RTAVReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rtav_received_bytes_total"), - "(RTAVReceivedBytes)", - nil, - nil, - ), - RTAVReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rtav_received_packets_total"), - "(RTAVReceivedPackets)", - nil, - nil, - ), - RTAVTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rtav_transmitted_bytes_total"), - "(RTAVTransmittedBytes)", - nil, - nil, - ), - RTAVTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "rtav_transmitted_packets_total"), - "(RTAVTransmittedPackets)", - nil, - nil, - ), - - SerialPortandScannerReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "serial_port_and_scanner_received_bytes_total"), - "(SerialPortandScannerReceivedBytes)", - nil, - nil, - ), - SerialPortandScannerReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "serial_port_and_scanner_received_packets_total"), - "(SerialPortandScannerReceivedPackets)", - nil, - nil, - ), - SerialPortandScannerTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "serial_port_and_scanner_transmitted_bytes_total"), - "(SerialPortandScannerTransmittedBytes)", - nil, - nil, - ), - SerialPortandScannerTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "serial_port_and_scanner_transmitted_packets_total"), - "(SerialPortandScannerTransmittedPackets)", - nil, - nil, - ), - - SessionAutomaticReconnectCount: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_automatic_reconnect_count_total"), - "(SessionAutomaticReconnectCount)", - nil, - nil, - ), - SessionCumulativeReceivedBytesOverTCP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_cumlative_received_bytes_over_tcp_total"), - "(SessionCumulativeReceivedBytesOverTCP)", - nil, - nil, - ), - SessionCumulativeReceivedBytesOverUDP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_cumlative_received_bytes_over_udp_total"), - "(SessionCumulativeReceivedBytesOverUDP)", - nil, - nil, - ), - SessionCumulativeTransmittedBytesOverTCP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_cumlative_transmitted_bytes_over_tcp_total"), - "(SessionCumulativeTransmittedBytesOverTCP)", - nil, - nil, - ), - SessionCumulativeTransmittedBytesOverUDP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_cumlative_transmitted_bytes_over_udp_total"), - "(SessionCumulativeTransmittedBytesOverUDP)", - nil, - nil, - ), - SessionEstimatedBandwidthUplink: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_estimated_bandwidth_uplink"), - "(SessionEstimatedBandwidthUplink)", - nil, - nil, - ), - SessionInstantaneousReceivedBytesOverTCP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_instantaneous_received_bytes_over_tcp_total"), - "(SessionInstantaneousReceivedBytesOverTCP)", - nil, - nil, - ), - SessionInstantaneousReceivedBytesOverUDP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_instantaneous_received_bytes_over_udp_total"), - "(SessionInstantaneousReceivedBytesOverUDP)", - nil, - nil, - ), - SessionInstantaneousTransmittedBytesOverTCP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_instantaneous_transmitted_bytes_over_tcp_total"), - "(SessionInstantaneousTransmittedBytesOverTCP)", - nil, - nil, - ), - SessionInstantaneousTransmittedBytesOverUDP: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_instantaneous_transmitted_bytes_over_udp_total"), - "(SessionInstantaneousTransmittedBytesOverUDP)", - nil, - nil, - ), - SessionJitterUplink: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_jitter_uplink"), - "(SessionJitterUplink)", - nil, - nil, - ), - SessionPacketLossUplink: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_packet_loss_uplink"), - "(SessionPacketLossUplink)", - nil, - nil, - ), - SessionReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_received_bytes_total"), - "(SessionReceivedBytes)", - nil, - nil, - ), - SessionReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_received_packets_total"), - "(SessionReceivedPackets)", - nil, - nil, - ), - SessionRTT: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_rtt"), - "(SessionRTT)", - nil, - nil, - ), - SessionTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_transmitted_bytes_total"), - "(SessionTransmittedBytes)", - nil, - nil, - ), - SessionTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "session_transmitted_packets_total"), - "(SessionTransmittedPackets)", - nil, - nil, - ), - - SkypeforBusinessControlReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "skype_for_business_control_received_bytes_total"), - "(SkypeforBusinessControlReceivedBytes)", - nil, - nil, - ), - SkypeforBusinessControlReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "skype_for_business_control_received_packets_total"), - "(SkypeforBusinessControlReceivedPackets)", - nil, - nil, - ), - SkypeforBusinessControlTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "skype_for_business_control_transmitted_bytes_total"), - "(SkypeforBusinessControlTransmittedBytes)", - nil, - nil, - ), - SkypeforBusinessControlTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "skype_for_business_control_transmitted_packets_total"), - "(SkypeforBusinessControlTransmittedPackets)", - nil, - nil, - ), - - ThinPrintReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "thinprint_received_bytes_total"), - "(ThinPrintReceivedBytes)", - nil, - nil, - ), - ThinPrintReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "thinprint_received_packets_total"), - "(ThinPrintReceivedPackets)", - nil, - nil, - ), - ThinPrintTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "thinprint_transmitted_bytes_total"), - "(ThinPrintTransmittedBytes)", - nil, - nil, - ), - ThinPrintTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "thinprint_transmitted_packets_total"), - "(ThinPrintTransmittedPackets)", - nil, - nil, - ), - - USBReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_received_bytes_total"), - "(USBReceivedBytes)", - nil, - nil, - ), - USBReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_received_packets_total"), - "(USBReceivedPackets)", - nil, - nil, - ), - USBTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_transmitted_bytes_total"), - "(USBTransmittedBytes)", - nil, - nil, - ), - USBTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "usb_transmitted_packets_total"), - "(USBTransmittedPackets)", - nil, - nil, - ), - - WindowsMediaMMRReceivedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "windows_media_mmr_received_bytes_total"), - "(WindowsMediaMMRReceivedBytes)", - nil, - nil, - ), - WindowsMediaMMRReceivedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "windows_media_mmr_received_packets_total"), - "(WindowsMediaMMRReceivedPackets)", - nil, - nil, - ), - WindowsMediaMMRTransmittedBytes: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "windows_media_mmr_transmitted_bytes_total"), - "(WindowsMediaMMRTransmittedBytes)", - nil, - nil, - ), - WindowsMediaMMRTransmittedPackets: prometheus.NewDesc( - prometheus.BuildFQName(Namespace, subsystem, "windows_media_mmr_transmitted_packets_total"), - "(WindowsMediaMMRTransmittedPackets)", - nil, - nil, - ), - }, nil +func New(logger log.Logger, _ *Config) types.Collector { + c := &collector{} + c.SetLogger(logger) + return c +} + +func NewWithFlags(_ *kingpin.Application) types.Collector { + return &collector{} +} + +func (c *collector) GetName() string { + return Name +} + +func (c *collector) SetLogger(logger log.Logger) { + c.logger = log.With(logger, "collector", Name) +} + +func (c *collector) GetPerfCounter() ([]string, error) { + return []string{}, nil +} + +func (c *collector) Build() error { + c.AudioReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_received_bytes_total"), + "(AudioReceivedBytes)", + nil, + nil, + ) + c.AudioReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_received_packets_total"), + "(AudioReceivedPackets)", + nil, + nil, + ) + c.AudioTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_transmitted_bytes_total"), + "(AudioTransmittedBytes)", + nil, + nil, + ) + c.AudioTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "audio_transmitted_packets_total"), + "(AudioTransmittedPackets)", + nil, + nil, + ) + + c.CDRReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cdr_received_bytes_total"), + "(CDRReceivedBytes)", + nil, + nil, + ) + c.CDRReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cdr_received_packets_total"), + "(CDRReceivedPackets)", + nil, + nil, + ) + c.CDRTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cdr_transmitted_bytes_total"), + "(CDRTransmittedBytes)", + nil, + nil, + ) + c.CDRTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "cdr_transmitted_packets_total"), + "(CDRTransmittedPackets)", + nil, + nil, + ) + + c.ClipboardReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clipboard_received_bytes_total"), + "(ClipboardReceivedBytes)", + nil, + nil, + ) + c.ClipboardReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clipboard_received_packets_total"), + "(ClipboardReceivedPackets)", + nil, + nil, + ) + c.ClipboardTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clipboard_transmitted_bytes_total"), + "(ClipboardTransmittedBytes)", + nil, + nil, + ) + c.ClipboardTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "clipboard_transmitted_packets_total"), + "(ClipboardTransmittedPackets)", + nil, + nil, + ) + + c.HTML5MMRReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "html5_mmr_received_bytes_total"), + "(HTML5MMRReceivedBytes)", + nil, + nil, + ) + c.HTML5MMRReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "html5_mmr_received_packets_total"), + "(HTML5MMRReceivedPackets)", + nil, + nil, + ) + c.HTML5MMRTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "html5_mmr_transmitted_bytes_total"), + "(HTML5MMRTransmittedBytes)", + nil, + nil, + ) + c.HTML5MMRTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "html5_mmr_transmitted_packets_total"), + "(HTML5MMRTransmittedPackets)", + nil, + nil, + ) + + c.ImagingDirtyFramesPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_dirty_frames_per_second"), + "(ImagingDirtyFramesPerSecond)", + nil, + nil, + ) + c.ImagingFBCRate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_fbc_rate"), + "(ImagingFBCRate)", + nil, + nil, + ) + c.ImagingFramesPerSecond = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_frames_per_second"), + "(ImagingFramesPerSecond)", + nil, + nil, + ) + c.ImagingPollRate = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_poll_rate"), + "(ImagingPollRate)", + nil, + nil, + ) + c.ImagingReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_received_bytes_total"), + "(ImagingReceivedBytes)", + nil, + nil, + ) + c.ImagingReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_received_packets_total"), + "(ImagingReceivedPackets)", + nil, + nil, + ) + c.ImagingTotalDirtyFrames = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_total_dirty_frames_total"), + "(ImagingTotalDirtyFrames)", + nil, + nil, + ) + c.ImagingTotalFBC = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_fbc_total"), + "(ImagingTotalFBC)", + nil, + nil, + ) + c.ImagingTotalFrames = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_frames_total"), + "(ImagingTotalFrames)", + nil, + nil, + ) + c.ImagingTotalPoll = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_poll_total"), + "(ImagingTotalPoll)", + nil, + nil, + ) + c.ImagingTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_transmitted_bytes_total"), + "(ImagingTransmittedBytes)", + nil, + nil, + ) + c.ImagingTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "imaging_transmitted_packets_total"), + "(ImagingTransmittedPackets)", + nil, + nil, + ) + + c.RTAVReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rtav_received_bytes_total"), + "(RTAVReceivedBytes)", + nil, + nil, + ) + c.RTAVReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rtav_received_packets_total"), + "(RTAVReceivedPackets)", + nil, + nil, + ) + c.RTAVTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rtav_transmitted_bytes_total"), + "(RTAVTransmittedBytes)", + nil, + nil, + ) + c.RTAVTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "rtav_transmitted_packets_total"), + "(RTAVTransmittedPackets)", + nil, + nil, + ) + + c.SerialPortandScannerReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "serial_port_and_scanner_received_bytes_total"), + "(SerialPortandScannerReceivedBytes)", + nil, + nil, + ) + c.SerialPortandScannerReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "serial_port_and_scanner_received_packets_total"), + "(SerialPortandScannerReceivedPackets)", + nil, + nil, + ) + c.SerialPortandScannerTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "serial_port_and_scanner_transmitted_bytes_total"), + "(SerialPortandScannerTransmittedBytes)", + nil, + nil, + ) + c.SerialPortandScannerTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "serial_port_and_scanner_transmitted_packets_total"), + "(SerialPortandScannerTransmittedPackets)", + nil, + nil, + ) + + c.SessionAutomaticReconnectCount = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_automatic_reconnect_count_total"), + "(SessionAutomaticReconnectCount)", + nil, + nil, + ) + c.SessionCumulativeReceivedBytesOverTCP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_cumlative_received_bytes_over_tcp_total"), + "(SessionCumulativeReceivedBytesOverTCP)", + nil, + nil, + ) + c.SessionCumulativeReceivedBytesOverUDP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_cumlative_received_bytes_over_udp_total"), + "(SessionCumulativeReceivedBytesOverUDP)", + nil, + nil, + ) + c.SessionCumulativeTransmittedBytesOverTCP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_cumlative_transmitted_bytes_over_tcp_total"), + "(SessionCumulativeTransmittedBytesOverTCP)", + nil, + nil, + ) + c.SessionCumulativeTransmittedBytesOverUDP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_cumlative_transmitted_bytes_over_udp_total"), + "(SessionCumulativeTransmittedBytesOverUDP)", + nil, + nil, + ) + c.SessionEstimatedBandwidthUplink = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_estimated_bandwidth_uplink"), + "(SessionEstimatedBandwidthUplink)", + nil, + nil, + ) + c.SessionInstantaneousReceivedBytesOverTCP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_instantaneous_received_bytes_over_tcp_total"), + "(SessionInstantaneousReceivedBytesOverTCP)", + nil, + nil, + ) + c.SessionInstantaneousReceivedBytesOverUDP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_instantaneous_received_bytes_over_udp_total"), + "(SessionInstantaneousReceivedBytesOverUDP)", + nil, + nil, + ) + c.SessionInstantaneousTransmittedBytesOverTCP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_instantaneous_transmitted_bytes_over_tcp_total"), + "(SessionInstantaneousTransmittedBytesOverTCP)", + nil, + nil, + ) + c.SessionInstantaneousTransmittedBytesOverUDP = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_instantaneous_transmitted_bytes_over_udp_total"), + "(SessionInstantaneousTransmittedBytesOverUDP)", + nil, + nil, + ) + c.SessionJitterUplink = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_jitter_uplink"), + "(SessionJitterUplink)", + nil, + nil, + ) + c.SessionPacketLossUplink = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_packet_loss_uplink"), + "(SessionPacketLossUplink)", + nil, + nil, + ) + c.SessionReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_received_bytes_total"), + "(SessionReceivedBytes)", + nil, + nil, + ) + c.SessionReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_received_packets_total"), + "(SessionReceivedPackets)", + nil, + nil, + ) + c.SessionRTT = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_rtt"), + "(SessionRTT)", + nil, + nil, + ) + c.SessionTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_transmitted_bytes_total"), + "(SessionTransmittedBytes)", + nil, + nil, + ) + c.SessionTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "session_transmitted_packets_total"), + "(SessionTransmittedPackets)", + nil, + nil, + ) + + c.SkypeforBusinessControlReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "skype_for_business_control_received_bytes_total"), + "(SkypeforBusinessControlReceivedBytes)", + nil, + nil, + ) + c.SkypeforBusinessControlReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "skype_for_business_control_received_packets_total"), + "(SkypeforBusinessControlReceivedPackets)", + nil, + nil, + ) + c.SkypeforBusinessControlTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "skype_for_business_control_transmitted_bytes_total"), + "(SkypeforBusinessControlTransmittedBytes)", + nil, + nil, + ) + c.SkypeforBusinessControlTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "skype_for_business_control_transmitted_packets_total"), + "(SkypeforBusinessControlTransmittedPackets)", + nil, + nil, + ) + + c.ThinPrintReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "thinprint_received_bytes_total"), + "(ThinPrintReceivedBytes)", + nil, + nil, + ) + c.ThinPrintReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "thinprint_received_packets_total"), + "(ThinPrintReceivedPackets)", + nil, + nil, + ) + c.ThinPrintTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "thinprint_transmitted_bytes_total"), + "(ThinPrintTransmittedBytes)", + nil, + nil, + ) + c.ThinPrintTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "thinprint_transmitted_packets_total"), + "(ThinPrintTransmittedPackets)", + nil, + nil, + ) + + c.USBReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_received_bytes_total"), + "(USBReceivedBytes)", + nil, + nil, + ) + c.USBReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_received_packets_total"), + "(USBReceivedPackets)", + nil, + nil, + ) + c.USBTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_transmitted_bytes_total"), + "(USBTransmittedBytes)", + nil, + nil, + ) + c.USBTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "usb_transmitted_packets_total"), + "(USBTransmittedPackets)", + nil, + nil, + ) + + c.WindowsMediaMMRReceivedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "windows_media_mmr_received_bytes_total"), + "(WindowsMediaMMRReceivedBytes)", + nil, + nil, + ) + c.WindowsMediaMMRReceivedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "windows_media_mmr_received_packets_total"), + "(WindowsMediaMMRReceivedPackets)", + nil, + nil, + ) + c.WindowsMediaMMRTransmittedBytes = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "windows_media_mmr_transmitted_bytes_total"), + "(WindowsMediaMMRTransmittedBytes)", + nil, + nil, + ) + c.WindowsMediaMMRTransmittedPackets = prometheus.NewDesc( + prometheus.BuildFQName(types.Namespace, Name, "windows_media_mmr_transmitted_packets_total"), + "(WindowsMediaMMRTransmittedPackets)", + nil, + nil, + ) + return nil } // Collect sends the metric values for each metric // to the provided prometheus Metric channel. -func (c *vmwareBlastCollector) Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) error { +func (c *collector) Collect(_ *types.ScrapeContext, ch chan<- prometheus.Metric) error { if desc, err := c.collectAudio(ch); err != nil { _ = level.Error(c.logger).Log("failed collecting vmware blast audio metrics", "desc", desc, "err", err) return err @@ -701,9 +726,9 @@ type win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters struct { TransmittedPackets uint32 } -func (c *vmwareBlastCollector) collectAudio(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectAudio(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastAudioCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -740,9 +765,9 @@ func (c *vmwareBlastCollector) collectAudio(ch chan<- prometheus.Metric) (*prome return nil, nil } -func (c *vmwareBlastCollector) collectCdr(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectCdr(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastCDRCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -779,9 +804,9 @@ func (c *vmwareBlastCollector) collectCdr(ch chan<- prometheus.Metric) (*prometh return nil, nil } -func (c *vmwareBlastCollector) collectClipboard(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectClipboard(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastClipboardCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -818,9 +843,9 @@ func (c *vmwareBlastCollector) collectClipboard(ch chan<- prometheus.Metric) (*p return nil, nil } -func (c *vmwareBlastCollector) collectHtml5Mmr(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectHtml5Mmr(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastHTML5MMRcounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -857,9 +882,9 @@ func (c *vmwareBlastCollector) collectHtml5Mmr(ch chan<- prometheus.Metric) (*pr return nil, nil } -func (c *vmwareBlastCollector) collectImaging(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectImaging(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastImagingCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -944,9 +969,9 @@ func (c *vmwareBlastCollector) collectImaging(ch chan<- prometheus.Metric) (*pro return nil, nil } -func (c *vmwareBlastCollector) collectRtav(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectRtav(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastRTAVCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -983,9 +1008,9 @@ func (c *vmwareBlastCollector) collectRtav(ch chan<- prometheus.Metric) (*promet return nil, nil } -func (c *vmwareBlastCollector) collectSerialPortandScanner(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectSerialPortandScanner(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastSerialPortandScannerCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1022,9 +1047,9 @@ func (c *vmwareBlastCollector) collectSerialPortandScanner(ch chan<- prometheus. return nil, nil } -func (c *vmwareBlastCollector) collectSession(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectSession(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastSessionCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1139,9 +1164,9 @@ func (c *vmwareBlastCollector) collectSession(ch chan<- prometheus.Metric) (*pro return nil, nil } -func (c *vmwareBlastCollector) collectSkypeforBusinessControl(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectSkypeforBusinessControl(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastSkypeforBusinessControlCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1178,9 +1203,9 @@ func (c *vmwareBlastCollector) collectSkypeforBusinessControl(ch chan<- promethe return nil, nil } -func (c *vmwareBlastCollector) collectThinPrint(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectThinPrint(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastThinPrintCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1217,9 +1242,9 @@ func (c *vmwareBlastCollector) collectThinPrint(ch chan<- prometheus.Metric) (*p return nil, nil } -func (c *vmwareBlastCollector) collectUsb(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectUsb(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastUSBCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } @@ -1256,9 +1281,9 @@ func (c *vmwareBlastCollector) collectUsb(ch chan<- prometheus.Metric) (*prometh return nil, nil } -func (c *vmwareBlastCollector) collectWindowsMediaMmr(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { +func (c *collector) collectWindowsMediaMmr(ch chan<- prometheus.Metric) (*prometheus.Desc, error) { var dst []win32_PerfRawData_Counters_VMwareBlastWindowsMediaMMRCounters - q := queryAll(&dst, c.logger) + q := wmi.QueryAll(&dst, c.logger) if err := wmi.Query(q, &dst); err != nil { return nil, err } diff --git a/pkg/collector/vmware_blast/vmware_blast_test.go b/pkg/collector/vmware_blast/vmware_blast_test.go new file mode 100644 index 0000000000..f0aa664f99 --- /dev/null +++ b/pkg/collector/vmware_blast/vmware_blast_test.go @@ -0,0 +1,12 @@ +package vmware_blast_test + +import ( + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/collector/vmware_blast" + "github.com/prometheus-community/windows_exporter/pkg/testutils" +) + +func BenchmarkCollector(b *testing.B) { + testutils.FuncBenchmarkCollector(b, vmware_blast.Name, vmware_blast.NewWithFlags) +} diff --git a/config/config.go b/pkg/config/config.go similarity index 100% rename from config/config.go rename to pkg/config/config.go diff --git a/config/flatten.go b/pkg/config/flatten.go similarity index 100% rename from config/flatten.go rename to pkg/config/flatten.go diff --git a/config/flatten_test.go b/pkg/config/flatten_test.go similarity index 100% rename from config/flatten_test.go rename to pkg/config/flatten_test.go diff --git a/headers/netapi32/netapi32.go b/pkg/headers/netapi32/netapi32.go similarity index 100% rename from headers/netapi32/netapi32.go rename to pkg/headers/netapi32/netapi32.go diff --git a/headers/psapi/psapi.go b/pkg/headers/psapi/psapi.go similarity index 100% rename from headers/psapi/psapi.go rename to pkg/headers/psapi/psapi.go diff --git a/headers/sysinfoapi/sysinfoapi.go b/pkg/headers/sysinfoapi/sysinfoapi.go similarity index 100% rename from headers/sysinfoapi/sysinfoapi.go rename to pkg/headers/sysinfoapi/sysinfoapi.go diff --git a/initiate/initiate.go b/pkg/initiate/initiate.go similarity index 83% rename from initiate/initiate.go rename to pkg/initiate/initiate.go index b307d0365a..00162dd4df 100644 --- a/initiate/initiate.go +++ b/pkg/initiate/initiate.go @@ -1,4 +1,4 @@ -// This package allows us to initiate Time Sensitive components (Like registering the windows service) as early as possible in the startup process +// Package initiate allows us to initiate Time Sensitive components (Like registering the windows service) as early as possible in the startup process package initiate import ( @@ -19,7 +19,7 @@ type windowsExporterService struct { var logger *eventlog.Log -func (s *windowsExporterService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { +func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (ssec bool, errno uint32) { const cmdsAccepted = svc.AcceptStop | svc.AcceptShutdown changes <- svc.Status{State: svc.StartPending} changes <- svc.Status{State: svc.Running, Accepts: cmdsAccepted} diff --git a/log/eventlog/eventlog.go b/pkg/log/eventlog/eventlog.go similarity index 100% rename from log/eventlog/eventlog.go rename to pkg/log/eventlog/eventlog.go diff --git a/log/flag/flag.go b/pkg/log/flag/flag.go similarity index 96% rename from log/flag/flag.go rename to pkg/log/flag/flag.go index ba48a24828..35d0ab0e29 100644 --- a/log/flag/flag.go +++ b/pkg/log/flag/flag.go @@ -15,7 +15,7 @@ package flag import ( "github.com/alecthomas/kingpin/v2" - "github.com/prometheus-community/windows_exporter/log" + "github.com/prometheus-community/windows_exporter/pkg/log" "github.com/prometheus/common/promlog" promlogflag "github.com/prometheus/common/promlog/flag" ) diff --git a/log/logger.go b/pkg/log/logger.go similarity index 96% rename from log/logger.go rename to pkg/log/logger.go index 94548c8b6e..ba23a4db86 100644 --- a/log/logger.go +++ b/pkg/log/logger.go @@ -7,7 +7,7 @@ import ( "os" "github.com/go-kit/log" - "github.com/prometheus-community/windows_exporter/log/eventlog" + "github.com/prometheus-community/windows_exporter/pkg/log/eventlog" "github.com/prometheus/common/promlog" goeventlog "golang.org/x/sys/windows/svc/eventlog" ) diff --git a/perflib/LICENSE b/pkg/perflib/LICENSE similarity index 100% rename from perflib/LICENSE rename to pkg/perflib/LICENSE diff --git a/perflib/const.go b/pkg/perflib/const.go similarity index 100% rename from perflib/const.go rename to pkg/perflib/const.go diff --git a/perflib/nametable.go b/pkg/perflib/nametable.go similarity index 100% rename from perflib/nametable.go rename to pkg/perflib/nametable.go diff --git a/perflib/perflib.go b/pkg/perflib/perflib.go similarity index 100% rename from perflib/perflib.go rename to pkg/perflib/perflib.go diff --git a/perflib/perflib_test.go b/pkg/perflib/perflib_test.go similarity index 100% rename from perflib/perflib_test.go rename to pkg/perflib/perflib_test.go diff --git a/perflib/raw_types.go b/pkg/perflib/raw_types.go similarity index 100% rename from perflib/raw_types.go rename to pkg/perflib/raw_types.go diff --git a/collector/perflib.go b/pkg/perflib/unmarshal.go similarity index 69% rename from collector/perflib.go rename to pkg/perflib/unmarshal.go index 47f0d5978d..e022f93edb 100644 --- a/collector/perflib.go +++ b/pkg/perflib/unmarshal.go @@ -1,35 +1,21 @@ -package collector +package perflib import ( "fmt" "reflect" - "strconv" "strings" - "github.com/prometheus-community/windows_exporter/perflib" - "github.com/go-kit/log" "github.com/go-kit/log/level" ) -func MapCounterToIndex(name string) string { - return strconv.Itoa(int(perflib.CounterNameTable.LookupIndex(name))) -} - -func getPerflibSnapshot(objNames string) (map[string]*perflib.PerfObject, error) { - objects, err := perflib.QueryPerformanceData(objNames) - if err != nil { - return nil, err - } - - indexed := make(map[string]*perflib.PerfObject) - for _, obj := range objects { - indexed[obj.Name] = obj - } - return indexed, nil -} +// Conversion factors +const ( + TicksToSecondScaleFactor = 1 / 1e7 + WindowsEpoch = 116444736000000000 +) -func unmarshalObject(obj *perflib.PerfObject, vs interface{}, logger log.Logger) error { +func UnmarshalObject(obj *PerfObject, vs interface{}, logger log.Logger) error { if obj == nil { return fmt.Errorf("counter not found") } @@ -52,7 +38,7 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}, logger log.Logger) target := ev.Index(idx) rt := target.Type() - counters := make(map[string]*perflib.PerfCounter, len(instance.Counters)) + counters := make(map[string]*PerfCounter, len(instance.Counters)) for _, ctr := range instance.Counters { if ctr.Def.IsBaseValue && !ctr.Def.IsNanosecondCounter { counters[ctr.Def.Name+"_Base"] = ctr @@ -99,10 +85,10 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}, logger log.Logger) } switch ctr.Def.CounterType { - case perflib.PERF_ELAPSED_TIME: - target.Field(i).SetFloat(float64(ctr.Value-windowsEpoch) / float64(obj.Frequency)) - case perflib.PERF_100NSEC_TIMER, perflib.PERF_PRECISION_100NS_TIMER: - target.Field(i).SetFloat(float64(ctr.Value) * ticksToSecondsScaleFactor) + case PERF_ELAPSED_TIME: + target.Field(i).SetFloat(float64(ctr.Value-WindowsEpoch) / float64(obj.Frequency)) + case PERF_100NSEC_TIMER, PERF_PRECISION_100NS_TIMER: + target.Field(i).SetFloat(float64(ctr.Value) * TicksToSecondScaleFactor) default: target.Field(i).SetFloat(float64(ctr.Value)) } @@ -116,7 +102,7 @@ func unmarshalObject(obj *perflib.PerfObject, vs interface{}, logger log.Logger) return nil } -func counterMapKeys(m map[string]*perflib.PerfCounter) []string { +func counterMapKeys(m map[string]*PerfCounter) []string { keys := make([]string, 0, len(m)) for k := range m { keys = append(keys, k) diff --git a/perflib/utf16.go b/pkg/perflib/utf16.go similarity index 100% rename from perflib/utf16.go rename to pkg/perflib/utf16.go diff --git a/pkg/perflib/utils.go b/pkg/perflib/utils.go new file mode 100644 index 0000000000..bca5011f73 --- /dev/null +++ b/pkg/perflib/utils.go @@ -0,0 +1,22 @@ +package perflib + +import ( + "strconv" +) + +func MapCounterToIndex(name string) string { + return strconv.Itoa(int(CounterNameTable.LookupIndex(name))) +} + +func GetPerflibSnapshot(objNames string) (map[string]*PerfObject, error) { + objects, err := QueryPerformanceData(objNames) + if err != nil { + return nil, err + } + + indexed := make(map[string]*PerfObject) + for _, obj := range objects { + indexed[obj.Name] = obj + } + return indexed, nil +} diff --git a/collector/perflib_test.go b/pkg/perflib/utils_test.go similarity index 65% rename from collector/perflib_test.go rename to pkg/perflib/utils_test.go index ee5fe0db48..d029e63e45 100644 --- a/collector/perflib_test.go +++ b/pkg/perflib/utils_test.go @@ -1,11 +1,9 @@ -package collector +package perflib import ( "reflect" "testing" - "github.com/prometheus-community/windows_exporter/perflib" - "github.com/go-kit/log" ) @@ -18,7 +16,7 @@ type simple struct { func TestUnmarshalPerflib(t *testing.T) { cases := []struct { name string - obj *perflib.PerfObject + obj *PerfObject expectedOutput []simple expectError bool @@ -31,14 +29,14 @@ func TestUnmarshalPerflib(t *testing.T) { }, { name: "Simple", - obj: &perflib.PerfObject{ - Instances: []*perflib.PerfInstance{ + obj: &PerfObject{ + Instances: []*PerfInstance{ { - Counters: []*perflib.PerfCounter{ + Counters: []*PerfCounter{ { - Def: &perflib.PerfCounterDef{ + Def: &PerfCounterDef{ Name: "Something", - CounterType: perflib.PERF_COUNTER_COUNTER, + CounterType: PERF_COUNTER_COUNTER, }, Value: 123, }, @@ -51,21 +49,21 @@ func TestUnmarshalPerflib(t *testing.T) { }, { name: "Multiple properties", - obj: &perflib.PerfObject{ - Instances: []*perflib.PerfInstance{ + obj: &PerfObject{ + Instances: []*PerfInstance{ { - Counters: []*perflib.PerfCounter{ + Counters: []*PerfCounter{ { - Def: &perflib.PerfCounterDef{ + Def: &PerfCounterDef{ Name: "Something", - CounterType: perflib.PERF_COUNTER_COUNTER, + CounterType: PERF_COUNTER_COUNTER, }, Value: 123, }, { - Def: &perflib.PerfCounterDef{ + Def: &PerfCounterDef{ Name: "Something Else", - CounterType: perflib.PERF_COUNTER_COUNTER, + CounterType: PERF_COUNTER_COUNTER, HasSecondValue: true, }, Value: 256, @@ -80,25 +78,25 @@ func TestUnmarshalPerflib(t *testing.T) { }, { name: "Multiple instances", - obj: &perflib.PerfObject{ - Instances: []*perflib.PerfInstance{ + obj: &PerfObject{ + Instances: []*PerfInstance{ { - Counters: []*perflib.PerfCounter{ + Counters: []*PerfCounter{ { - Def: &perflib.PerfCounterDef{ + Def: &PerfCounterDef{ Name: "Something", - CounterType: perflib.PERF_COUNTER_COUNTER, + CounterType: PERF_COUNTER_COUNTER, }, Value: 321, }, }, }, { - Counters: []*perflib.PerfCounter{ + Counters: []*PerfCounter{ { - Def: &perflib.PerfCounterDef{ + Def: &PerfCounterDef{ Name: "Something", - CounterType: perflib.PERF_COUNTER_COUNTER, + CounterType: PERF_COUNTER_COUNTER, }, Value: 231, }, @@ -113,7 +111,7 @@ func TestUnmarshalPerflib(t *testing.T) { for _, c := range cases { t.Run(c.name, func(t *testing.T) { output := make([]simple, 0) - err := unmarshalObject(c.obj, &output, log.NewNopLogger()) + err := UnmarshalObject(c.obj, &output, log.NewNopLogger()) if err != nil && !c.expectError { t.Errorf("Did not expect error, got %q", err) } diff --git a/pkg/testutils/testutils.go b/pkg/testutils/testutils.go new file mode 100644 index 0000000000..8b8fe6d688 --- /dev/null +++ b/pkg/testutils/testutils.go @@ -0,0 +1,38 @@ +//go:build windows + +package testutils + +import ( + "testing" + + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus-community/windows_exporter/pkg/collector" + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus/client_golang/prometheus" + "github.com/stretchr/testify/require" +) + +func FuncBenchmarkCollector(b *testing.B, name string, collectFunc types.CollectorBuilderWithFlags) { + c := collectFunc(kingpin.CommandLine) + collectors := collector.New(map[string]types.Collector{name: c}) + require.NoError(b, collectors.Build()) + collectors.SetLogger(log.NewNopLogger()) + + // Create perflib scrape context. + // Some perflib collectors required a correct context, + // or will fail during benchmark. + scrapeContext, err := collectors.PrepareScrapeContext() + require.NoError(b, err) + + metrics := make(chan prometheus.Metric) + go func() { + for { + <-metrics + } + }() + + for i := 0; i < b.N; i++ { + require.NoError(b, c.Collect(scrapeContext, metrics)) + } +} diff --git a/pkg/types/const.go b/pkg/types/const.go new file mode 100644 index 0000000000..decc07ced4 --- /dev/null +++ b/pkg/types/const.go @@ -0,0 +1,9 @@ +//go:build windows + +package types + +const ( + DefaultCollectors = "cpu,cs,logical_disk,physical_disk,net,os,service,system,textfile" + DefaultCollectorsPlaceholder = "[defaults]" + Namespace = "windows" +) diff --git a/pkg/types/types.go b/pkg/types/types.go new file mode 100644 index 0000000000..42c26e1411 --- /dev/null +++ b/pkg/types/types.go @@ -0,0 +1,29 @@ +//go:build windows + +package types + +import ( + "github.com/alecthomas/kingpin/v2" + "github.com/go-kit/log" + "github.com/prometheus-community/windows_exporter/pkg/perflib" + "github.com/prometheus/client_golang/prometheus" +) + +type CollectorBuilder func(logger log.Logger) Collector +type CollectorBuilderWithFlags func(*kingpin.Application) Collector + +// Collector is the interface a collector has to implement. +type Collector interface { + Build() error + // GetName get the name of the collector + GetName() string + // GetPerfCounter returns the perf counter required by the collector + GetPerfCounter() ([]string, error) + // Collect Get new metrics and expose them via prometheus registry. + Collect(ctx *ScrapeContext, ch chan<- prometheus.Metric) (err error) + SetLogger(logger log.Logger) +} + +type ScrapeContext struct { + PerfObjects map[string]*perflib.PerfObject +} diff --git a/pkg/utils/collector.go b/pkg/utils/collector.go new file mode 100644 index 0000000000..146a53d7a3 --- /dev/null +++ b/pkg/utils/collector.go @@ -0,0 +1,36 @@ +//go:build windows + +package utils + +import ( + "slices" + "sort" + "strings" + + "github.com/prometheus-community/windows_exporter/pkg/types" +) + +// ExpandEnabledChildCollectors used by more complex Collectors where user input specifies enabled child Collectors. +// Splits provided child Collectors and deduplicate. +func ExpandEnabledChildCollectors(enabled string) []string { + result := slices.Compact(strings.Split(enabled, ",")) + // Ensure result is ordered, to prevent test failure + sort.Strings(result) + return result +} + +func ExpandEnabledCollectors(enabled string) []string { + expanded := strings.Replace(enabled, types.DefaultCollectorsPlaceholder, types.DefaultCollectors, -1) + separated := strings.Split(expanded, ",") + unique := map[string]bool{} + for _, s := range separated { + if s != "" { + unique[s] = true + } + } + result := make([]string, 0, len(unique)) + for s := range unique { + result = append(result, s) + } + return result +} diff --git a/pkg/utils/collector_test.go b/pkg/utils/collector_test.go new file mode 100644 index 0000000000..0f524f256c --- /dev/null +++ b/pkg/utils/collector_test.go @@ -0,0 +1,79 @@ +package utils_test + +import ( + "reflect" + "sort" + "strings" + "testing" + + "github.com/prometheus-community/windows_exporter/pkg/types" + "github.com/prometheus-community/windows_exporter/pkg/utils" +) + +func TestExpandChildCollectors(t *testing.T) { + cases := []struct { + name string + input string + expectedOutput []string + }{ + { + name: "simple", + input: "testing1,testing2,testing3", + expectedOutput: []string{"testing1", "testing2", "testing3"}, + }, + { + name: "duplicate", + input: "testing1,testing2,testing2,testing3", + expectedOutput: []string{"testing1", "testing2", "testing3"}, + }, + } + + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + output := utils.ExpandEnabledChildCollectors(c.input) + if !reflect.DeepEqual(output, c.expectedOutput) { + t.Errorf("Output mismatch, expected %+v, got %+v", c.expectedOutput, output) + } + }) + } +} + +func TestExpandEnabled(t *testing.T) { + expansionTests := []struct { + input string + expectedOutput []string + }{ + {"", []string{}}, + // Default case + {"cs,os", []string{"cs", "os"}}, + // Placeholder expansion + {types.DefaultCollectorsPlaceholder, strings.Split(types.DefaultCollectors, ",")}, + // De-duplication + {"cs,cs", []string{"cs"}}, + // De-duplicate placeholder + {types.DefaultCollectorsPlaceholder + "," + types.DefaultCollectorsPlaceholder, strings.Split(types.DefaultCollectors, ",")}, + // Composite case + {"foo," + types.DefaultCollectorsPlaceholder + ",bar", append(strings.Split(types.DefaultCollectors, ","), "foo", "bar")}, + } + + for _, testCase := range expansionTests { + output := utils.ExpandEnabledCollectors(testCase.input) + sort.Strings(output) + + success := true + if len(output) != len(testCase.expectedOutput) { + success = false + } else { + sort.Strings(testCase.expectedOutput) + for idx := range output { + if output[idx] != testCase.expectedOutput[idx] { + success = false + break + } + } + } + if !success { + t.Error("For", testCase.input, "expected", testCase.expectedOutput, "got", output) + } + } +} diff --git a/pkg/utils/utils.go b/pkg/utils/utils.go new file mode 100644 index 0000000000..68ddaa6551 --- /dev/null +++ b/pkg/utils/utils.go @@ -0,0 +1,14 @@ +//go:build windows + +package utils + +func MilliSecToSec(t float64) float64 { + return t / 1000 +} + +func BoolToFloat(b bool) float64 { + if b { + return 1.0 + } + return 0.0 +} diff --git a/pkg/winversion/main.go b/pkg/winversion/main.go new file mode 100644 index 0000000000..d858cf3f9f --- /dev/null +++ b/pkg/winversion/main.go @@ -0,0 +1,44 @@ +//go:build windows + +package winversion + +import ( + "fmt" + "strconv" + + "golang.org/x/sys/windows/registry" +) + +var WindowsVersion string +var WindowsVersionFloat float64 + +func init() { + var err error + WindowsVersion, WindowsVersionFloat, err = GetWindowsVersion() + if err != nil { + panic(err) + } +} + +// GetWindowsVersion reads the version number of the OS from the Registry +// See https://docs.microsoft.com/en-us/windows/desktop/sysinfo/operating-system-version +func GetWindowsVersion() (string, float64, error) { + reg, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) + if err != nil { + return "", 0, fmt.Errorf("couldn't open registry: %w", err) + } + + defer reg.Close() + + windowsVersion, _, err := reg.GetStringValue("CurrentVersion") + if err != nil { + return "", 0, fmt.Errorf("couldn't open registry: %w", err) + } + + windowsVersionFloat, err := strconv.ParseFloat(windowsVersion, 64) + if err != nil { + return "", 0, fmt.Errorf("couldn't open registry: %w", err) + } + + return windowsVersion, windowsVersionFloat, nil +} diff --git a/collector/wmi.go b/pkg/wmi/wmi.go similarity index 52% rename from collector/wmi.go rename to pkg/wmi/wmi.go index 3a9d644585..c46e7b7317 100644 --- a/collector/wmi.go +++ b/pkg/wmi/wmi.go @@ -1,4 +1,4 @@ -package collector +package wmi import ( "bytes" @@ -7,8 +7,24 @@ import ( "github.com/go-kit/log" "github.com/go-kit/log/level" + "github.com/yusufpapurcu/wmi" ) +func InitWbem(logger log.Logger) error { + // This initialization prevents a memory leak on WMF 5+. See + // https://github.com/prometheus-community/windows_exporter/issues/77 and + // linked issues for details. + _ = level.Debug(logger).Log("msg", "Initializing SWbemServices") + s, err := wmi.InitializeSWbemServices(wmi.DefaultClient) + if err != nil { + return err + } + wmi.DefaultClient.AllowMissingFields = true + wmi.DefaultClient.SWbemServicesClient = s + + return nil +} + func className(src interface{}) string { s := reflect.Indirect(reflect.ValueOf(src)) t := s.Type() @@ -18,7 +34,15 @@ func className(src interface{}) string { return t.Name() } -func queryAll(src interface{}, logger log.Logger) string { +func Query(query string, dst interface{}, connectServerArgs ...interface{}) error { + return wmi.Query(query, dst, connectServerArgs...) +} + +func QueryNamespace(query string, dst interface{}, namespace string) error { + return wmi.QueryNamespace(query, dst, namespace) +} + +func QueryAll(src interface{}, logger log.Logger) string { var b bytes.Buffer b.WriteString("SELECT * FROM ") b.WriteString(className(src)) @@ -27,7 +51,7 @@ func queryAll(src interface{}, logger log.Logger) string { return b.String() } -func queryAllForClass(src interface{}, class string, logger log.Logger) string { +func QueryAllForClass(_ interface{}, class string, logger log.Logger) string { var b bytes.Buffer b.WriteString("SELECT * FROM ") b.WriteString(class) @@ -36,7 +60,7 @@ func queryAllForClass(src interface{}, class string, logger log.Logger) string { return b.String() } -func queryAllWhere(src interface{}, where string, logger log.Logger) string { +func QueryAllWhere(src interface{}, where string, logger log.Logger) string { var b bytes.Buffer b.WriteString("SELECT * FROM ") b.WriteString(className(src)) @@ -50,7 +74,7 @@ func queryAllWhere(src interface{}, where string, logger log.Logger) string { return b.String() } -func queryAllForClassWhere(src interface{}, class string, where string, logger log.Logger) string { +func QueryAllForClassWhere(_ interface{}, class string, where string, logger log.Logger) string { var b bytes.Buffer b.WriteString("SELECT * FROM ") b.WriteString(class) diff --git a/collector/wmi_test.go b/pkg/wmi/wmi_test.go similarity index 92% rename from collector/wmi_test.go rename to pkg/wmi/wmi_test.go index 9970245e8b..dc07eacfa8 100644 --- a/collector/wmi_test.go +++ b/pkg/wmi/wmi_test.go @@ -1,4 +1,4 @@ -package collector +package wmi import ( "testing" @@ -13,16 +13,16 @@ type fakeWmiClass struct { var ( mapQueryAll = func(src interface{}, class string, where string) string { - return queryAll(src, log.NewNopLogger()) + return QueryAll(src, log.NewNopLogger()) } mapQueryAllWhere = func(src interface{}, class string, where string) string { - return queryAllWhere(src, where, log.NewNopLogger()) + return QueryAllWhere(src, where, log.NewNopLogger()) } mapQueryAllForClass = func(src interface{}, class string, where string) string { - return queryAllForClass(src, class, log.NewNopLogger()) + return QueryAllForClass(src, class, log.NewNopLogger()) } mapQueryAllForClassWhere = func(src interface{}, class string, where string) string { - return queryAllForClassWhere(src, class, where, log.NewNopLogger()) + return QueryAllForClassWhere(src, class, where, log.NewNopLogger()) } )